summaryrefslogtreecommitdiffstats
path: root/sys/gnu
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2000-11-03 16:41:48 +0000
committerbde <bde@FreeBSD.org>2000-11-03 16:41:48 +0000
commit2041bf0212fa75c870a9a05751e8cb1e5e7d6ae8 (patch)
treeb3e2046dc7d762fe0184285457f4afd054d39055 /sys/gnu
parenta1750a380142dd6f26bd6d163514bb5f107d1a9b (diff)
downloadFreeBSD-src-2041bf0212fa75c870a9a05751e8cb1e5e7d6ae8.zip
FreeBSD-src-2041bf0212fa75c870a9a05751e8cb1e5e7d6ae8.tar.gz
Support filesystems with the not-so-new "sparse_superblocks" feature.
When this feature is enabled, mke2fs doesn't necessarily allocate a super block and its associated descriptor blocks for every group. The (non-)allocations are reflected in the block bitmap. Since the filesystem code doesn't write to these blocks except for the first superblock, all it has to do to support them is to not count them in ext2_statfs() and not attempt to check them at mount time in ext2_check_blocks_bitmap() (the check has never been enabled in FreeBSD anyway).
Diffstat (limited to 'sys/gnu')
-rw-r--r--sys/gnu/ext2fs/ext2_extern.h2
-rw-r--r--sys/gnu/ext2fs/ext2_fs.h2
-rw-r--r--sys/gnu/ext2fs/ext2_linux_balloc.c36
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c20
-rw-r--r--sys/gnu/fs/ext2fs/ext2_extern.h2
-rw-r--r--sys/gnu/fs/ext2fs/ext2_fs.h2
-rw-r--r--sys/gnu/fs/ext2fs/ext2_linux_balloc.c36
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c20
8 files changed, 90 insertions, 30 deletions
diff --git a/sys/gnu/ext2fs/ext2_extern.h b/sys/gnu/ext2fs/ext2_extern.h
index 317f540..b37b3ec 100644
--- a/sys/gnu/ext2fs/ext2_extern.h
+++ b/sys/gnu/ext2fs/ext2_extern.h
@@ -37,6 +37,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
+ * $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
@@ -78,6 +79,7 @@ int ext2_dirempty __P((struct inode *, ino_t, struct ucred *));
int ext2_checkpath __P((struct inode *, struct inode *, struct ucred *));
struct ext2_group_desc * get_group_desc __P((struct mount * ,
unsigned int , struct buf ** ));
+int ext2_group_sparse __P((int group));
void ext2_discard_prealloc __P((struct inode *));
int ext2_inactive __P((struct vop_inactive_args *));
int ext2_new_block __P ((struct mount * mp, unsigned long goal,
diff --git a/sys/gnu/ext2fs/ext2_fs.h b/sys/gnu/ext2fs/ext2_fs.h
index 64aff0d..8d5a56d 100644
--- a/sys/gnu/ext2fs/ext2_fs.h
+++ b/sys/gnu/ext2fs/ext2_fs.h
@@ -509,7 +509,7 @@ struct ext2_super_block {
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#else
-#define EXT2_FEATURE_RO_COMPAT_SUPP 0
+#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
#endif
/*
diff --git a/sys/gnu/ext2fs/ext2_linux_balloc.c b/sys/gnu/ext2fs/ext2_linux_balloc.c
index 817408c..bc5f08d 100644
--- a/sys/gnu/ext2fs/ext2_linux_balloc.c
+++ b/sys/gnu/ext2fs/ext2_linux_balloc.c
@@ -496,6 +496,25 @@ static __inline int block_in_use (unsigned long block,
EXT2_BLOCKS_PER_GROUP(sb), map);
}
+static int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
+int ext2_group_sparse(int group)
+{
+ return (test_root(group, 3) || test_root(group, 5) ||
+ test_root(group, 7));
+}
+
#ifdef unused
static void ext2_check_blocks_bitmap (struct mount * mp)
{
@@ -521,15 +540,20 @@ static void ext2_check_blocks_bitmap (struct mount * mp)
bitmap_nr = load_block_bitmap (mp, i);
bh = sb->s_block_bitmap[bitmap_nr];
- if (!test_bit (0, bh->b_data))
- printf ( "ext2_check_blocks_bitmap: "
- "Superblock in group %d is marked free", i);
-
- for (j = 0; j < desc_blocks; j++)
- if (!test_bit (j + 1, bh->b_data))
+ if (!(es->s_feature_ro_compat &
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+ ext2_group_sparse(i)) {
+ if (!test_bit (0, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
+ "Superblock in group %d "
+ "is marked free", i);
+
+ for (j = 0; j < desc_blocks; j++)
+ if (!test_bit (j + 1, bh->b_data))
+ printf ("ext2_check_blocks_bitmap: "
"Descriptor block #%d in group "
"%d is marked free", j, i);
+ }
if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index bd77f0a..6b147b0 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -846,11 +846,10 @@ ext2_statfs(mp, sbp, p)
struct proc *p;
{
unsigned long overhead;
- unsigned long overhead_per_group;
-
register struct ufsmount *ump;
register struct ext2_sb_info *fs;
register struct ext2_super_block *es;
+ int i, nsb;
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
@@ -862,13 +861,18 @@ ext2_statfs(mp, sbp, p)
/*
* Compute the overhead (FS structures)
*/
- overhead_per_group = 1 /* super block */ +
- fs->s_db_per_group +
- 1 /* block bitmap */ +
- 1 /* inode bitmap */ +
- fs->s_itb_per_group;
+ if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
+ nsb = 0;
+ for (i = 0 ; i < fs->s_groups_count; i++)
+ if (ext2_group_sparse(i))
+ nsb++;
+ } else
+ nsb = fs->s_groups_count;
overhead = es->s_first_data_block +
- fs->s_groups_count * overhead_per_group;
+ /* Superblocks and block group descriptors: */
+ nsb * (1 + fs->s_db_per_group) +
+ /* Inode bitmap, block bitmap, and inode table: */
+ fs->s_groups_count * (1 + 1 + fs->s_itb_per_group);
sbp->f_bsize = EXT2_FRAG_SIZE(fs);
sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
diff --git a/sys/gnu/fs/ext2fs/ext2_extern.h b/sys/gnu/fs/ext2fs/ext2_extern.h
index 317f540..b37b3ec 100644
--- a/sys/gnu/fs/ext2fs/ext2_extern.h
+++ b/sys/gnu/fs/ext2fs/ext2_extern.h
@@ -37,6 +37,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
+ * $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
@@ -78,6 +79,7 @@ int ext2_dirempty __P((struct inode *, ino_t, struct ucred *));
int ext2_checkpath __P((struct inode *, struct inode *, struct ucred *));
struct ext2_group_desc * get_group_desc __P((struct mount * ,
unsigned int , struct buf ** ));
+int ext2_group_sparse __P((int group));
void ext2_discard_prealloc __P((struct inode *));
int ext2_inactive __P((struct vop_inactive_args *));
int ext2_new_block __P ((struct mount * mp, unsigned long goal,
diff --git a/sys/gnu/fs/ext2fs/ext2_fs.h b/sys/gnu/fs/ext2fs/ext2_fs.h
index 64aff0d..8d5a56d 100644
--- a/sys/gnu/fs/ext2fs/ext2_fs.h
+++ b/sys/gnu/fs/ext2fs/ext2_fs.h
@@ -509,7 +509,7 @@ struct ext2_super_block {
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#else
-#define EXT2_FEATURE_RO_COMPAT_SUPP 0
+#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
#endif
/*
diff --git a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c
index 817408c..bc5f08d 100644
--- a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c
+++ b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c
@@ -496,6 +496,25 @@ static __inline int block_in_use (unsigned long block,
EXT2_BLOCKS_PER_GROUP(sb), map);
}
+static int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
+int ext2_group_sparse(int group)
+{
+ return (test_root(group, 3) || test_root(group, 5) ||
+ test_root(group, 7));
+}
+
#ifdef unused
static void ext2_check_blocks_bitmap (struct mount * mp)
{
@@ -521,15 +540,20 @@ static void ext2_check_blocks_bitmap (struct mount * mp)
bitmap_nr = load_block_bitmap (mp, i);
bh = sb->s_block_bitmap[bitmap_nr];
- if (!test_bit (0, bh->b_data))
- printf ( "ext2_check_blocks_bitmap: "
- "Superblock in group %d is marked free", i);
-
- for (j = 0; j < desc_blocks; j++)
- if (!test_bit (j + 1, bh->b_data))
+ if (!(es->s_feature_ro_compat &
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+ ext2_group_sparse(i)) {
+ if (!test_bit (0, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
+ "Superblock in group %d "
+ "is marked free", i);
+
+ for (j = 0; j < desc_blocks; j++)
+ if (!test_bit (j + 1, bh->b_data))
+ printf ("ext2_check_blocks_bitmap: "
"Descriptor block #%d in group "
"%d is marked free", j, i);
+ }
if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index bd77f0a..6b147b0 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c
@@ -846,11 +846,10 @@ ext2_statfs(mp, sbp, p)
struct proc *p;
{
unsigned long overhead;
- unsigned long overhead_per_group;
-
register struct ufsmount *ump;
register struct ext2_sb_info *fs;
register struct ext2_super_block *es;
+ int i, nsb;
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
@@ -862,13 +861,18 @@ ext2_statfs(mp, sbp, p)
/*
* Compute the overhead (FS structures)
*/
- overhead_per_group = 1 /* super block */ +
- fs->s_db_per_group +
- 1 /* block bitmap */ +
- 1 /* inode bitmap */ +
- fs->s_itb_per_group;
+ if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
+ nsb = 0;
+ for (i = 0 ; i < fs->s_groups_count; i++)
+ if (ext2_group_sparse(i))
+ nsb++;
+ } else
+ nsb = fs->s_groups_count;
overhead = es->s_first_data_block +
- fs->s_groups_count * overhead_per_group;
+ /* Superblocks and block group descriptors: */
+ nsb * (1 + fs->s_db_per_group) +
+ /* Inode bitmap, block bitmap, and inode table: */
+ fs->s_groups_count * (1 + 1 + fs->s_itb_per_group);
sbp->f_bsize = EXT2_FRAG_SIZE(fs);
sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
OpenPOWER on IntegriCloud