EXT2FS: support variable inode size.
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 21 Jul 2009 19:39:03 +0000 (12:39 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 21 Jul 2009 19:39:03 +0000 (12:39 -0700)
Obtained-from: FreeBSD
Cherry-picked-from: http://github.com/polachok/dragonflybsd/commit/d8b7a4caaa2724148e95939207977a0730c349b2
Submitted-by: Alexander Polakov
sys/vfs/gnu/ext2fs/ext2_fs.h
sys/vfs/gnu/ext2fs/ext2_fs_sb.h
sys/vfs/gnu/ext2fs/ext2_inode.c
sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c
sys/vfs/gnu/ext2fs/ext2_vfsops.c

index a5e9cd2..2184ba1 100644 (file)
 #else
 # define EXT2_BLOCK_SIZE_BITS(s)       ((s)->s_log_block_size + 10)
 #endif
-#ifdef notyet
-#ifdef __KERNEL__
-#define        EXT2_ADDR_PER_BLOCK_BITS(s)     ((s)->u.ext2_sb.s_addr_per_block_bits)
-#define EXT2_INODE_SIZE(s)             ((s)->u.ext2_sb.s_inode_size)
-#define EXT2_FIRST_INO(s)              ((s)->u.ext2_sb.s_first_ino)
+#if defined(__KERNEL__) || defined _KERNEL
+#define        EXT2_ADDR_PER_BLOCK_BITS(s)     ((s)->s_addr_per_block_bits)
+#define EXT2_INODE_SIZE(s)             ((s)->s_inode_size)
+#define EXT2_FIRST_INO(s)              ((s)->s_first_ino)
 #else
 #define EXT2_INODE_SIZE(s)     (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
                                 EXT2_GOOD_OLD_INODE_SIZE : \
                                 EXT2_GOOD_OLD_FIRST_INO : \
                                 (s)->s_first_ino)
 #endif
-#else /* !notyet */
 #define        EXT2_INODES_PER_BLOCK(s)        ((s)->s_inodes_per_block)
-/* Should be sizeof(struct ext2_inode): */
-#define EXT2_INODE_SIZE                        128
-#define EXT2_FIRST_INO                 11
-#endif /* notyet */
-
 /*
  * Macro-instructions used to manage fragments
  */
index 85f71bf..a5b9123 100644 (file)
@@ -58,8 +58,12 @@ struct ext2_sb_info {
        struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
        int s_rename_lock;
        unsigned long  s_mount_opt;
+#ifdef notyet
        unsigned short s_resuid;
        unsigned short s_resgid;
+#endif
+    unsigned short s_inode_size;
+    unsigned int s_first_ino;
        unsigned short s_mount_state;
        /* 
           stuff that FFS keeps in its super block or that linux
index f1ad3ac..7eb1799 100644 (file)
@@ -97,7 +97,7 @@ ext2_update(struct vnode *vp, int waitfor)
                brelse(bp);
                return (error);
        }
-       ext2_di2ei( &ip->i_din, (struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
+       ext2_di2ei( &ip->i_din, (struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
            ino_to_fsbo(fs, ip->i_number)));
 /*
        if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
index 9333652..db6e78f 100644 (file)
@@ -214,7 +214,7 @@ ext2_free_inode(struct inode *inode)
 
        sb = inode->i_e2fs;
        lock_super (DEVVP(inode));
-       if (inode->i_number < EXT2_FIRST_INO ||
+       if (inode->i_number < EXT2_FIRST_INO(sb) ||
            inode->i_number > sb->s_es->s_inodes_count) {
                kprintf ("free_inode reserved inode or nonexistent inode");
                unlock_super (DEVVP(inode));
@@ -424,7 +424,7 @@ repeat:
                goto repeat;
        }
        j += i * EXT2_INODES_PER_GROUP(sb) + 1;
-       if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
+       if (j < EXT2_FIRST_INO(sb) || j > es->s_inodes_count) {
                kprintf ( "ext2_new_inode:"
                            "reserved inode or inode > inodes count - "
                            "block_group = %d,inode=%d", i, j);
index e440780..7657238 100644 (file)
@@ -537,7 +537,26 @@ compute_sb_data(struct vnode *devvp, struct ext2_super_block *es,
     V(s_frags_per_group)
     fs->s_inodes_per_group = es->s_inodes_per_group;
     V(s_inodes_per_group)
-    fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE;
+    if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
+        fs->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
+        fs->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+    } else {
+        fs->s_first_ino = es->s_first_ino;
+        fs->s_inode_size = es->s_inode_size;
+        /*
+         * Simple sanity check for superblock inode size value.
+         */
+        if (fs->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
+            fs->s_inode_size > fs->s_blocksize ||
+            (fs->s_inode_size & (fs->s_inode_size - 1)) != 0) {
+            kprintf("EXT2-fs: invalid inode size %d\n",
+                fs->s_inode_size);
+            return (EIO);
+        }
+    }
+    V(s_first_ino)
+    V(s_inode_size)
+    fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs);
     V(s_inodes_per_block)
     fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block;
     V(s_itb_per_group)
@@ -711,7 +730,7 @@ ext2_reload_scan2(struct mount *mp, struct vnode *vp, void *data)
        if (error)
                return (error);
        ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + 
-           EXT2_INODE_SIZE * ino_to_fsbo(info->fs, ip->i_number)), 
+           EXT2_INODE_SIZE(info->fs) * ino_to_fsbo(info->fs, ip->i_number)),
            &ip->i_din);
        brelse(bp);
        return(0);
@@ -1170,7 +1189,7 @@ kprintf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino)));
                return (error);
        }
        /* convert ext2 inode to dinode */
-       ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
+       ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
                        ino_to_fsbo(fs, ino)), &ip->i_din);
        ip->i_block_group = ino_to_cg(fs, ino);
        ip->i_next_alloc_block = 0;