summaryrefslogtreecommitdiffstats
path: root/sys/gnu/fs/ext2fs
diff options
context:
space:
mode:
authorstas <stas@FreeBSD.org>2009-06-03 13:25:50 +0000
committerstas <stas@FreeBSD.org>2009-06-03 13:25:50 +0000
commitd6b21c236cf40e78801e968ce969484b4c7bb7c5 (patch)
treefe0d707358b0746653ebd04634b32121b093d58a /sys/gnu/fs/ext2fs
parent7f32f3f2a110cb1bf2681c657d5f47053e23f6c5 (diff)
downloadFreeBSD-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.h88
-rw-r--r--sys/gnu/fs/ext2fs/ext2_fs_sb.h13
-rw-r--r--sys/gnu/fs/ext2fs/ext2_lookup.c5
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c33
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c3
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
OpenPOWER on IntegriCloud