[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

grub: does not support 256 byte inodes on ext3.



Package: grub
Version: 0.97-29
Severity: normal

*** Please type your report below this line ***
Hi

ext3 filesystems with an inode size of 256 byte cannot be read by the 
read-only file system code of grub 0.97-29 (e2fs_stage1_5 can't be loaded).

Following up #463123 "e2fsprogs: grub 0.97 cannot boot ext3 filesystems 
with an inode size of 256 byte", I have reviewed the grub patches by Jesse 
Keating <jkeating@redhat.com> and Eric Sandeen <esandeen@redhat.com> 
staging up for Fedora 9:
http://cvs.fedora.redhat.com/viewcvs/devel/grub/grub-support-256byte-inode.patch?view=markup
which depends upon
http://cvs.fedora.redhat.com/viewcvs/devel/grub/grub-fedora-9.patch?view=markup
and came up with the attached patch, which allows grub(-legacy) 0.97 to 
boot from ext3 partitions with 256 byte inodes.

Even though I understand that grub(-legacy) is in feature freeze (grub2 
does already support booting from ext3 partitions with 256 byte inodes), I 
personally would prefer an update to grub 0.97, given that this issue 
leaves the (newly installed/ moved) system unbootable without any chance 
for manual interaction (grub neither installs and dies without any message)
and that the patch seems to be of reasonable size, while grub2 doesn't seem
to be ready for mass deployment.

The attached patch has been tested on several amd64 and i386 systems of 
varying (ext3) filesystem age and seems to work well with 128 byte and 256 
byte inode sizes.

Regards
	Stefan Lippers-Hollmann

CC'ing debian-boot on request of Robert Millan

-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.24-slh64-smp-1 (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

-- no debconf information
diff -Nrup a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c
--- a/stage2/fsys_ext2fs.c	2004-08-08 20:19:18.000000000 +0200
+++ b/stage2/fsys_ext2fs.c	2008-01-30 14:27:20.000000000 +0100
@@ -79,7 +79,52 @@ struct ext2_super_block
     __u32 s_rev_level;		/* Revision level */
     __u16 s_def_resuid;		/* Default uid for reserved blocks */
     __u16 s_def_resgid;		/* Default gid for reserved blocks */
-    __u32 s_reserved[235];	/* Padding to the end of the block */
+    /*
+     * These fields are for EXT2_DYNAMIC_REV superblocks only.
+     *
+     * Note: the difference between the compatible feature set and
+     * the incompatible feature set is that if there is a bit set
+     * in the incompatible feature set that the kernel doesn't
+     * know about, it should refuse to mount the filesystem.
+     *
+     * e2fsck's requirements are more strict; if it doesn't know
+     * about a feature in either the compatible or incompatible
+     * feature set, it must abort and not try to meddle with
+     * things it doesn't understand...
+     */
+    __u32 s_first_ino;		/* First non-reserved inode */
+    __u16 s_inode_size;		/* size of inode structure */
+    __u16 s_block_group_nr;	/* block group # of this superblock */
+    __u32 s_feature_compat;	/* compatible feature set */
+    __u32 s_feature_incompat;	/* incompatible feature set */
+    __u32 s_feature_ro_compat;	/* readonly-compatible feature set */
+    __u8  s_uuid[16];		/* 128-bit uuid for volume */
+    char  s_volume_name[16];	/* volume name */
+    char  s_last_mounted[64];	/* directory where last mounted */
+    __u32 s_algorithm_usage_bitmap; /* For compression */
+    /*
+     * Performance hints.  Directory preallocation should only
+     * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+     */
+    __u8  s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+    __u8  s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+    __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
+    /*
+     * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
+     */
+    __u8 s_journal_uuid[16];	/* uuid of journal superblock */
+    __u32 s_journal_inum;	/* inode number of journal file */
+    __u32 s_journal_dev;	/* device number of journal file */
+    __u32 s_last_orphan;	/* start of list of inodes to delete */
+    __u32 s_hash_seed[4];	/* HTREE hash seed */
+    __u8  s_def_hash_version;	/* Default hash version to use */
+    __u8  s_jnl_backup_type; 	/* Default type of journal backup */
+    __u16 s_reserved_word_pad;
+    __u32 s_default_mount_opts;
+    __u32 s_first_meta_bg;	/* First metablock group */
+    __u32 s_mkfs_time;		/* When the filesystem was created */
+    __u32 s_jnl_blocks[17]; 	/* Backup of the journal inode */
+    __u32 s_reserved[172];	/* Padding to the end of the block */
   };
 
 struct ext2_group_desc
@@ -218,6 +263,9 @@ struct ext2_dir_entry
 #define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
 #define EXT2_ADDR_PER_BLOCK_BITS(s)		(log2(EXT2_ADDR_PER_BLOCK(s)))
 
+#define EXT2_INODE_SIZE(s)		(SUPERBLOCK->s_inode_size)
+#define EXT2_INODES_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
+
 /* linux/ext2_fs.h */
 #define EXT2_BLOCK_SIZE_BITS(s)        ((s)->s_log_block_size + 10)
 /* kind of from ext2/super.c */
@@ -553,7 +601,7 @@ ext2fs_dir (char *dirname)
       gdp = GROUP_DESC;
       ino_blk = gdp[desc].bg_inode_table +
 	(((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
-	 >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
+	 >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
 #ifdef E2DEBUG
       printf ("inode table fsblock=%d\n", ino_blk);
 #endif /* E2DEBUG */
@@ -565,13 +613,12 @@ ext2fs_dir (char *dirname)
       /* reset indirect blocks! */
       mapblock2 = mapblock1 = -1;
 
-      raw_inode = INODE +
-	((current_ino - 1)
-	 & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
+      raw_inode = (struct ext2_inode *)((char *)INODE +
+	((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
+	EXT2_INODE_SIZE (SUPERBLOCK));
 #ifdef E2DEBUG
       printf ("ipb=%d, sizeof(inode)=%d\n",
-	      (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
-	      sizeof (struct ext2_inode));
+	      EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
       printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
       printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
       for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;

Attachment: signature.asc
Description: This is a digitally signed message part.


Reply to: