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" <[email protected]>
> 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
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel