diff options
Diffstat (limited to 'pcr/grub-legacy/ext4.patch')
-rw-r--r-- | pcr/grub-legacy/ext4.patch | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/pcr/grub-legacy/ext4.patch b/pcr/grub-legacy/ext4.patch new file mode 100644 index 000000000..8a2f9bdb0 --- /dev/null +++ b/pcr/grub-legacy/ext4.patch @@ -0,0 +1,263 @@ +diff -ruNp grub-0.97/stage2/fsys_ext2fs.c grub-0.97-patch/stage2/fsys_ext2fs.c +--- grub-0.97/stage2/fsys_ext2fs.c 2004-08-08 20:19:18.000000000 +0200 ++++ grub-0.97-patch/stage2/fsys_ext2fs.c 2007-12-29 16:25:19.000000000 ++0100 +@@ -51,6 +51,9 @@ typedef unsigned int __u32; + #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) + #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + ++/* Inode flags */ ++#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ ++ + /* include/linux/ext2_fs.h */ + struct ext2_super_block + { +@@ -191,6 +194,42 @@ struct ext2_dir_entry + #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ + ~EXT2_DIR_ROUND) + ++/* linux/ext4_fs_extents.h */ ++/* ++ * This is the extent on-disk structure. ++ * It's used at the bottom of the tree. ++ */ ++struct ext4_extent { ++ __u32 ee_block; /* first logical block extent covers */ ++ __u16 ee_len; /* number of blocks covered by extent */ ++ __u16 ee_start_hi; /* high 16 bits of physical block */ ++ __u32 ee_start; /* low 32 bits of physical block */ ++}; ++ ++/* ++ * This is index on-disk structure. ++ * It's used at all the levels except the bottom. ++ */ ++struct ext4_extent_idx { ++ __u32 ei_block; /* index covers logical blocks from 'block' */ ++ __u32 ei_leaf; /* pointer to the physical block of the next * ++ * level. leaf or next index could be there */ ++ __u16 ei_leaf_hi; /* high 16 bits of physical block */ ++ __u16 ei_unused; ++}; ++ ++/* ++ * Each block (leaves and indexes), even inode-stored has header. ++ */ ++struct ext4_extent_header { ++ __u16 eh_magic; /* probably will support different formats */ ++ __u16 eh_entries; /* number of valid entries */ ++ __u16 eh_max; /* capacity of store in entries */ ++ __u16 eh_depth; /* has tree real underlying blocks? */ ++ __u32 eh_generation; /* generation of the tree */ ++}; ++ ++#define EXT4_EXT_MAGIC 0xf30a + + /* ext2/super.c */ + #define log2(n) ffz(~(n)) +@@ -279,6 +318,26 @@ ext2_rdfsb (int fsblock, int buffer) + EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); + } + ++/* Walk through extents index tree to find the good leaf */ ++static struct ext4_extent_header * ++ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block) ++{ ++ int i; ++ struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1); ++ if (extent_block->eh_magic != EXT4_EXT_MAGIC) ++ return NULL; ++ if (extent_block->eh_depth == 0) ++ return extent_block; ++ for (i = 0; i < extent_block->eh_entries; i++) ++ { ++ if (logical_block < index[i].ei_block) ++ break; ++ } ++ if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1)) ++ return NULL; ++ return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block)); ++} ++ + /* from + ext2/inode.c:ext2_bmap() + */ +--- grub-0.97/stage2/fsys_ext2fs.c~ 2008-12-28 20:19:00.000000000 +0100 ++++ grub-0.97/stage2/fsys_ext2fs.c 2008-12-28 20:19:00.000000000 +0100 +@@ -366,83 +366,106 @@ + } + printf ("logical block %d\n", logical_block); + #endif /* E2DEBUG */ +- +- /* if it is directly pointed to by the inode, return that physical addr */ +- if (logical_block < EXT2_NDIR_BLOCKS) +- { +-#ifdef E2DEBUG +- printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); +- printf ("returning %d\n", INODE->i_block[logical_block]); +-#endif /* E2DEBUG */ +- return INODE->i_block[logical_block]; +- } +- /* else */ +- logical_block -= EXT2_NDIR_BLOCKS; +- /* try the indirect block */ +- if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) ++ /* standard ext2 inode */ ++ if (!(INODE->i_flags & EXT4_EXTENTS_FL)) + { +- if (mapblock1 != 1 +- && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) +- { +- errnum = ERR_FSYS_CORRUPT; +- return -1; +- } +- mapblock1 = 1; +- return ((__u32 *) DATABLOCK1)[logical_block]; +- } +- /* else */ +- logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); +- /* now try the double indirect block */ +- if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) +- { +- int bnum; +- if (mapblock1 != 2 +- && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) +- { +- errnum = ERR_FSYS_CORRUPT; +- return -1; +- } +- mapblock1 = 2; +- if ((bnum = (((__u32 *) DATABLOCK1) +- [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) +- != mapblock2 +- && !ext2_rdfsb (bnum, DATABLOCK2)) +- { +- errnum = ERR_FSYS_CORRUPT; +- return -1; +- } +- mapblock2 = bnum; ++ /* if it is directly pointed to by the inode, return that physical addr */ ++ if (logical_block < EXT2_NDIR_BLOCKS) ++ { ++#ifdef E2DEBUG ++ printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); ++ printf ("returning %d\n", INODE->i_block[logical_block]); ++#endif /* E2DEBUG */ ++ return INODE->i_block[logical_block]; ++ } ++ /* else */ ++ logical_block -= EXT2_NDIR_BLOCKS; ++ /* try the indirect block */ ++ if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) ++ { ++ if (mapblock1 != 1 ++ && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ mapblock1 = 1; ++ return ((__u32 *) DATABLOCK1)[logical_block]; ++ } ++ /* else */ ++ logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); ++ /* now try the double indirect block */ ++ if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) ++ { ++ int bnum; ++ if (mapblock1 != 2 ++ && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ mapblock1 = 2; ++ if ((bnum = (((__u32 *) DATABLOCK1) ++ [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) ++ != mapblock2 ++ && !ext2_rdfsb (bnum, DATABLOCK2)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ mapblock2 = bnum; ++ return ((__u32 *) DATABLOCK2) ++ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; ++ } ++ /* else */ ++ mapblock2 = -1; ++ logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); ++ if (mapblock1 != 3 ++ && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ mapblock1 = 3; ++ if (!ext2_rdfsb (((__u32 *) DATABLOCK1) ++ [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) ++ * 2)], ++ DATABLOCK2)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ if (!ext2_rdfsb (((__u32 *) DATABLOCK2) ++ [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) ++ & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], ++ DATABLOCK2)) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } + return ((__u32 *) DATABLOCK2) +- [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; +- } +- /* else */ +- mapblock2 = -1; +- logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); +- if (mapblock1 != 3 +- && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) +- { +- errnum = ERR_FSYS_CORRUPT; +- return -1; ++ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; + } +- mapblock1 = 3; +- if (!ext2_rdfsb (((__u32 *) DATABLOCK1) +- [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) +- * 2)], +- DATABLOCK2)) +- { +- errnum = ERR_FSYS_CORRUPT; +- return -1; +- } +- if (!ext2_rdfsb (((__u32 *) DATABLOCK2) +- [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) +- & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], +- DATABLOCK2)) ++ /* inode is in extents format */ ++ else + { ++ int i; ++ struct ext4_extent_header *extent_hdr = ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block); ++ struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1); ++ if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC) ++ { ++ errnum = ERR_FSYS_CORRUPT; ++ return -1; ++ } ++ for (i = 0; i<extent_hdr->eh_entries; i++) ++ { ++ if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15)) ++ return (logical_block - extent[i].ee_block + extent[i].ee_start); ++ } ++ /* We should not arrive here */ + errnum = ERR_FSYS_CORRUPT; + return -1; + } +- return ((__u32 *) DATABLOCK2) +- [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; + } + + /* preconditions: all preconds of ext2fs_block_map */ |