[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] pygrub: add ext4 support
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1260981764 0 # Node ID c6ee21dca84850447797afba0550f0a61d160601 # Parent cbcb3d564b2fb51574b8a1d06cd6e7780839c331 pygrub: add ext4 support This is a port of the following two patches: http://patches.ubuntulinux.org/g/grub/extracted/ext4_support.diff http://patches.ubuntulinux.org/g/grub/extracted/ext4_fix_variable_sized_inodes.diff Signed-off-by: Mark Johnson <mark.johnson@xxxxxxx> --- tools/libfsimage/ext2fs/fsys_ext2fs.c | 237 +++++++++++++++++++++++----------- 1 files changed, 161 insertions(+), 76 deletions(-) diff -r cbcb3d564b2f -r c6ee21dca848 tools/libfsimage/ext2fs/fsys_ext2fs.c --- a/tools/libfsimage/ext2fs/fsys_ext2fs.c Wed Dec 16 12:45:18 2009 +0000 +++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c Wed Dec 16 16:42:44 2009 +0000 @@ -48,6 +48,9 @@ typedef unsigned int __u32; #define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) #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 @@ -234,6 +237,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) grub_log2(n) @@ -311,6 +350,27 @@ ext2_rdfsb (fsi_file_t *ffi, int fsblock 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(fsi_file_t *ffi, 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(ffi, index[i-1].ei_leaf, DATABLOCK1)) + return NULL; + return (ext4_recurse_extent_index(ffi, (struct ext4_extent_header *) DATABLOCK1, logical_block)); +} + + /* from ext2/inode.c:ext2_bmap() */ @@ -319,7 +379,6 @@ static int static int ext2fs_block_map (fsi_file_t *ffi, int logical_block) { - #ifdef E2DEBUG unsigned char *i; for (i = (unsigned char *) INODE; @@ -340,82 +399,106 @@ ext2fs_block_map (fsi_file_t *ffi, int l 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) + if (!(INODE->i_flags & EXT4_EXTENTS_FL)) + { + /* 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 (ffi, 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 (ffi, 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 (ffi, 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 (ffi, INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 3; + if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK1) + [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) + * 2)], + DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + if (!ext2_rdfsb (ffi, ((__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)]; + } + /* inode is in extents format */ + else { -#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 (ffi, 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 (ffi, 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 (ffi, 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 (ffi, INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) - { + int i; + struct ext4_extent_header *extent_hdr = + ext4_recurse_extent_index(ffi, (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; } - mapblock1 = 3; - if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK1) - [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) - * 2)], - DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - if (!ext2_rdfsb (ffi, ((__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)]; } /* preconditions: all preconds of ext2fs_block_map */ @@ -548,6 +631,8 @@ ext2fs_dir (fsi_file_t *ffi, char *dirna int off; /* offset within block of directory entry (off mod blocksize) */ int loc; /* location within a directory */ int blk; /* which data blk within dir entry (off div blocksize) */ + int inodes_per_block; /* number of inodes in each block */ + int inode_offset; /* inode offset in block */ long map; /* fs pointer of a particular block from dir entry */ struct ext2_dir_entry *dp; /* pointer to directory entry */ #ifdef E2DEBUG @@ -583,9 +668,9 @@ ext2fs_dir (fsi_file_t *ffi, char *dirna return 0; } gdp = GROUP_DESC; - ino_blk = gdp[desc].bg_inode_table + - (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) - >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK))); + inodes_per_block = EXT2_BLOCK_SIZE (SUPERBLOCK) / EXT2_INODE_SIZE(SUPERBLOCK); + inode_offset = ((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)); + ino_blk = gdp[desc].bg_inode_table + (inode_offset / inodes_per_block); #ifdef E2DEBUG printf ("inode table fsblock=%d\n", ino_blk); #endif /* E2DEBUG */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |