- 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
This commit is contained in:
Stanislav Sedov 2009-06-03 13:25:50 +00:00
parent af0adb8312
commit 22db14d54b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=193377
5 changed files with 76 additions and 68 deletions

View File

@ -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,41 +104,52 @@
*/
#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)
/*
* FreeBSD passes the pointer to the in-core struct with relevant
* fields to EXT2_SB macro when accessing superblock fields.
*/
#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
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
/*
* 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.
*/
/*
* Macro-instructions used to manage several block sizes
*/
#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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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