Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Jan 2018 21:54:13 +0000 (UTC)
From:      Fedor Uporov <fsu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r328564 - head/sys/fs/ext2fs
Message-ID:  <201801292154.w0TLsDsR008816@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: fsu
Date: Mon Jan 29 21:54:13 2018
New Revision: 328564
URL: https://svnweb.freebsd.org/changeset/base/328564

Log:
  Add flex_bg/meta_bg features RW support.
  
  Reviewed by:    pfg
  MFC after:      6 months
  
  Differential Revision:    https://reviews.freebsd.org/D13964

Modified:
  head/sys/fs/ext2fs/ext2_alloc.c
  head/sys/fs/ext2fs/ext2_vfsops.c
  head/sys/fs/ext2fs/ext2fs.h

Modified: head/sys/fs/ext2fs/ext2_alloc.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_alloc.c	Mon Jan 29 21:16:56 2018	(r328563)
+++ head/sys/fs/ext2fs/ext2_alloc.c	Mon Jan 29 21:54:13 2018	(r328564)
@@ -755,49 +755,68 @@ ext2_hashalloc(struct inode *ip, int cg, long pref, in
 }
 
 static unsigned long
-ext2_cg_num_gdb(struct m_ext2fs *fs, int cg)
+ext2_cg_number_gdb_nometa(struct m_ext2fs *fs, int cg)
 {
-	int gd_per_block, metagroup, first, last;
 
-	gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd);
-	metagroup = cg / gd_per_block;
-	first = metagroup * gd_per_block;
-	last = first + gd_per_block - 1;
+	if (!ext2_cg_has_sb(fs, cg))
+		return (0);
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
-	    metagroup < fs->e2fs->e3fs_first_meta_bg) {
-		if (!ext2_cg_has_sb(fs, cg))
-			return (0);
-		if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
-			return (fs->e2fs->e3fs_first_meta_bg);
-		return (fs->e2fs_gdbcount);
-	}
+	if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
+		return (fs->e2fs->e3fs_first_meta_bg);
 
+	return ((fs->e2fs_gcount + EXT2_DESCS_PER_BLOCK(fs) - 1) /
+	    EXT2_DESCS_PER_BLOCK(fs));
+}
+
+static unsigned long
+ext2_cg_number_gdb_meta(struct m_ext2fs *fs, int cg)
+{
+	unsigned long metagroup;
+	int first, last;
+
+	metagroup = cg / EXT2_DESCS_PER_BLOCK(fs);
+	first = metagroup * EXT2_DESCS_PER_BLOCK(fs);
+	last = first + EXT2_DESCS_PER_BLOCK(fs) - 1;
+
 	if (cg == first || cg == first + 1 || cg == last)
 		return (1);
+
 	return (0);
+}
 
+static unsigned long
+ext2_cg_number_gdb(struct m_ext2fs *fs, int cg)
+{
+	unsigned long first_meta_bg, metagroup;
+
+	first_meta_bg = fs->e2fs->e3fs_first_meta_bg;
+	metagroup = cg / EXT2_DESCS_PER_BLOCK(fs);
+
+	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
+	    metagroup < first_meta_bg)
+		return (ext2_cg_number_gdb_nometa(fs, cg));
+
+	return ext2_cg_number_gdb_meta(fs, cg);
 }
 
 static int
-ext2_num_base_meta_blocks(struct m_ext2fs *fs, int cg)
+ext2_number_base_meta_blocks(struct m_ext2fs *fs, int cg)
 {
-	int num, gd_per_block;
+	int number;
 
-	gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd);
-	num = ext2_cg_has_sb(fs, cg);
+	number = ext2_cg_has_sb(fs, cg);
 
 	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
-	    cg < fs->e2fs->e3fs_first_meta_bg * gd_per_block) {
-		if (num) {
-			num += ext2_cg_num_gdb(fs, cg);
-			num += fs->e2fs->e2fs_reserved_ngdb;
+	    cg < fs->e2fs->e3fs_first_meta_bg * EXT2_DESCS_PER_BLOCK(fs)) {
+		if (number) {
+			number += ext2_cg_number_gdb(fs, cg);
+			number += fs->e2fs->e2fs_reserved_ngdb;
 		}
 	} else {
-		num += ext2_cg_num_gdb(fs, cg);
+		number += ext2_cg_number_gdb(fs, cg);
 	}
-	
-	return (num);
+
+	return (number);
 }
 
 static void
