On Sat, Jul 5, 2008 at 7:01 PM, Marco Gerards <[EMAIL PROTECTED]> wrote: >> + grub_printf ("HH\n"); > > Whoops? ;-) > >> + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, >> + "ext2fs doesn't support extents"); > > Why the error? I thought you have added extent support? Doesn't this > mean the extent has another error of some kind?
Hi, Oh, I forget to cleanup the code, here is the new patch. 2008-07-06 Bean <[EMAIL PROTECTED]> * fs/ext2.c (EXT4_EXTENTS_FLAG): New macro. (grub_ext4_extent_header): New structure. (grub_ext4_extent): Likewise. (grub_ext4_extent_idx): Likewise. (grub_ext4_find_leaf): New function. (grub_ext2_read_block): Handle extents. -- Bean
diff --git a/fs/ext2.c b/fs/ext2.c index 22fd272..80e6576 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -86,6 +86,8 @@ #define EXT3_JOURNAL_FLAG_DELETED 4 #define EXT3_JOURNAL_FLAG_LAST_TAG 8 +#define EXT4_EXTENTS_FLAG 0x80000 + /* The ext2 superblock. */ struct grub_ext2_sblock { @@ -226,6 +228,33 @@ struct grub_ext3_journal_sblock grub_uint32_t start; }; +#define EXT4_EXT_MAGIC 0xf30a + +struct grub_ext4_extent_header +{ + grub_uint16_t magic; + grub_uint16_t entries; + grub_uint16_t max; + grub_uint16_t depth; + grub_uint32_t generation; +}; + +struct grub_ext4_extent +{ + grub_uint32_t block; + grub_uint16_t len; + grub_uint16_t start_hi; + grub_uint32_t start; +}; + +struct grub_ext4_extent_idx +{ + grub_uint32_t block; + grub_uint32_t leaf; + grub_uint16_t leaf_hi; + grub_uint16_t unused; +}; + struct grub_fshelp_node { struct grub_ext2_data *data; @@ -262,6 +291,46 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group, sizeof (struct grub_ext2_block_group), (char *) blkgrp); } +static struct grub_ext4_extent_header * +grub_ext4_find_leaf (struct grub_ext2_data *data, + struct grub_ext4_extent_header *ext_block, + grub_uint32_t fileblock) +{ + char buf[EXT2_BLOCK_SIZE(data)]; + struct grub_ext4_extent_idx *index; + + while (1) + { + int i; + grub_disk_addr_t block; + + index = (struct grub_ext4_extent_idx *) (ext_block + 1); + + if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC) + return 0; + + if (ext_block->depth == 0) + return ext_block; + + for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++) + { + if (fileblock < grub_le_to_cpu32(index[i].block)) + break; + } + + if (i == 0) + return 0; + + block = grub_le_to_cpu16 (index[i].leaf_hi); + block = (block << 32) + grub_le_to_cpu32 (index[i].leaf); + if (grub_disk_read (data->disk, + block << LOG2_EXT2_BLOCK_SIZE (data), + 0, sizeof (buf), buf)) + return 0; + + ext_block = (struct grub_ext4_extent_header *) buf; + } +} static grub_disk_addr_t grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) @@ -272,6 +341,38 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) unsigned int blksz = EXT2_BLOCK_SIZE (data); int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); + if (inode->flags & EXT4_EXTENTS_FLAG) + { + struct grub_ext4_extent_header *leaf; + struct grub_ext4_extent *ext; + int i; + + leaf = grub_ext4_find_leaf (data, + (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, + fileblock); + if (! leaf) + { + grub_error (GRUB_ERR_BAD_FS, "invalid extent"); + return -1; + } + + ext = (struct grub_ext4_extent *) (leaf + 1); + for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++) + if ((fileblock >= grub_le_to_cpu32 (ext[i].block)) && + (fileblock < grub_le_to_cpu32 (ext[i].block) + + grub_le_to_cpu16 (ext[i].len)) && + ((grub_le_to_cpu16 (ext[i].len) >> 15) == 0)) + { + grub_disk_addr_t start; + + start = grub_le_to_cpu16 (ext[i].start_hi); + start = (start << 32) + grub_le_to_cpu32 (ext[i].start); + return fileblock - grub_le_to_cpu32 (ext[i].block) + start; + } + + grub_error (GRUB_ERR_BAD_FS, "something wrong with extent"); + return -1; + } /* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel