From 469327903134dbe076c692e1824d870012bcb5e5 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 21 Jul 2009 12:39:03 -0700 Subject: [PATCH] EXT2FS: support variable inode size. Obtained-from: FreeBSD Cherry-picked-from: http://github.com/polachok/dragonflybsd/commit/d8b7a4caaa2724148e95939207977a0730c349b2 Submitted-by: Alexander Polakov --- sys/vfs/gnu/ext2fs/ext2_fs.h | 15 ++++----------- sys/vfs/gnu/ext2fs/ext2_fs_sb.h | 4 ++++ sys/vfs/gnu/ext2fs/ext2_inode.c | 2 +- sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c | 4 ++-- sys/vfs/gnu/ext2fs/ext2_vfsops.c | 25 ++++++++++++++++++++++--- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/sys/vfs/gnu/ext2fs/ext2_fs.h b/sys/vfs/gnu/ext2fs/ext2_fs.h index a5e9cd2e95..2184ba15ab 100644 --- a/sys/vfs/gnu/ext2fs/ext2_fs.h +++ b/sys/vfs/gnu/ext2fs/ext2_fs.h @@ -135,11 +135,10 @@ #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 : \ @@ -148,13 +147,7 @@ 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 */ diff --git a/sys/vfs/gnu/ext2fs/ext2_fs_sb.h b/sys/vfs/gnu/ext2fs/ext2_fs_sb.h index 85f71bf39c..a5b9123f3d 100644 --- a/sys/vfs/gnu/ext2fs/ext2_fs_sb.h +++ b/sys/vfs/gnu/ext2fs/ext2_fs_sb.h @@ -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 diff --git a/sys/vfs/gnu/ext2fs/ext2_inode.c b/sys/vfs/gnu/ext2fs/ext2_inode.c index f1ad3acede..7eb179918f 100644 --- a/sys/vfs/gnu/ext2fs/ext2_inode.c +++ b/sys/vfs/gnu/ext2fs/ext2_inode.c @@ -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) diff --git a/sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c b/sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c index 93336523e6..db6e78f0c2 100644 --- a/sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c +++ b/sys/vfs/gnu/ext2fs/ext2_linux_ialloc.c @@ -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); diff --git a/sys/vfs/gnu/ext2fs/ext2_vfsops.c b/sys/vfs/gnu/ext2fs/ext2_vfsops.c index e440780fab..7657238553 100644 --- a/sys/vfs/gnu/ext2fs/ext2_vfsops.c +++ b/sys/vfs/gnu/ext2fs/ext2_vfsops.c @@ -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; -- 2.41.0