@@ -815,6 +834,20 @@ ext2_mark_bitmap_end(int start_bit, int end_bit, char 
 }
 
 static int
+ext2_get_group_number(struct m_ext2fs *fs, e4fs_daddr_t block)
+{
+
+	return ((block - fs->e2fs->e2fs_first_dblock) / fs->e2fs_bsize);
+}
+
+static int
+ext2_block_in_group(struct m_ext2fs *fs, e4fs_daddr_t block, int cg)
+{
+
+	return ((ext2_get_group_number(fs, block) == cg) ? 1 : 0);
+}
+
+static int
 ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
 {
 	int bit, bit_max, inodes_per_block;
@@ -825,7 +858,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg,
 
 	memset(bp->b_data, 0, fs->e2fs_bsize);
 
-	bit_max = ext2_num_base_meta_blocks(fs, cg);
+	bit_max = ext2_number_base_meta_blocks(fs, cg);
 	if ((bit_max >> 3) >= fs->e2fs_bsize)
 		return (EINVAL);
 
@@ -837,12 +870,12 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg,
 	/* Set bits for block and inode bitmaps, and inode table. */
 	tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
 	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-	    cg == dtogd(fs, tmp))
+	    ext2_block_in_group(fs, tmp, cg))
 		setbit(bp->b_data, tmp - start);
 
 	tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
 	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-	    cg == dtogd(fs, tmp))
+	    ext2_block_in_group(fs, tmp, cg))
 		setbit(bp->b_data, tmp - start);
 
 	tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]);
@@ -850,7 +883,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg,
 	while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) +
 	    fs->e2fs->e2fs_ipg / inodes_per_block ) {
 		if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-		    cg == dtogd(fs, tmp))
+		    ext2_block_in_group(fs, tmp, cg))
 			setbit(bp->b_data, tmp - start);
 		tmp++;
 	}

Modified: head/sys/fs/ext2fs/ext2_vfsops.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_vfsops.c	Mon Jan 29 21:16:56 2018	(r328563)
+++ head/sys/fs/ext2fs/ext2_vfsops.c	Mon Jan 29 21:54:13 2018	(r328564)
@@ -154,7 +154,8 @@ ext2_mount(struct mount *mp)
 			if (mp->mnt_flag & MNT_FORCE)
 				flags |= FORCECLOSE;
 			error = ext2_flushfiles(mp, flags, td);
-			if (error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) {
+			if (error == 0 && fs->e2fs_wasvalid &&
+			    ext2_cgupdate(ump, MNT_WAIT) == 0) {
 				fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
 				ext2_sbupdate(ump, MNT_WAIT);
 			}
@@ -318,6 +319,36 @@ ext2_check_sb_compat(struct ext2fs *es, struct cdev *d
 	return (0);
 }
 
+static e4fs_daddr_t
+cg_location(struct m_ext2fs *fs, int number)
+{
+	int cg, descpb, logical_sb, has_super = 0;
+
+	/*
+	 * Adjust logical superblock block number.
+	 * Godmar thinks: if the blocksize is greater than 1024, then
+	 * the superblock is logically part of block zero.
+	 */
+	logical_sb = fs->e2fs_bsize > SBSIZE ? 0 : 1;
+
+	if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
+	    number < fs->e2fs->e3fs_first_meta_bg)
+		return (logical_sb + number + 1);
+
+	if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT))
+		descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+	else
+		descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
+
+	cg = descpb * number;
+
+	if (ext2_cg_has_sb(fs, cg))
+		has_super = 1;
+
+	return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) +
+	    fs->e2fs->e2fs_first_dblock);
+}
+
 /*
  * This computes the fields of the m_ext2fs structure from the
  * data in the ext2fs structure read in.
@@ -328,7 +359,6 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
 {
 	int g_count = 0, error;
 	int i, j;
-	int logic_sb_block = 1;	/* XXX for now */
 	struct buf *bp;
 	uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
 
