On Fri, Jul 11, 2008 at 4:39 PM, Felix Zielcke <[EMAIL PROTECTED]> wrote: > From: "Bean" <[EMAIL PROTECTED]> > Sent: Friday, July 11, 2008 10:17 AM > To: "The development of GRUB 2" <grub-devel@gnu.org> > Subject: Re: [PATCH] ext4 extent support > >> Hi, >> >> Is the image empty ? Perhaps you can add a few files to it. Also, you >> can use grub-fstest to check if grub can access it, For example: >> > > Urm, yeah sorry, didn't think that it could be more helpful with files on it > I copied now my /boot to it > Seems like 1,9 MB is too big for the mailing list, message returned > So i just uploaded to rapidshare > > http://rapidshare.com/files/128833892/ext4.img.bz2.html > > But if you like i'll send it to you offlist > >> grub-fstest ext4.img ls / >> grub-fstest ext4.img ls /boot >> grub-fstest ext4.img hex /boot/grub.cfg > > just with ext4.img it didn't worked, it complained about not using an > absolute path > > # grub2/grub-fstest /root/ext4.img ls / > lost+found/ grub/ System.map-2.6.26-rc9 config-2.6.26-rc9 vmlinuz-2.6.26-rc9 > # grub2/grub-fstest /root/ext4.img ls /grub/ > _linux.mod amiga.mod ascii.pff biosdisk.mod bitmap.mod cdboot.img [...] > vbeinfo.mod video.mod > # grub2/grub-fstest /root/ext4.img hex /grub/grub.cfg > 00000000 23 0a 23 20 44 4f 20 4e 4f 54 20 45 44 49 54 20 |#.# DO NOT EDIT > | > 00000010 54 48 49 53 20 46 49 4c 45 0a 23 0a 23 20 49 74 |THIS FILE.#.# > It| > 00000020 20 69 73 20 61 75 74 6f 6d 61 74 69 63 61 6c 6c | is > automaticall| > [...] > 00000470 44 20 2f 65 74 63 2f 67 72 75 62 2e 64 2f 33 30 |D > /etc/grub.d/30| > 00000480 5f 6f 73 2d 70 72 6f 62 65 72 20 23 23 23 0a |_os-prober > ###.| > # grub2/grub-fstest /root/ext4.img hex /vmlinuz-2.6.26-rc9 > grub-fstest: error: read error at offset 0. > # grub2/grub-fstest /root/ext4.img ls /vmlinuz-2.6.26-rc9 > vmlinuz-2.6.26-rc9
Hi, This patch should fix the problem. -- Bean
diff --git a/fs/ext2.c b/fs/ext2.c index 22fd272..d8e1b3e 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,45 @@ 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, char *buf, + struct grub_ext4_extent_header *ext_block, + grub_uint32_t fileblock) +{ + 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, EXT2_BLOCK_SIZE(data), 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 +340,50 @@ 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) + { + char buf[EXT2_BLOCK_SIZE(data)]; + struct grub_ext4_extent_header *leaf; + struct grub_ext4_extent *ext; + int i; + + leaf = grub_ext4_find_leaf (data, buf, + (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)) + break; + } + + if (--i >= 0) + { + fileblock -= grub_le_to_cpu32 (ext[i].block); + if (fileblock >= grub_le_to_cpu16 (ext[i].len)) + return 0; + else + { + 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 + start; + } + } + else + { + 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