diff options
author | stas <stas@FreeBSD.org> | 2009-06-03 13:25:50 +0000 |
---|---|---|
committer | stas <stas@FreeBSD.org> | 2009-06-03 13:25:50 +0000 |
commit | d6b21c236cf40e78801e968ce969484b4c7bb7c5 (patch) | |
tree | fe0d707358b0746653ebd04634b32121b093d58a /sys/gnu/fs/ext2fs | |
parent | 7f32f3f2a110cb1bf2681c657d5f47053e23f6c5 (diff) | |
download | FreeBSD-src-d6b21c236cf40e78801e968ce969484b4c7bb7c5.zip FreeBSD-src-d6b21c236cf40e78801e968ce969484b4c7bb7c5.tar.gz |
- Sync our copies of ext2fs Linux headers to current Linux versions.
Minimize differencies between our ext2fs headers and relevant Linux
versions by using EXT2_SB macro to access the superblock fields. Most
of the differencies in access to these fields are now hidden inside
this macro.
- Rename the s_db_per_group field of ext2fs_sb_info to s_gdb_count
to reflect the similar change in Linux headers. New name also seem
to be more appropriate for this field.
- Use proper types for s_first_inode and s_inode_size in-core superblock
fields. Now they reflec types used in the on-disk superblock version.
- Add support for older filesystem revisions that doesn't have proper
s_first_ino and s_inode_size fields in the on-disk superblock. In these
cases predefined values for these fields are used.
- Add simple sanity checks for s_first_inode and s_inode_size correctness.
Reviewed by: bde (previous version)
MFC after: 2 weeks
Diffstat (limited to 'sys/gnu/fs/ext2fs')
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs.h | 88 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs_sb.h | 13 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_lookup.c | 5 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_vfsops.c | 33 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_vnops.c | 3 |
5 files changed, 75 insertions, 67 deletions
diff --git a/sys/gnu/fs/ext2fs/ext2_fs.h b/sys/gnu/fs/ext2fs/ext2_fs.h index c1d6ffd..8a4081e 100644 --- a/sys/gnu/fs/ext2fs/ext2_fs.h +++ b/sys/gnu/fs/ext2fs/ext2_fs.h @@ -52,6 +52,8 @@ #define umode_t mode_t #define loff_t off_t +#define cpu_to_le32(x) htole32(x) + /* * The second extended filesystem constants/structures */ @@ -87,12 +89,10 @@ #endif /* - * Special inodes numbers + * Special inode numbers */ #define EXT2_BAD_INO 1 /* Bad blocks inode */ #define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_ACL_IDX_INO 3 /* ACL inode */ -#define EXT2_ACL_DATA_INO 4 /* ACL inode */ #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ @@ -104,17 +104,29 @@ */ #define EXT2_SUPER_MAGIC 0xEF53 +#ifdef __KERNEL__ +#include <linux/ext2_fs_sb.h> +static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} +#elif defined(_KERNEL) /* - * Maximal count of links to a file + * FreeBSD passes the pointer to the in-core struct with relevant + * fields to EXT2_SB macro when accessing superblock fields. */ -#define EXT2_LINK_MAX 32000 +#define EXT2_SB(sb) (sb) +#else +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) +#endif /* - * Note: under FreeBSD, the "user" versions of the following macros are - * used (and must be used) in most cases, because ((s)->u.ext2_sb.s_es is - * not accessible. This depends on __KERNEL__ not being defined for - * kernel builds under FreeBSD. + * Maximal count of links to a file */ +#define EXT2_LINK_MAX 32000 /* * Macro-instructions used to manage several block sizes @@ -122,23 +134,22 @@ #define EXT2_MIN_BLOCK_SIZE 1024 #define EXT2_MAX_BLOCK_SIZE 4096 #define EXT2_MIN_BLOCK_LOG_SIZE 10 -#if defined(__KERNEL__) || (defined(__FreeBSD__) && defined(_KERNEL)) +#if defined(__KERNEL__) || defined(_KERNEL) # define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) #else # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) #endif -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) -#ifdef __KERNEL__ +#if defined(__KERNEL__) || defined(_KERNEL) # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) #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) (EXT2_SB(s)->s_addr_per_block_bits) +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) +#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block) #else #define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ EXT2_GOOD_OLD_INODE_SIZE : \ @@ -147,12 +158,6 @@ 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(s) ((s)->s_inode_size) -#define EXT2_FIRST_INO(s) ((s)->s_first_inode) -#endif /* notyet */ /* * Macro-instructions used to manage fragments @@ -160,15 +165,11 @@ #define EXT2_MIN_FRAG_SIZE 1024 #define EXT2_MAX_FRAG_SIZE 4096 #define EXT2_MIN_FRAG_LOG_SIZE 10 -#ifdef __KERNEL__ -# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block) +#if defined(__KERNEL__) || defined(_KERNEL) +# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) #else -# if defined(_KERNEL) && defined(__FreeBSD__) -# define EXT2_FRAG_SIZE(s) ((s)->s_frag_size) -# else # define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) -# endif # define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) #endif @@ -212,11 +213,11 @@ struct ext2_group_desc /* * Macro-instructions used to manage group descriptors */ -#ifdef __KERNEL__ -# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group) -# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block) -# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group) -# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits) +#if defined(__KERNEL__) || defined(_KERNEL) +# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) +# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) +# define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) #else # define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group) # define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) @@ -366,7 +367,7 @@ struct ext2_inode { #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \ +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ EXT2_MOUNT_##opt) /* * Maximal mount counts between two filesystem checks @@ -444,15 +445,6 @@ struct ext2_super_block { __u32 s_reserved[204]; /* Padding to the end of the block */ }; -#ifdef __KERNEL__ -#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -#else -/* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test - * macros from user land. */ -#define EXT2_SB(sb) (sb) -#endif - /* * Codes for operating systems */ @@ -478,11 +470,11 @@ struct ext2_super_block { */ #define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_compat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) ) #define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) ) #define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_incompat & (mask) ) + ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) ) #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 diff --git a/sys/gnu/fs/ext2fs/ext2_fs_sb.h b/sys/gnu/fs/ext2fs/ext2_fs_sb.h index ae5c268..2e3d78f 100644 --- a/sys/gnu/fs/ext2fs/ext2_fs_sb.h +++ b/sys/gnu/fs/ext2fs/ext2_fs_sb.h @@ -60,11 +60,9 @@ struct ext2_sb_info { unsigned long s_blocks_per_group;/* Number of blocks in a group */ unsigned long s_inodes_per_group;/* Number of inodes in a group */ unsigned long s_itb_per_group; /* Number of inode table blocks per group */ - unsigned long s_db_per_group; /* Number of descriptor blocks per group */ + unsigned long s_gdb_count; /* Number of group descriptor blocks */ unsigned long s_desc_per_block; /* Number of group descriptors per block */ unsigned long s_groups_count; /* Number of groups in the fs */ - unsigned long s_first_inode; /* First inode on fs */ - unsigned int s_inode_size; /* Size for inode with extra data */ struct buffer_head * s_sbh; /* Buffer containing the super block */ struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */ struct buffer_head ** s_group_desc; @@ -74,10 +72,13 @@ struct ext2_sb_info { struct buffer_head * s_inode_bitmap[EXT2_MAX_GROUP_LOADED]; unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED]; struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED]; - int s_rename_lock; unsigned long s_mount_opt; - unsigned short s_resuid; - unsigned short s_resgid; +#ifdef notyet + uid_t s_resuid; + gid_t 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/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c index 7788d58..261d85f 100644 --- a/sys/gnu/fs/ext2fs/ext2_lookup.c +++ b/sys/gnu/fs/ext2fs/ext2_lookup.c @@ -46,6 +46,7 @@ #include <sys/namei.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/endian.h> #include <sys/mount.h> #include <sys/vnode.h> #include <sys/malloc.h> @@ -771,7 +772,7 @@ ext2_direnter(ip, dvp, cnp) dp = VTOI(dvp); newdir.inode = ip->i_number; newdir.name_len = cnp->cn_namelen; - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); else @@ -949,7 +950,7 @@ ext2_dirrewrite(dp, ip, cnp) &bp)) != 0) return (error); ep->inode = ip->i_number; - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) ep->file_type = DTTOFT(IFTODT(ip->i_mode)); else diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index c8d79fb..a81994b 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -78,8 +78,8 @@ #include <gnu/fs/ext2fs/fs.h> #include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> #include <gnu/fs/ext2fs/ext2_fs_sb.h> +#include <gnu/fs/ext2fs/ext2_fs.h> static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); static int ext2_mountfs(struct vnode *, struct mount *); @@ -412,7 +412,7 @@ static int compute_sb_data(devvp, es, fs) V(s_fsbtodb) fs->s_qbmask = fs->s_blocksize - 1; V(s_qbmask) - fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es); + fs->s_blocksize_bits = es->s_log_block_size + 10; V(s_blocksize_bits) fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; V(s_frag_size) @@ -425,10 +425,23 @@ static int compute_sb_data(devvp, es, fs) V(s_frags_per_group) fs->s_inodes_per_group = es->s_inodes_per_group; V(s_inodes_per_group) - fs->s_inode_size = es->s_inode_size; - V(s_inode_size) - fs->s_first_inode = es->s_first_ino; - V(s_first_inode); + 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) { + printf("EXT2-fs: invalid inode size %d\n", fs->s_inode_size); + return (EIO); + } + } 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; @@ -443,8 +456,8 @@ static int compute_sb_data(devvp, es, fs) V(s_groups_count) db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / EXT2_DESC_PER_BLOCK(fs); - fs->s_db_per_group = db_count; - V(s_db_per_group) + fs->s_gdb_count = db_count; + V(s_gdb_count) fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *), M_EXT2MNT, M_WAITOK); @@ -761,7 +774,7 @@ ext2_unmount(mp, mntflags) } /* release buffers containing group descriptors */ - for(i = 0; i < fs->s_db_per_group; i++) + for(i = 0; i < fs->s_gdb_count; i++) ULCK_BUF(fs->s_group_desc[i]) bsd_free(fs->s_group_desc, M_EXT2MNT); @@ -839,7 +852,7 @@ ext2_statfs(mp, sbp) nsb = fs->s_groups_count; overhead = es->s_first_data_block + /* Superblocks and block group descriptors: */ - nsb * (1 + fs->s_db_per_group) + + nsb * (1 + fs->s_gdb_count) + /* Inode bitmap, block bitmap, and inode table: */ fs->s_groups_count * (1 + 1 + fs->s_itb_per_group); diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index 1b5023c..248c433 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -52,6 +52,7 @@ #include <sys/stat.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/endian.h> #include <sys/priv.h> #include <sys/proc.h> #include <sys/mount.h> @@ -1185,7 +1186,7 @@ ext2_mkdir(ap) goto bad; /* Initialize directory with "." and ".." from static template. */ - if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, + if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2_FEATURE_INCOMPAT_FILETYPE)) dtp = &mastertemplate; else |