@@ -385,6 +415,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
 		    es->e3fs_desc_size);
 		return (EINVAL);
 	}
+	/* Check for group size */
+	if (fs->e2fs_bpg != fs->e2fs_bsize * 8) {
+		printf("ext2fs: non-standard group size unsupported %d\n",
+		    fs->e2fs_bpg);
+		return (EINVAL);
+	}
 
 	fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
 	fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
@@ -405,16 +441,9 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
 	fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
 	    sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
 
-	/*
-	 * Adjust logic_sb_block.
-	 * Godmar thinks: if the blocksize is greater than 1024, then
-	 * the superblock is logically part of block zero.
-	 */
-	if (fs->e2fs_bsize > SBSIZE)
-		logic_sb_block = 0;
 	for (i = 0; i < fs->e2fs_gdbcount; i++) {
 		error = bread(devvp,
-		    fsbtodb(fs, logic_sb_block + i + 1),
+		    fsbtodb(fs, cg_location(fs, i)),
 		    fs->e2fs_bsize, NOCRED, &bp);
 		if (error) {
 			free(fs->e2fs_contigdirs, M_EXT2MNT);
@@ -1151,8 +1180,8 @@ ext2_cgupdate(struct ext2mount *mp, int waitfor)
 
 	for (i = 0; i < fs->e2fs_gdbcount; i++) {
 		bp = getblk(mp->um_devvp, fsbtodb(fs,
-		    fs->e2fs->e2fs_first_dblock +
-		    1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
+		    cg_location(fs, i)),
+		    fs->e2fs_bsize, 0, 0, 0);
 		if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
 			memcpy(bp->b_data, &fs->e2fs_gd[
 			    i * fs->e2fs_bsize / sizeof(struct ext2_gd)],

Modified: head/sys/fs/ext2fs/ext2fs.h
==============================================================================
--- head/sys/fs/ext2fs/ext2fs.h	Mon Jan 29 21:16:56 2018	(r328563)
+++ head/sys/fs/ext2fs/ext2fs.h	Mon Jan 29 21:54:13 2018	(r328564)
@@ -334,12 +334,12 @@ static const struct ext2_feature incompat[] = {
 					 EXT2F_ROCOMPAT_HUGE_FILE | \
 					 EXT2F_ROCOMPAT_EXTRA_ISIZE)
 #define	EXT2F_INCOMPAT_SUPP		(EXT2F_INCOMPAT_FTYPE | \
+					 EXT2F_INCOMPAT_META_BG | \
 					 EXT2F_INCOMPAT_EXTENTS | \
 					 EXT2F_INCOMPAT_64BIT | \
-					 EXT2F_INCOMPAT_CSUM_SEED)
-#define	EXT4F_RO_INCOMPAT_SUPP		(EXT2F_INCOMPAT_RECOVER | \
 					 EXT2F_INCOMPAT_FLEX_BG | \
-					 EXT2F_INCOMPAT_META_BG )
+					 EXT2F_INCOMPAT_CSUM_SEED)
+#define	EXT4F_RO_INCOMPAT_SUPP		EXT2F_INCOMPAT_RECOVER
 
 /* 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
@@ -423,5 +423,8 @@ struct ext2_gd {
  * Macro-instructions used to manage group descriptors
  */
 #define	EXT2_BLOCKS_PER_GROUP(s)	(EXT2_SB(s)->e2fs_bpg)
+#define	EXT2_DESCS_PER_BLOCK(s)		(EXT2_HAS_INCOMPAT_FEATURE((s), \
+	EXT2F_INCOMPAT_64BIT) ? ((s)->e2fs_bsize / sizeof(struct ext2_gd)) : \
+	((s)->e2fs_bsize / E2FS_REV0_GD_SIZE))
 
 #endif	/* !_FS_EXT2FS_EXT2FS_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801292154.w0TLsDsR008816>