- 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:
parent
af0adb8312
commit
22db14d54b
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user