All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds
@ 2015-10-12 21:56 Darrick J. Wong
  2015-10-12 21:56 ` [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled Darrick J. Wong
                   ` (11 more replies)
  0 siblings, 12 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:56 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Hi all,

Here's a short patch series that rolls up all my pending fixes for
assorted minor problems with e2fsprogs.  It then replaces all the open
coded feature flag functions with a series of helper functions; and
finally it introduces the "metdata_csum_seed" feature which decouples
the metadata block checksums from the FS UUID so that said UUID can be
changed while the FS is mounted.

Patches 1-2 fix an incorrect overhead calculation in mke2fs when
formatting with meta_bg that prevented formatting devices larger than
256TB; and teaches mke2fs to enable meta_bg whenever the group
descriptor blocks overflow a block group.  This makes it possible to
format ext4 on multi-petabyte block devices, albeit at a SEVERE
overhead cost.

Patches 3-7 replace open-coded feature flag manipulation code with
helper functions.  I've hand-checked all the changes to ensure that
they are correct.

Patches 8-12 introduces the metadata_csum_seed feature, which saves
the first component of metadata block checksums (specifically, the
value of crc32c(~0, FS_UUID)) in the superblock.  This enables the
administrator to change the UUID on a mounted metadata_csum
filesystem.

The patchset should apply cleanly against the -next branch as of 29
September.  Comments and questions are, as always, welcome.

--D

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
@ 2015-10-12 21:56 ` Darrick J. Wong
  2015-10-24  4:37   ` Theodore Ts'o
  2015-10-12 21:56 ` [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0 Darrick J. Wong
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:56 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4, Dave Chinner

When meta_bg is enabled at mkfs time, we put at most one group
descriptor block in each blockgroup.  Unfortunately, the calculation
of max overhead per bg doesn't know this, so mkfs fails when it isn't
strictly necessary.  Fix it, since Dave reported that he couldn't
create a 500TB ext4 filesystem.

Reported-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/initialize.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)


diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 75fbf8e..f672a27 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -379,7 +379,12 @@ ipg_retry:
 	 * table, and the reserved gdt blocks.
 	 */
 	overhead = (int) (3 + fs->inode_blocks_per_group +
-			  fs->desc_blocks + super->s_reserved_gdt_blocks);
+			  super->s_reserved_gdt_blocks);
+
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+		overhead++;
+	else
+		overhead += fs->desc_blocks;
 
 	/* This can only happen if the user requested too many inodes */
 	if (overhead > super->s_blocks_per_group) {


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
  2015-10-12 21:56 ` [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled Darrick J. Wong
@ 2015-10-12 21:56 ` Darrick J. Wong
  2015-10-13  2:34   ` Andreas Dilger
  2015-10-24  4:38   ` Theodore Ts'o
  2015-10-12 21:56 ` [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions Darrick J. Wong
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:56 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

If during formatting we'd lose more than half of a block group to
group descriptors and other metadata, enable the meta_bg feature.
This enables us to create >500T filesystems with default options.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/initialize.c |    5 +++++
 1 file changed, 5 insertions(+)


diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index f672a27..b5ca928 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -381,6 +381,11 @@ ipg_retry:
 	overhead = (int) (3 + fs->inode_blocks_per_group +
 			  super->s_reserved_gdt_blocks);
 
+	/* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
+	if (super->s_reserved_gdt_blocks + fs->desc_blocks >
+	    super->s_blocks_per_group * 3 / 4)
+		fs->super->s_feature_incompat |= EXT2_FEATURE_INCOMPAT_META_BG;
+
 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
 		overhead++;
 	else


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
  2015-10-12 21:56 ` [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled Darrick J. Wong
  2015-10-12 21:56 ` [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0 Darrick J. Wong
@ 2015-10-12 21:56 ` Darrick J. Wong
  2015-10-24  4:41   ` Theodore Ts'o
  2015-10-12 21:56 ` [PATCH 04/12] e2fsck: " Darrick J. Wong
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:56 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Create separate predicate functions to test/set/clear feature flags,
thereby replacing the wordy old macros.  Furthermore, clean out the
places where we open-coded feature tests.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/e2p/ls.c              |   18 +++++----
 lib/ext2fs/alloc_sb.c     |    2 +
 lib/ext2fs/alloc_tables.c |    3 +-
 lib/ext2fs/blknum.c       |   63 +++++++++++++-------------------
 lib/ext2fs/bmap.c         |    6 +--
 lib/ext2fs/check_desc.c   |    3 +-
 lib/ext2fs/closefs.c      |   16 ++++----
 lib/ext2fs/csum.c         |   48 ++++++++----------------
 lib/ext2fs/dir_iterate.c  |    3 +-
 lib/ext2fs/ext2_fs.h      |   89 +++++++++++++++++++++++++++++++++++++++++++++
 lib/ext2fs/ext2fs.h       |   11 ++----
 lib/ext2fs/ext_attr.c     |    6 +--
 lib/ext2fs/i_block.c      |   19 ++++------
 lib/ext2fs/initialize.c   |   17 ++++-----
 lib/ext2fs/inline_data.c  |   11 ++----
 lib/ext2fs/kernel-jbd.h   |   78 +++++++++++++++++++++++++++++++++++----
 lib/ext2fs/link.c         |    5 +--
 lib/ext2fs/mkdir.c        |    9 ++---
 lib/ext2fs/mkjournal.c    |    9 ++---
 lib/ext2fs/mmp.c          |    8 ++--
 lib/ext2fs/newdir.c       |    6 +--
 lib/ext2fs/openfs.c       |   20 ++++------
 lib/ext2fs/read_bb.c      |    3 +-
 lib/ext2fs/res_gdt.c      |    5 +--
 lib/ext2fs/symlink.c      |    6 +--
 lib/support/quotaio.c     |    3 +-
 26 files changed, 278 insertions(+), 189 deletions(-)


diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c
index 2e98c14..6c82857 100644
--- a/lib/e2p/ls.c
+++ b/lib/e2p/ls.c
@@ -170,21 +170,21 @@ static void print_super_flags(struct ext2_super_block * s, FILE *f)
 static __u64 e2p_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_blocks_count_hi << 32 : 0);
 }
 
 static __u64 e2p_r_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_r_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_r_blocks_count_hi << 32 : 0);
 }
 
 static __u64 e2p_free_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_free_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_free_blocks_hi << 32 : 0);
 }
 
@@ -263,19 +263,19 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
 	fprintf(f, "Free inodes:              %u\n", sb->s_free_inodes_count);
 	fprintf(f, "First block:              %u\n", sb->s_first_data_block);
 	fprintf(f, "Block size:               %u\n", EXT2_BLOCK_SIZE(sb));
-	if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+	if (ext2fs_has_feature_bigalloc(sb))
 		fprintf(f, "Cluster size:             %u\n",
 			EXT2_CLUSTER_SIZE(sb));
 	else
 		fprintf(f, "Fragment size:            %u\n",
 			EXT2_CLUSTER_SIZE(sb));
-	if (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(sb))
 		fprintf(f, "Group descriptor size:    %u\n", sb->s_desc_size);
 	if (sb->s_reserved_gdt_blocks)
 		fprintf(f, "Reserved GDT blocks:      %u\n",
 			sb->s_reserved_gdt_blocks);
 	fprintf(f, "Blocks per group:         %u\n", sb->s_blocks_per_group);
-	if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+	if (ext2fs_has_feature_bigalloc(sb))
 		fprintf(f, "Clusters per group:       %u\n",
 			sb->s_clusters_per_group);
 	else
@@ -361,7 +361,7 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
 	if (sb->s_last_orphan)
 		fprintf(f, "First orphan inode:       %u\n",
 			sb->s_last_orphan);
-	if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+	if (ext2fs_has_feature_dir_index(sb) ||
 	    sb->s_def_hash_version)
 		fprintf(f, "Default directory hash:   %s\n",
 			e2p_hash2string(sb->s_def_hash_version));
@@ -428,7 +428,7 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
 		fprintf(f, "Last error block #:       %llu\n",
 			sb->s_last_error_block);
 	}
-	if (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) {
+	if (ext2fs_has_feature_mmp(sb)) {
 		fprintf(f, "MMP block number:         %llu\n",
 			(long long)sb->s_mmp_block);
 		fprintf(f, "MMP update interval:      %u\n",
@@ -441,7 +441,7 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
 		fprintf(f, "Group quota inode:        %u\n",
 			sb->s_grp_quota_inum);
 
-	if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+	if (ext2fs_has_feature_metadata_csum(sb)) {
 		fprintf(f, "Checksum type:            %s\n",
 			checksum_type(sb->s_checksum_type));
 		fprintf(f, "Checksum:                 0x%08x\n",
diff --git a/lib/ext2fs/alloc_sb.c b/lib/ext2fs/alloc_sb.c
index 8788c00..8530b40 100644
--- a/lib/ext2fs/alloc_sb.c
+++ b/lib/ext2fs/alloc_sb.c
@@ -52,7 +52,7 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
 	ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
 				  &old_desc_blk, &new_desc_blk, &used_blks);
 
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks =
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 3e1952f..da0b15b 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -95,8 +95,7 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
 	if (!bmap)
 		bmap = fs->block_map;
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+	if (ext2fs_has_feature_flex_bg(fs->super) &&
 	    fs->super->s_log_groups_per_flex) {
 		flexbg_size = 1 << fs->super->s_log_groups_per_flex;
 		last_grp = group | (flexbg_size - 1);
diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c
index 93b64ce..4389a2f 100644
--- a/lib/ext2fs/blknum.c
+++ b/lib/ext2fs/blknum.c
@@ -69,8 +69,7 @@ blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
 					struct ext2_inode *inode)
 {
 	return (inode->i_blocks |
-		((fs->super->s_feature_ro_compat &
-		  EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
+		(ext2fs_has_feature_huge_file(fs->super) ?
 		 (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
 		(inode->i_file_acl ? fs->blocksize >> 9 : 0);
 }
@@ -82,8 +81,7 @@ blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
 					struct ext2_inode *inode)
 {
 	return (inode->i_blocks |
-		((fs->super->s_feature_ro_compat &
-		  EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
+		(ext2fs_has_feature_huge_file(fs->super) ?
 		 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
 }
 
@@ -93,7 +91,7 @@ blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
 blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_blocks_count_hi << 32 : 0);
 }
 
@@ -103,7 +101,7 @@ blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
 void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
 {
 	super->s_blocks_count = blk;
-	if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(super))
 		super->s_blocks_count_hi = (__u64) blk >> 32;
 }
 
@@ -123,7 +121,7 @@ void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
 blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_r_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_r_blocks_count_hi << 32 : 0);
 }
 
@@ -133,7 +131,7 @@ blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
 void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
 {
 	super->s_r_blocks_count = blk;
-	if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(super))
 		super->s_r_blocks_count_hi = (__u64) blk >> 32;
 }
 
@@ -153,7 +151,7 @@ void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
 blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
 {
 	return super->s_free_blocks_count |
-		(super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(super) ?
 		(__u64) super->s_free_blocks_hi << 32 : 0);
 }
 
@@ -163,7 +161,7 @@ blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
 void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
 {
 	super->s_free_blocks_count = blk;
-	if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(super))
 		super->s_free_blocks_hi = (__u64) blk >> 32;
 }
 
@@ -223,8 +221,7 @@ blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_block_bitmap |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u64)gdp->bg_block_bitmap_hi << 32 : 0);
 }
 
@@ -237,7 +234,7 @@ void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_block_bitmap = blk;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
 }
 
@@ -265,8 +262,7 @@ blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_inode_bitmap |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
 }
 
@@ -279,7 +275,7 @@ void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_inode_bitmap = blk;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
 }
 
@@ -292,8 +288,7 @@ blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_inode_table |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u64) gdp->bg_inode_table_hi << 32 : 0);
 }
 
@@ -306,7 +301,7 @@ void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_inode_table = blk;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_inode_table_hi = (__u64) blk >> 32;
 }
 
@@ -319,8 +314,7 @@ __u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_free_blocks_count |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
 }
 
@@ -334,7 +328,7 @@ void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_free_blocks_count = n;
 
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
 }
 
@@ -347,8 +341,7 @@ __u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_free_inodes_count |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
 }
 
@@ -361,7 +354,7 @@ void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_free_inodes_count = n;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
 }
 
@@ -374,8 +367,7 @@ __u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_used_dirs_count |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
 }
 
@@ -388,7 +380,7 @@ void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_used_dirs_count = n;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
 }
 
@@ -401,8 +393,7 @@ __u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	return gdp->bg_itable_unused |
-		(fs->super->s_feature_incompat
-		 & EXT4_FEATURE_INCOMPAT_64BIT ?
+		(ext2fs_has_feature_64bit(fs->super) ?
 		 (__u32) gdp->bg_itable_unused_hi << 16 : 0);
 }
 
@@ -415,7 +406,7 @@ void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
 
 	gdp = ext4fs_group_desc(fs, fs->group_desc, group);
 	gdp->bg_itable_unused = n;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		gdp->bg_itable_unused_hi = (__u32) n >> 16;
 }
 
@@ -507,7 +498,7 @@ blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
 {
 	blk64_t	blk = inode->i_file_acl;
 
-	if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (fs && ext2fs_has_feature_64bit(fs->super))
 		blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
 	return blk;
 }
@@ -519,7 +510,7 @@ void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
 			       blk64_t blk)
 {
 	inode->i_file_acl = blk;
-	if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (fs && ext2fs_has_feature_64bit(fs->super))
 		inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
 }
 
@@ -536,11 +527,9 @@ errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
 	/* If we're writing a large file, set the large_file flag */
 	if (LINUX_S_ISREG(inode->i_mode) &&
 	    ext2fs_needs_large_file_feature(size) &&
-	    (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
+	    (!ext2fs_has_feature_large_file(fs->super) ||
 	     fs->super->s_rev_level == EXT2_GOOD_OLD_REV)) {
-		fs->super->s_feature_ro_compat |=
-					EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+		ext2fs_set_feature_large_file(fs->super);
 		ext2fs_update_dynamic_rev(fs);
 		ext2fs_mark_super_dirty(fs);
 	}
diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c
index c18f742..29da4ef 100644
--- a/lib/ext2fs/bmap.c
+++ b/lib/ext2fs/bmap.c
@@ -145,8 +145,7 @@ static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino,
 	blk64_t	base_block, pblock = 0;
 	int i;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (!ext2fs_has_feature_bigalloc(fs->super))
 		return 0;
 
 	base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs);
@@ -183,8 +182,7 @@ errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino,
 
 	/* Need bigalloc and extents to be enabled */
 	*pblk = 0;
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_BIGALLOC) ||
+	if (!ext2fs_has_feature_bigalloc(fs->super) ||
 	    !(inode->i_flags & EXT4_EXTENTS_FL))
 		return 0;
 
diff --git a/lib/ext2fs/check_desc.c b/lib/ext2fs/check_desc.c
index 1a768f9..3e3fa94 100644
--- a/lib/ext2fs/check_desc.c
+++ b/lib/ext2fs/check_desc.c
@@ -53,8 +53,7 @@ errcode_t ext2fs_check_desc(ext2_filsys fs)
 		ext2fs_reserve_super_and_bgd(fs, i, bmap);
 
 	for (i = 0; i < fs->group_desc_count; i++) {
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+		if (!ext2fs_has_feature_flex_bg(fs->super)) {
 			first_block = ext2fs_group_first_block2(fs, i);
 			last_block = ext2fs_group_last_block2(fs, i);
 		}
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index 3c7c7dc..b69fa09 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -37,14 +37,13 @@ int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
 {
 	if (group == 0)
 		return 1;
-	if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+	if (ext2fs_has_feature_sparse_super2(fs->super)) {
 		if (group == fs->super->s_backup_bgs[0] ||
 		    group == fs->super->s_backup_bgs[1])
 			return 1;
 		return 0;
 	}
-	if ((group <= 1) || !(fs->super->s_feature_ro_compat &
-			      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+	if ((group <= 1) || !ext2fs_has_feature_sparse_super(fs->super))
 		return 1;
 	if (!(group & 1))
 		return 0;
@@ -86,7 +85,7 @@ errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
 	if (group_block == 0 && fs->blocksize == 1024)
 		group_block = 1; /* Deal with 1024 blocksize && bigalloc */
 
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks =
@@ -101,7 +100,7 @@ errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
 	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
 	meta_bg = group / meta_bg_size;
 
-	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+	if (!ext2fs_has_feature_meta_bg(fs->super) ||
 	    (meta_bg < fs->super->s_first_meta_bg)) {
 		if (has_super) {
 			old_desc_blk = group_block + 1;
@@ -347,14 +346,13 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
 	 * we write out the backup superblocks.)
 	 */
 	fs->super->s_state &= ~EXT2_VALID_FS;
-	fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+	ext2fs_clear_feature_journal_needs_recovery(fs->super);
 
 	/*
 	 * If this is an external journal device, don't write out the
 	 * block group descriptors or any of the backup superblocks
 	 */
-	if (fs->super->s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+	if (ext2fs_has_feature_journal_dev(fs->super))
 		goto write_primary_superblock_only;
 
 	/*
@@ -362,7 +360,7 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
 	 * superblocks and group descriptors.
 	 */
 	group_ptr = (char *) group_shadow;
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
+	if (ext2fs_has_feature_meta_bg(fs->super)) {
 		old_desc_blocks = fs->super->s_first_meta_bg;
 		if (old_desc_blocks > fs->desc_blocks)
 			old_desc_blocks = fs->desc_blocks;
diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
index 6dcefb9..ab8b83f 100644
--- a/lib/ext2fs/csum.c
+++ b/lib/ext2fs/csum.c
@@ -41,8 +41,7 @@ int ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp)
 {
 	__u32 calculated;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	calculated = ext2fs_mmp_csum(fs, mmp);
@@ -54,8 +53,7 @@ errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp)
 {
 	__u32 crc;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	crc = ext2fs_mmp_csum(fs, mmp);
@@ -66,8 +64,7 @@ errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp)
 
 int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb)
 {
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	return sb->s_checksum_type == EXT2_CRC32C_CHKSUM;
@@ -145,8 +142,7 @@ int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 	__u32 calculated;
 	errcode_t retval;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated);
@@ -163,8 +159,7 @@ errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
 	errcode_t retval;
 	__u32 crc;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc);
@@ -442,8 +437,7 @@ static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum,
 int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 				 struct ext2_dir_entry *dirent)
 {
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
@@ -457,8 +451,7 @@ int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
 				    struct ext2_dir_entry *dirent)
 {
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
@@ -516,8 +509,7 @@ int ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 	 * The extent tree structures are accessed in LE order, so we must
 	 * swap the checksum bytes here.
 	 */
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	provided = ext2fs_le32_to_cpu(t->et_checksum);
@@ -535,8 +527,7 @@ errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
 	__u32 crc;
 	struct ext3_extent_tail *t = get_extent_tail(eh);
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	/*
@@ -557,8 +548,7 @@ int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
 			ext2fs_group_desc(fs, fs->group_desc, group);
 	__u32 provided, calculated;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 	provided = gdp->bg_inode_bitmap_csum_lo;
 	calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
@@ -578,8 +568,7 @@ errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
 	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
 			ext2fs_group_desc(fs, fs->group_desc, group);
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
@@ -597,8 +586,7 @@ int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
 			ext2fs_group_desc(fs, fs->group_desc, group);
 	__u32 provided, calculated;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 	provided = gdp->bg_block_bitmap_csum_lo;
 	calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
@@ -618,8 +606,7 @@ errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
 	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
 			ext2fs_group_desc(fs, fs->group_desc, group);
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
@@ -669,8 +656,7 @@ int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 	char *cp;
 
 	if (fs->super->s_creator_os != EXT2_OS_LINUX ||
-	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	    !ext2fs_has_feature_metadata_csum(fs->super))
 		return 1;
 
 	has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
@@ -713,8 +699,7 @@ errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum,
 	int has_hi;
 
 	if (fs->super->s_creator_os != EXT2_OS_LINUX ||
-	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	    !ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
@@ -750,8 +735,7 @@ __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
 	group = ext2fs_swab32(group);
 #endif
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+	if (ext2fs_has_feature_metadata_csum(fs->super)) {
 		/* new metadata csum code */
 		__u16 old_crc;
 		__u32 crc32;
diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c
index 390573a..b2b7769 100644
--- a/lib/ext2fs/dir_iterate.c
+++ b/lib/ext2fs/dir_iterate.c
@@ -218,8 +218,7 @@ int ext2fs_process_dir_block(ext2_filsys fs,
 		buflen = ctx->buflen;
 	}
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 
 	while (offset < buflen - 8) {
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index cfeaa05..709838d 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -809,6 +809,95 @@ struct ext2_super_block {
 #define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */
 #define EXT4_FEATURE_INCOMPAT_ENCRYPT		0x10000
 
+#define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \
+static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
+{ \
+	return ((EXT2_SB(sb)->s_feature_compat & \
+		 EXT##ver##_FEATURE_COMPAT_##flagname) != 0); \
+} \
+static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_compat |= \
+		EXT##ver##_FEATURE_COMPAT_##flagname; \
+} \
+static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_compat &= \
+		~EXT##ver##_FEATURE_COMPAT_##flagname; \
+}
+
+#define EXT4_FEATURE_RO_COMPAT_FUNCS(name, ver, flagname) \
+static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
+{ \
+	return ((EXT2_SB(sb)->s_feature_ro_compat & \
+		 EXT##ver##_FEATURE_RO_COMPAT_##flagname) != 0); \
+} \
+static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_ro_compat |= \
+		EXT##ver##_FEATURE_RO_COMPAT_##flagname; \
+} \
+static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_ro_compat &= \
+		~EXT##ver##_FEATURE_RO_COMPAT_##flagname; \
+}
+
+#define EXT4_FEATURE_INCOMPAT_FUNCS(name, ver, flagname) \
+static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \
+{ \
+	return ((EXT2_SB(sb)->s_feature_incompat & \
+		 EXT##ver##_FEATURE_INCOMPAT_##flagname) != 0); \
+} \
+static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_incompat |= \
+		EXT##ver##_FEATURE_INCOMPAT_##flagname; \
+} \
+static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \
+{ \
+	EXT2_SB(sb)->s_feature_incompat &= \
+		~EXT##ver##_FEATURE_INCOMPAT_##flagname; \
+}
+
+EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc,		2, DIR_PREALLOC)
+EXT4_FEATURE_COMPAT_FUNCS(imagic_inodes,	2, IMAGIC_INODES)
+EXT4_FEATURE_COMPAT_FUNCS(journal,		3, HAS_JOURNAL)
+EXT4_FEATURE_COMPAT_FUNCS(xattr,		2, EXT_ATTR)
+EXT4_FEATURE_COMPAT_FUNCS(resize_inode,		2, RESIZE_INODE)
+EXT4_FEATURE_COMPAT_FUNCS(dir_index,		2, DIR_INDEX)
+EXT4_FEATURE_COMPAT_FUNCS(lazy_bg,		2, LAZY_BG)
+EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap,	2, EXCLUDE_BITMAP)
+EXT4_FEATURE_COMPAT_FUNCS(sparse_super2,	4, SPARSE_SUPER2)
+
+EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super,	2, SPARSE_SUPER)
+EXT4_FEATURE_RO_COMPAT_FUNCS(large_file,	2, LARGE_FILE)
+EXT4_FEATURE_RO_COMPAT_FUNCS(huge_file,		4, HUGE_FILE)
+EXT4_FEATURE_RO_COMPAT_FUNCS(gdt_csum,		4, GDT_CSUM)
+EXT4_FEATURE_RO_COMPAT_FUNCS(dir_nlink,		4, DIR_NLINK)
+EXT4_FEATURE_RO_COMPAT_FUNCS(extra_isize,	4, EXTRA_ISIZE)
+EXT4_FEATURE_RO_COMPAT_FUNCS(has_snapshot,	4, HAS_SNAPSHOT)
+EXT4_FEATURE_RO_COMPAT_FUNCS(quota,		4, QUOTA)
+EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc,		4, BIGALLOC)
+EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum,	4, METADATA_CSUM)
+EXT4_FEATURE_RO_COMPAT_FUNCS(replica,		4, REPLICA)
+EXT4_FEATURE_RO_COMPAT_FUNCS(readonly,		4, READONLY)
+
+EXT4_FEATURE_INCOMPAT_FUNCS(compression,	2, COMPRESSION)
+EXT4_FEATURE_INCOMPAT_FUNCS(filetype,		2, FILETYPE)
+EXT4_FEATURE_INCOMPAT_FUNCS(journal_needs_recovery,	3, RECOVER)
+EXT4_FEATURE_INCOMPAT_FUNCS(journal_dev,	3, JOURNAL_DEV)
+EXT4_FEATURE_INCOMPAT_FUNCS(meta_bg,		2, META_BG)
+EXT4_FEATURE_INCOMPAT_FUNCS(extents,		3, EXTENTS)
+EXT4_FEATURE_INCOMPAT_FUNCS(64bit,		4, 64BIT)
+EXT4_FEATURE_INCOMPAT_FUNCS(mmp,		4, MMP)
+EXT4_FEATURE_INCOMPAT_FUNCS(flex_bg,		4, FLEX_BG)
+EXT4_FEATURE_INCOMPAT_FUNCS(ea_inode,		4, EA_INODE)
+EXT4_FEATURE_INCOMPAT_FUNCS(dirdata,		4, DIRDATA)
+EXT4_FEATURE_INCOMPAT_FUNCS(largedir,		4, LARGEDIR)
+EXT4_FEATURE_INCOMPAT_FUNCS(inline_data,	4, INLINE_DATA)
+EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,		4, ENCRYPT)
+
 #define EXT2_FEATURE_COMPAT_SUPP	0
 #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \
 				       EXT4_FEATURE_INCOMPAT_MMP)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 86d860f..30e913c 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -635,9 +635,8 @@ struct ext2_xattr_handle;
  */
 static inline int ext2fs_has_group_desc_csum(ext2_filsys fs)
 {
-	return EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-			EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
-			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+	return ext2fs_has_feature_metadata_csum(fs->super) ||
+	       ext2fs_has_feature_gdt_csum(fs->super);
 }
 
 /* The LARGE_FILE feature should be set if we have stored files 2GB+ in size */
@@ -1658,7 +1657,6 @@ extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
 
 /* inline functions */
 #ifdef NO_INLINE_FUNCS
-extern void ext2fs_init_csum_seed(ext2_filsys fs);
 extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
 extern errcode_t ext2fs_get_memzero(unsigned long size, void *ptr);
 extern errcode_t ext2fs_get_array(unsigned long count,
@@ -1714,10 +1712,9 @@ extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type);
 #endif /* __STDC_VERSION__ >= 199901L */
 #endif
 
-_INLINE_ void ext2fs_init_csum_seed(ext2_filsys fs)
+static inline void ext2fs_init_csum_seed(ext2_filsys fs)
 {
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(fs->super))
 		return;
 
 	fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index bb950aa..0a4f8c0 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -1060,10 +1060,8 @@ errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino,
 	struct ext2_xattr_handle *h;
 	errcode_t err;
 
-	if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-				     EXT2_FEATURE_COMPAT_EXT_ATTR) &&
-	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				     EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+	if (!ext2fs_has_feature_xattr(fs->super) &&
+	    !ext2fs_has_feature_inline_data(fs->super))
 		return EXT2_ET_MISSING_EA_FEATURE;
 
 	err = ext2fs_get_memzero(sizeof(*h), &h);
diff --git a/lib/ext2fs/i_block.c b/lib/ext2fs/i_block.c
index 5ca57e4..2eecf02 100644
--- a/lib/ext2fs/i_block.c
+++ b/lib/ext2fs/i_block.c
@@ -32,18 +32,17 @@ errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
 {
 	unsigned long long b = inode->i_blocks;
 
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
 
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	if (!ext2fs_has_feature_huge_file(fs->super) ||
 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 	    num_blocks *= fs->blocksize / 512;
 	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
 
 	b += num_blocks;
 
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
 	else if (b > 0xFFFFFFFF)
 		return EOVERFLOW;
@@ -56,11 +55,10 @@ errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
 {
 	unsigned long long b = inode->i_blocks;
 
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
 
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	if (!ext2fs_has_feature_huge_file(fs->super) ||
 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 	    num_blocks *= fs->blocksize / 512;
 	num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
@@ -70,7 +68,7 @@ errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
 
 	b -= num_blocks;
 
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
 	inode->i_blocks = b & 0xFFFFFFFF;
 	return 0;
@@ -78,14 +76,13 @@ errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
 
 errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b)
 {
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	if (!ext2fs_has_feature_huge_file(fs->super) ||
 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 		b *= fs->blocksize / 512;
 	b *= EXT2FS_CLUSTER_RATIO(fs);
 
 	inode->i_blocks = b & 0xFFFFFFFF;
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		inode->osd2.linux2.l_i_blocks_hi = b >> 32;
 	else if (b >> 32)
 		return EOVERFLOW;
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index b5ca928..8714ff5 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -147,8 +147,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
 	super->s_magic = EXT2_SUPER_MAGIC;
 	super->s_state = EXT2_VALID_FS;
 
-	bigalloc_flag = EXT2_HAS_RO_COMPAT_FEATURE(param,
-				   EXT4_FEATURE_RO_COMPAT_BIGALLOC);
+	bigalloc_flag = ext2fs_has_feature_bigalloc(param);
 
 	assign_field(s_log_block_size);
 
@@ -258,7 +257,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
 	 * If we're creating an external journal device, we don't need
 	 * to bother with the rest.
 	 */
-	if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(super)) {
 		fs->group_desc_count = 0;
 		ext2fs_mark_super_dirty(fs);
 		*ret_fs = fs;
@@ -275,7 +274,7 @@ retry:
 	}
 
 	set_field(s_desc_size,
-		  super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+		  ext2fs_has_feature_64bit(super) ?
 		  EXT2_MIN_DESC_SIZE_64BIT : 0);
 
 	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
@@ -283,7 +282,7 @@ retry:
 
 	i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
 
-	if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT &&
+	if (ext2fs_has_feature_64bit(super) &&
 	    (ext2fs_blocks_count(super) / i) > (1ULL << 32))
 		set_field(s_inodes_count, ~0U);
 	else
@@ -362,7 +361,7 @@ ipg_retry:
 	/*
 	 * check the number of reserved group descriptor table blocks
 	 */
-	if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)
+	if (ext2fs_has_feature_resize_inode(super))
 		rsv_gdt = calc_reserved_gdt_blocks(fs);
 	else
 		rsv_gdt = 0;
@@ -384,9 +383,9 @@ ipg_retry:
 	/* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
 	if (super->s_reserved_gdt_blocks + fs->desc_blocks >
 	    super->s_blocks_per_group * 3 / 4)
-		fs->super->s_feature_incompat |= EXT2_FEATURE_INCOMPAT_META_BG;
+		ext2fs_set_feature_meta_bg(fs->super);
 
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		overhead++;
 	else
 		overhead += fs->desc_blocks;
@@ -435,7 +434,7 @@ ipg_retry:
 	 */
 
 	/* Set up the locations of the backup superblocks */
-	if (super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+	if (ext2fs_has_feature_sparse_super2(super)) {
 		if (super->s_backup_bgs[0] >= fs->group_desc_count)
 			super->s_backup_bgs[0] = fs->group_desc_count - 1;
 		if (super->s_backup_bgs[1] >= fs->group_desc_count)
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index 3a81eb0..587b88d 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -291,13 +291,11 @@ static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
 	int csum_size = 0;
 	int filetype = 0;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 
 	/* Create '.' and '..' */
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+	if (ext2fs_has_feature_filetype(fs->super))
 		filetype = EXT2_FT_DIR;
 
 	/*
@@ -386,7 +384,7 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
 		goto errout;
 
 	/* Update inode */
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS))
+	if (ext2fs_has_feature_extents(fs->super))
 		inode->i_flags |= EXT4_EXTENTS_FL;
 	inode->i_flags &= ~EXT4_INLINE_DATA_FL;
 	retval = ext2fs_iblk_add_blocks(fs, inode, 1);
@@ -415,8 +413,7 @@ ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino,
 
 	/* Update inode */
 	memset(inode->i_block, 0, sizeof(inode->i_block));
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+	if (ext2fs_has_feature_extents(fs->super)) {
 		ext2_extent_handle_t handle;
 
 		inode->i_flags &= ~EXT4_EXTENTS_FL;
diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h
index 4653560..772d7ed 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -245,7 +245,7 @@ typedef struct journal_superblock_s
 	((j)->j_format_version >= 2 &&					\
 	 ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
 
-#define JFS_FEATURE_COMPAT_CHECKSUM	0x00000001
+#define JFS_FEATURE_COMPAT_CHECKSUM		0x00000001
 
 #define JFS_FEATURE_INCOMPAT_REVOKE		0x00000001
 #define JFS_FEATURE_INCOMPAT_64BIT		0x00000002
@@ -253,6 +253,69 @@ typedef struct journal_superblock_s
 #define JFS_FEATURE_INCOMPAT_CSUM_V2		0x00000008
 #define JFS_FEATURE_INCOMPAT_CSUM_V3		0x00000010
 
+/* journal feature predicate functions */
+#define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \
+static inline int jfs_has_feature_##name(journal_t *j) \
+{ \
+	return ((j)->j_format_version >= 2 && \
+		((j)->j_superblock->s_feature_compat & \
+		 ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname)) != 0); \
+} \
+static inline void jfs_set_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_compat |= \
+		ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
+} \
+static inline void jfs_clear_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_compat &= \
+		~ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
+}
+
+#define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
+static inline int jfs_has_feature_##name(journal_t *j) \
+{ \
+	return ((j)->j_format_version >= 2 && \
+		((j)->j_superblock->s_feature_ro_compat & \
+		 ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname)) != 0); \
+} \
+static inline void jfs_set_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_ro_compat |= \
+		ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
+} \
+static inline void jfs_clear_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_ro_compat &= \
+		~ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
+}
+
+#define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \
+static inline int jfs_has_feature_##name(journal_t *j) \
+{ \
+	return ((j)->j_format_version >= 2 && \
+		((j)->j_superblock->s_feature_incompat & \
+		 ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname)) != 0); \
+} \
+static inline void jfs_set_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_incompat |= \
+		ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
+} \
+static inline void jfs_clear_feature_##name(journal_t *j) \
+{ \
+	(j)->j_superblock->s_feature_incompat &= \
+		~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
+}
+
+JFS_FEATURE_COMPAT_FUNCS(checksum,		CHECKSUM)
+
+JFS_FEATURE_INCOMPAT_FUNCS(revoke,		REVOKE)
+JFS_FEATURE_INCOMPAT_FUNCS(64bit,		64BIT)
+JFS_FEATURE_INCOMPAT_FUNCS(async_commit,	ASYNC_COMMIT)
+JFS_FEATURE_INCOMPAT_FUNCS(csum2,		CSUM_V2)
+JFS_FEATURE_INCOMPAT_FUNCS(csum3,		CSUM_V3)
+
 /* Features known to this kernel version: */
 #define JFS_KNOWN_COMPAT_FEATURES	0
 #define JFS_KNOWN_ROCOMPAT_FEATURES	0
@@ -284,28 +347,27 @@ typedef struct journal_superblock_s
 /*
  * helper functions to deal with 32 or 64bit block numbers.
  */
-_INLINE_ size_t journal_tag_bytes(journal_t *journal)
+static inline size_t journal_tag_bytes(journal_t *journal)
 {
 	size_t sz;
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum3(journal))
 		return sizeof(journal_block_tag3_t);
 
 	sz = sizeof(journal_block_tag_t);
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
+	if (jfs_has_feature_csum2(journal))
 		sz += sizeof(__u16);
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(journal))
 		return sz;
 
 	return sz - sizeof(__u32);
 }
 
-_INLINE_ int journal_has_csum_v2or3(journal_t *journal)
+static inline int journal_has_csum_v2or3(journal_t *journal)
 {
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) ||
-	    JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum2(journal) || jfs_has_feature_csum3(journal))
 		return 1;
 
 	return 0;
diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c
index 09e6cb4..65dc887 100644
--- a/lib/ext2fs/link.c
+++ b/lib/ext2fs/link.c
@@ -53,8 +53,7 @@ static int link_proc(struct ext2_dir_entry *dirent,
 	if (ls->err)
 		return DIRENT_ABORT;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(ls->fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(ls->fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 	/*
 	 * See if the following directory entry (if any) is unused;
@@ -138,7 +137,7 @@ static int link_proc(struct ext2_dir_entry *dirent,
 	dirent->inode = ls->inode;
 	ext2fs_dirent_set_name_len(dirent, ls->namelen);
 	strncpy(dirent->name, ls->name, ls->namelen);
-	if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+	if (ext2fs_has_feature_filetype(ls->sb))
 		ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
 
 	ls->done++;
diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c
index 433f3b4..2a63aad 100644
--- a/lib/ext2fs/mkdir.c
+++ b/lib/ext2fs/mkdir.c
@@ -51,8 +51,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 	 * and ino >= EXT2_FIRST_INO.
 	 */
 	if ((!ino || ino >= EXT2_FIRST_INO(fs->super)) &&
-	    EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+	    ext2fs_has_feature_inline_data(fs->super))
 		inline_data = 1;
 
 	/*
@@ -108,8 +107,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 		inode.i_flags |= EXT4_INLINE_DATA_FL;
 		inode.i_size = EXT4_MIN_INLINE_DATA_SIZE;
 	} else {
-		if (fs->super->s_feature_incompat &
-		    EXT3_FEATURE_INCOMPAT_EXTENTS)
+		if (ext2fs_has_feature_extents(fs->super))
 			inode.i_flags |= EXT4_EXTENTS_FL;
 		else
 			inode.i_block[0] = blk;
@@ -134,8 +132,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
 		if (retval)
 			goto cleanup;
 
-		if (fs->super->s_feature_incompat &
-		    EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		if (ext2fs_has_feature_extents(fs->super)) {
 			retval = ext2fs_extent_open2(fs, ino, &inode, &handle);
 			if (retval)
 				goto cleanup;
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 80a1021..af983c7 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -73,8 +73,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
 	 * If we're creating an external journal device, we need to
 	 * adjust these fields.
 	 */
-	if (fs->super->s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(fs->super)) {
 		jsb->s_nr_users = 0;
 		jsb->s_first = htonl(ext2fs_journal_sb_start(fs->blocksize) + 1);
 	}
@@ -289,7 +288,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
 	if (goal == ~0ULL)
 		goal = get_midpoint_journal_block(fs);
 
-	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)
+	if (ext2fs_has_feature_extents(fs->super))
 		inode.i_flags |= EXT4_EXTENTS_FL;
 
 	if (!(flags & EXT2_MKJOURNAL_LAZYINIT))
@@ -414,7 +413,7 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
 	memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
 	       sizeof(fs->super->s_journal_uuid));
 	memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks));
-	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	ext2fs_set_feature_journal(fs->super);
 	ext2fs_mark_super_dirty(fs);
 	return 0;
 }
@@ -526,7 +525,7 @@ errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
 	fs->super->s_journal_dev = 0;
 	memset(fs->super->s_journal_uuid, 0,
 	       sizeof(fs->super->s_journal_uuid));
-	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	ext2fs_set_feature_journal(fs->super);
 
 	ext2fs_mark_super_dirty(fs);
 	return 0;
diff --git a/lib/ext2fs/mmp.c b/lib/ext2fs/mmp.c
index ac27837..0570fed 100644
--- a/lib/ext2fs/mmp.c
+++ b/lib/ext2fs/mmp.c
@@ -378,7 +378,7 @@ errcode_t ext2fs_mmp_stop(ext2_filsys fs)
 	struct mmp_struct *mmp, *mmp_cmp;
 	errcode_t retval = 0;
 
-	if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+	if (!ext2fs_has_feature_mmp(fs->super) ||
 	    !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
 		goto mmp_error;
 
@@ -405,7 +405,7 @@ mmp_error:
 
 	return retval;
 #else
-	if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+	if (!ext2fs_has_feature_mmp(fs->super) ||
 	    !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
 		return 0;
 
@@ -425,7 +425,7 @@ errcode_t ext2fs_mmp_update2(ext2_filsys fs, int immediately)
 	struct timeval tv;
 	errcode_t retval = 0;
 
-	if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+	if (!ext2fs_has_feature_mmp(fs->super) ||
 	    !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
 		return 0;
 
@@ -451,7 +451,7 @@ errcode_t ext2fs_mmp_update2(ext2_filsys fs, int immediately)
 mmp_error:
 	return retval;
 #else
-	if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+	if (!ext2fs_has_feature_mmp(fs->super) ||
 	    !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
 		return 0;
 
diff --git a/lib/ext2fs/newdir.c b/lib/ext2fs/newdir.c
index ed250c7..7f47285 100644
--- a/lib/ext2fs/newdir.c
+++ b/lib/ext2fs/newdir.c
@@ -45,8 +45,7 @@ errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
 	memset(buf, 0, fs->blocksize);
 	dir = (struct ext2_dir_entry *) buf;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 
 	retval = ext2fs_set_rec_len(fs, fs->blocksize - csum_size, dir);
@@ -56,8 +55,7 @@ errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
 	}
 
 	if (dir_ino) {
-		if (fs->super->s_feature_incompat &
-		    EXT2_FEATURE_INCOMPAT_FILETYPE)
+		if (ext2fs_has_feature_filetype(fs->super))
 			filetype = EXT2_FT_DIR;
 		/*
 		 * Set up entry for '.'
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 1d6f147..ba39e01 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -47,7 +47,7 @@ blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
 	if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1)
 		group_zero_adjust = 1;
 
-	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+	if (!ext2fs_has_feature_meta_bg(fs->super) ||
 	    (i < fs->super->s_first_meta_bg))
 		return group_block + i + 1 + group_zero_adjust;
 
@@ -269,8 +269,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 		}
 
 		if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
-		    (fs->super->s_feature_incompat &
-		     EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		    ext2fs_has_feature_journal_dev(fs->super)) {
 			retval = EXT2_ET_UNSUPP_FEATURE;
 			goto cleanup;
 		}
@@ -286,15 +285,13 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 	 * bigalloc requires cluster-aware bitfield operations, which at the
 	 * moment means we need EXT2_FLAG_64BITS.
 	 */
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+	if (ext2fs_has_feature_bigalloc(fs->super) &&
 	    !(flags & EXT2_FLAG_64BITS)) {
 		retval = EXT2_ET_CANT_USE_LEGACY_BITMAPS;
 		goto cleanup;
 	}
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+	if (!ext2fs_has_feature_bigalloc(fs->super) &&
 	    (fs->super->s_log_block_size != fs->super->s_log_cluster_size)) {
 		retval = EXT2_ET_CORRUPT_SUPERBLOCK;
 		goto cleanup;
@@ -306,7 +303,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 	}
 
 	/* Enforce the block group descriptor size */
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) {
+	if (ext2fs_has_feature_64bit(fs->super)) {
 		if (fs->super->s_desc_size < EXT2_MIN_DESC_SIZE_64BIT) {
 			retval = EXT2_ET_BAD_DESC_SIZE;
 			goto cleanup;
@@ -345,8 +342,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 	 * If this is an external journal device, don't try to read
 	 * the group descriptors, because they're not there.
 	 */
-	if (fs->super->s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(fs->super)) {
 		fs->group_desc_count = 0;
 		*ret_fs = fs;
 		return 0;
@@ -404,7 +400,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 #ifdef WORDS_BIGENDIAN
 	groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
 #endif
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
+	if (ext2fs_has_feature_meta_bg(fs->super)) {
 		first_meta_bg = fs->super->s_first_meta_bg;
 		if (first_meta_bg > fs->desc_blocks)
 			first_meta_bg = fs->desc_blocks;
@@ -461,7 +457,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 			ext2fs_mark_super_dirty(fs);
 	}
 
-	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
+	if (ext2fs_has_feature_mmp(fs->super) &&
 	    !(flags & EXT2_FLAG_SKIP_MMP) &&
 	    (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) {
 		retval = ext2fs_mmp_start(fs);
diff --git a/lib/ext2fs/read_bb.c b/lib/ext2fs/read_bb.c
index b5a0d7b..e58b7cb 100644
--- a/lib/ext2fs/read_bb.c
+++ b/lib/ext2fs/read_bb.c
@@ -76,8 +76,7 @@ errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
 		if (retval)
 			return retval;
 		numblocks = inode.i_blocks;
-		if (!((fs->super->s_feature_ro_compat &
-		       EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+		if (!(ext2fs_has_feature_huge_file(fs->super) &&
 		      (inode.i_flags & EXT4_HUGE_FILE_FL)))
 			numblocks = numblocks / (fs->blocksize / 512);
 		numblocks += 20;
diff --git a/lib/ext2fs/res_gdt.c b/lib/ext2fs/res_gdt.c
index 46db61c..eaa9cf8 100644
--- a/lib/ext2fs/res_gdt.c
+++ b/lib/ext2fs/res_gdt.c
@@ -31,7 +31,7 @@ static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
 	int mult = 3;
 	unsigned int ret;
 
-	if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+	if (ext2fs_has_feature_sparse_super2(fs->super)) {
 		if (*min == 1) {
 			*min += 1;
 			if (fs->super->s_backup_bgs[0])
@@ -44,8 +44,7 @@ static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
 		}
 		return fs->group_desc_count;
 	}
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+	if (!ext2fs_has_feature_sparse_super(fs->super)) {
 		ret = *min;
 		*min += 1;
 		return ret;
diff --git a/lib/ext2fs/symlink.c b/lib/ext2fs/symlink.c
index 6e988ad..0e6f9a9 100644
--- a/lib/ext2fs/symlink.c
+++ b/lib/ext2fs/symlink.c
@@ -88,8 +88,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 	/* The time fields are set by ext2fs_write_new_inode() */
 
 	inlinelink = !fastlink &&
-		     (fs->super->s_feature_incompat &
-					EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+		     ext2fs_has_feature_inline_data(fs->super) &&
 		     (target_len < fs->blocksize);
 	if (fastlink) {
 		/* Fast symlinks, target stored in inode */
@@ -114,8 +113,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 need_block:
 		/* Slow symlinks, target stored in the first block */
 		ext2fs_iblk_set(fs, &inode, 1);
-		if (fs->super->s_feature_incompat &
-		    EXT3_FEATURE_INCOMPAT_EXTENTS) {
+		if (ext2fs_has_feature_extents(fs->super)) {
 			/*
 			 * The extent bmap is setup after the inode and block
 			 * have been written out below.
diff --git a/lib/support/quotaio.c b/lib/support/quotaio.c
index 3af82f7..d30c980 100644
--- a/lib/support/quotaio.c
+++ b/lib/support/quotaio.c
@@ -284,8 +284,7 @@ static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino)
 	inode.i_links_count = 1;
 	inode.i_mode = LINUX_S_IFREG | 0600;
 	inode.i_flags |= EXT2_IMMUTABLE_FL;
-	if (fs->super->s_feature_incompat &
-			EXT3_FEATURE_INCOMPAT_EXTENTS)
+	if (ext2fs_has_feature_extents(fs->super))
 		inode.i_flags |= EXT4_EXTENTS_FL;
 
 	err = ext2fs_write_new_inode(fs, ino, &inode);


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 04/12] e2fsck: clean up feature test macros with predicate functions
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (2 preceding siblings ...)
  2015-10-12 21:56 ` [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions Darrick J. Wong
@ 2015-10-12 21:56 ` Darrick J. Wong
  2015-10-24  4:49   ` Theodore Ts'o
  2015-10-12 21:57 ` [PATCH 05/12] misc: " Darrick J. Wong
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:56 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Create separate predicate functions to test/set/clear feature flags,
thereby replacing the wordy old macros.  Furthermore, clean out the
places where we open-coded feature tests.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/extents.c  |    9 +++-----
 e2fsck/journal.c  |   52 ++++++++++++++++++++---------------------------
 e2fsck/message.c  |    3 +--
 e2fsck/pass1.c    |   59 ++++++++++++++++++++---------------------------------
 e2fsck/pass1b.c   |    4 ++--
 e2fsck/pass2.c    |   36 ++++++++++++--------------------
 e2fsck/pass3.c    |    3 +--
 e2fsck/pass5.c    |    6 ++---
 e2fsck/quota.c    |    5 ++--
 e2fsck/recovery.c |   18 ++++++----------
 e2fsck/rehash.c   |   16 +++++---------
 e2fsck/super.c    |   46 ++++++++++++++---------------------------
 e2fsck/unix.c     |    9 ++++----
 13 files changed, 101 insertions(+), 165 deletions(-)


diff --git a/e2fsck/extents.c b/e2fsck/extents.c
index 407dafb..c4167e1 100644
--- a/e2fsck/extents.c
+++ b/e2fsck/extents.c
@@ -29,8 +29,7 @@ errcode_t e2fsck_rebuild_extents_later(e2fsck_t ctx, ext2_ino_t ino)
 {
 	errcode_t retval = 0;
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(ctx->fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS) ||
+	if (!ext2fs_has_feature_extents(ctx->fs->super) ||
 	    (ctx->options & E2F_OPT_NO) ||
 	    (ino != EXT2_ROOT_INO && ino < ctx->fs->super->s_first_ino))
 		return 0;
@@ -314,8 +313,7 @@ static errcode_t e2fsck_rebuild_extents(e2fsck_t ctx, ext2_ino_t ino)
 	struct extent_list	list;
 	errcode_t err;
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(ctx->fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS) ||
+	if (!ext2fs_has_feature_extents(ctx->fs->super) ||
 	    (ctx->options & E2F_OPT_NO) ||
 	    (ino != EXT2_ROOT_INO && ino < ctx->fs->super->s_first_ino))
 		return 0;
@@ -344,8 +342,7 @@ static void rebuild_extents(e2fsck_t ctx, const char *pass_name, int pr_header)
 	ext2_ino_t		ino = 0;
 	errcode_t		retval;
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(ctx->fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS) ||
+	if (!ext2fs_has_feature_extents(ctx->fs->super) ||
 	    !ext2fs_test_valid(ctx->fs) ||
 	    ctx->invalid_bitmaps) {
 		if (ctx->inodes_to_rebuild)
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 9f32095..c8ac57d 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -239,7 +239,7 @@ void wait_on_buffer(struct buffer_head *bh)
 
 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
 {
-	ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+	ext2fs_clear_feature_journal_needs_recovery(ctx->fs->super);
 
 	/* if we had an error doing journal recovery, we need a full fsck */
 	if (error)
@@ -461,7 +461,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
 			ext2fs_swap_super(&jsuper);
 #endif
 		if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
-		    !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		    !ext2fs_has_feature_journal_dev(&jsuper)) {
 			fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
 			retval = EXT2_ET_LOAD_EXT_JOURNAL;
 			brelse(bh);
@@ -477,8 +477,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
 		}
 
 		/* Check the superblock checksum */
-		if (jsuper.s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+		if (ext2fs_has_feature_metadata_csum(&jsuper)) {
 			struct struct_ext2_filsys fsx;
 			struct ext2_super_block	superx;
 			void *p;
@@ -487,8 +486,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
 			memcpy(&fsx, ctx->fs, sizeof(fsx));
 			memcpy(&superx, ctx->fs->super, sizeof(superx));
 			fsx.super = &superx;
-			fsx.super->s_feature_ro_compat |=
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+			ext2fs_set_feature_metadata_csum(fsx.super);
 			if (!ext2fs_superblock_csum_verify(&fsx, p) &&
 			    fix_problem(ctx, PR_0_EXT_JOURNAL_SUPER_CSUM_INVALID,
 					&pctx)) {
@@ -535,10 +533,8 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
 					      struct problem_context *pctx)
 {
 	struct ext2_super_block *sb = ctx->fs->super;
-	int recover = ctx->fs->super->s_feature_incompat &
-		EXT3_FEATURE_INCOMPAT_RECOVER;
-	int has_journal = ctx->fs->super->s_feature_compat &
-		EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	int recover = ext2fs_has_feature_journal_needs_recovery(ctx->fs->super);
+	int has_journal = ext2fs_has_feature_journal(ctx->fs->super);
 
 	if (has_journal || sb->s_journal_inum) {
 		/* The journal inode is bogus, remove and force full fsck */
@@ -546,7 +542,7 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
 		if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
 			if (has_journal && sb->s_journal_inum)
 				printf("*** journal has been deleted ***\n\n");
-			sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			ext2fs_clear_feature_journal(sb);
 			sb->s_journal_inum = 0;
 			memset(sb->s_jnl_blocks, 0, sizeof(sb->s_jnl_blocks));
 			ctx->flags |= E2F_FLAG_JOURNAL_INODE;
@@ -647,12 +643,11 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
 		return EXT2_ET_RO_UNSUPP_FEATURE;
 
 	/* Checksum v1-3 are mutually exclusive features. */
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
-	    JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum2(journal) && jfs_has_feature_csum3(journal))
 		return EXT2_ET_CORRUPT_SUPERBLOCK;
 
 	if (journal_has_csum_v2or3(journal) &&
-	    JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
+	    jfs_has_feature_checksum(journal))
 		return EXT2_ET_CORRUPT_SUPERBLOCK;
 
 	if (!e2fsck_journal_verify_csum_type(journal, jsb) ||
@@ -741,10 +736,9 @@ static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
 						  struct problem_context *pctx)
 {
 	struct ext2_super_block *sb = ctx->fs->super;
-	int recover = ctx->fs->super->s_feature_incompat &
-		EXT3_FEATURE_INCOMPAT_RECOVER;
+	int recover = ext2fs_has_feature_journal_needs_recovery(ctx->fs->super);
 
-	if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
+	if (ext2fs_has_feature_journal(sb)) {
 		if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
 			e2fsck_journal_reset_super(ctx, journal->j_superblock,
 						   journal);
@@ -799,15 +793,14 @@ errcode_t e2fsck_check_ext3_journal(e2fsck_t ctx)
 {
 	struct ext2_super_block *sb = ctx->fs->super;
 	journal_t *journal;
-	int recover = ctx->fs->super->s_feature_incompat &
-		EXT3_FEATURE_INCOMPAT_RECOVER;
+	int recover = ext2fs_has_feature_journal_needs_recovery(ctx->fs->super);
 	struct problem_context pctx;
 	problem_t problem;
 	int reset = 0, force_fsck = 0;
 	errcode_t retval;
 
 	/* If we don't have any journal features, don't do anything more */
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+	if (!ext2fs_has_feature_journal(sb) &&
 	    !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
 	    uuid_is_null(sb->s_journal_uuid))
  		return 0;
@@ -848,8 +841,8 @@ errcode_t e2fsck_check_ext3_journal(e2fsck_t ctx)
 	 * with -y, -n, or -p, only if a user isn't making up their mind.
 	 */
 no_has_journal:
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
-		recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
+	if (!ext2fs_has_feature_journal(sb)) {
+		recover = ext2fs_has_feature_journal_needs_recovery(sb);
 		if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
 			if (recover &&
 			    !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
@@ -867,14 +860,14 @@ no_has_journal:
 			       sizeof(sb->s_journal_uuid));
 			e2fsck_clear_recover(ctx, force_fsck);
 		} else if (!(ctx->options & E2F_OPT_READONLY)) {
-			sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			ext2fs_set_feature_journal(sb);
 			ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
 			ext2fs_mark_super_dirty(ctx->fs);
 		}
 	}
 
-	if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
-	    !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+	if (ext2fs_has_feature_journal(sb) &&
+	    !ext2fs_has_feature_journal_needs_recovery(sb) &&
 	    journal->j_superblock->s_start != 0) {
 		/* Print status information */
 		fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
@@ -884,8 +877,7 @@ no_has_journal:
 			problem = PR_0_JOURNAL_RUN;
 		if (fix_problem(ctx, problem, &pctx)) {
 			ctx->options |= E2F_OPT_FORCE;
-			sb->s_feature_incompat |=
-				EXT3_FEATURE_INCOMPAT_RECOVER;
+			ext2fs_set_feature_journal_needs_recovery(sb);
 			ext2fs_mark_super_dirty(ctx->fs);
 		} else if (fix_problem(ctx,
 				       PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
@@ -911,7 +903,7 @@ no_has_journal:
 	 * the journal's errno is set; if so, we need to mark the file
 	 * system as being corrupt and clear the journal's s_errno.
 	 */
-	if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+	if (!ext2fs_has_feature_journal_needs_recovery(sb) &&
 	    journal->j_superblock->s_errno) {
 		ctx->fs->super->s_state |= EXT2_ERROR_FS;
 		ext2fs_mark_super_dirty(ctx->fs);
@@ -1047,7 +1039,7 @@ void e2fsck_move_ext3_journal(e2fsck_t ctx)
 	 */
 	if ((ctx->options & E2F_OPT_READONLY) ||
 	    (sb->s_journal_inum == 0) ||
-	    !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+	    !ext2fs_has_feature_journal(sb))
 		return;
 
 	/*
@@ -1159,7 +1151,7 @@ int e2fsck_fix_ext3_journal_hint(e2fsck_t ctx)
 	char uuid[37], *journal_name;
 	struct stat st;
 
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) ||
+	if (!ext2fs_has_feature_journal(sb) ||
 	    uuid_is_null(sb->s_journal_uuid))
  		return 0;
 
diff --git a/e2fsck/message.c b/e2fsck/message.c
index 9c1433f..74e7b94 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -296,8 +296,7 @@ static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch,
 		fprintf(f, "%u", large_inode->i_extra_isize);
 		break;
 	case 'b':
-		if (fs->super->s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_HUGE_FILE) 
+		if (ext2fs_has_feature_huge_file(fs->super)) 
 			fprintf(f, "%llu", inode->i_blocks +
 				(((long long) inode->osd2.linux2.l_i_blocks_hi)
 				 << 32));
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 61ae2d9..0a8e23e 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -540,10 +540,8 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
 	 * data.  If it's true, we will treat it as a directory.
 	 */
 
-	extent_fs = (ctx->fs->super->s_feature_incompat &
-		     EXT3_FEATURE_INCOMPAT_EXTENTS);
-	inlinedata_fs = (ctx->fs->super->s_feature_incompat &
-			 EXT4_FEATURE_INCOMPAT_INLINE_DATA);
+	extent_fs = ext2fs_has_feature_extents(ctx->fs->super);
+	inlinedata_fs = ext2fs_has_feature_inline_data(ctx->fs->super);
 	if (inlinedata_fs && (inode->i_flags & EXT4_INLINE_DATA_FL)) {
 		size_t size;
 		__u32 dotdot;
@@ -830,10 +828,8 @@ static int fix_inline_data_extents_file(e2fsck_t ctx,
 	int dirty = 0;
 
 	/* Both feature flags not set?  Just run the regular checks */
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS) &&
-	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+	if (!ext2fs_has_feature_extents(fs->super) &&
+	    !ext2fs_has_feature_inline_data(fs->super))
 		return 0;
 
 	/* Clear both flags if it's a special file */
@@ -992,7 +988,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 	if (!(ctx->options & E2F_OPT_PREEN))
 		fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
 
-	if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
+	if (ext2fs_has_feature_dir_index(fs->super) &&
 	    !(ctx->options & E2F_OPT_NO)) {
 		if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
 			ctx->dirs_to_hash = 0;
@@ -1013,10 +1009,9 @@ void e2fsck_pass1(e2fsck_t ctx)
 	}
 #undef EXT2_BPP
 
-	imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
-	extent_fs = (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS);
-	inlinedata_fs = (sb->s_feature_incompat &
-			EXT4_FEATURE_INCOMPAT_INLINE_DATA);
+	imagic_fs = ext2fs_has_feature_imagic_inodes(sb);
+	extent_fs = ext2fs_has_feature_extents(sb);
+	inlinedata_fs = ext2fs_has_feature_inline_data(sb);
 
 	/*
 	 * Allocate bitmaps structures
@@ -1150,7 +1145,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 	     fs->super->s_mkfs_time < fs->super->s_inodes_count))
 		low_dtime_check = 0;
 
-	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
+	if (ext2fs_has_feature_mmp(fs->super) &&
 	    fs->super->s_mmp_block > fs->super->s_first_data_block &&
 	    fs->super->s_mmp_block < ext2fs_blocks_count(fs->super))
 		ext2fs_mark_block_bitmap2(ctx->block_found_map,
@@ -1263,8 +1258,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 			pctx.errcode = ext2fs_inline_data_size(fs, ino, &size);
 			if (!pctx.errcode && size &&
 			    fix_problem(ctx, PR_1_INLINE_DATA_FEATURE, &pctx)) {
-				sb->s_feature_incompat |=
-					EXT4_FEATURE_INCOMPAT_INLINE_DATA;
+				ext2fs_set_feature_inline_data(sb);
 				ext2fs_mark_super_dirty(fs);
 				inlinedata_fs = 1;
 			} else if (fix_problem(ctx, PR_1_INLINE_DATA_SET, &pctx)) {
@@ -1353,7 +1347,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 			if ((ext2fs_extent_header_verify(inode->i_block,
 						 sizeof(inode->i_block)) == 0) &&
 			    fix_problem(ctx, PR_1_EXTENT_FEATURE, &pctx)) {
-				sb->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_EXTENTS;
+				ext2fs_set_feature_extents(sb);
 				ext2fs_mark_super_dirty(fs);
 				extent_fs = 1;
 			} else if (fix_problem(ctx, PR_1_EXTENTS_SET, &pctx)) {
@@ -1507,8 +1501,7 @@ void e2fsck_pass1(e2fsck_t ctx)
 		} else if ((ino == EXT4_USR_QUOTA_INO) ||
 			   (ino == EXT4_GRP_QUOTA_INO)) {
 			ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
-			if ((fs->super->s_feature_ro_compat &
-					EXT4_FEATURE_RO_COMPAT_QUOTA) &&
+			if (ext2fs_has_feature_quota(fs->super) &&
 			    ((fs->super->s_usr_quota_inum == ino) ||
 			     (fs->super->s_grp_quota_inum == ino))) {
 				if (!LINUX_S_ISREG(inode->i_mode) &&
@@ -1639,13 +1632,11 @@ void e2fsck_pass1(e2fsck_t ctx)
 		    (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
 			mark_inode_bad(ctx, ino);
 		if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
-		    !(fs->super->s_feature_incompat &
-		      EXT4_FEATURE_INCOMPAT_64BIT) &&
+		    !ext2fs_has_feature_64bit(fs->super) &&
 		    inode->osd2.linux2.l_i_file_acl_high != 0)
 			mark_inode_bad(ctx, ino);
 		if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
-		    !(fs->super->s_feature_ro_compat &
-		      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+		    !ext2fs_has_feature_huge_file(fs->super) &&
 		    (inode->osd2.linux2.l_i_blocks_hi != 0))
 			mark_inode_bad(ctx, ino);
 		if (inode->i_flags & EXT2_IMAGIC_FL) {
@@ -2154,7 +2145,7 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
 	 * Or if the extended attribute block is an invalid block,
 	 * then the inode is also corrupted.
 	 */
-	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
+	if (!ext2fs_has_feature_xattr(fs->super) ||
 	    (blk < fs->super->s_first_data_block) ||
 	    (blk >= ext2fs_blocks_count(fs->super))) {
 		mark_inode_bad(ctx, ino);
@@ -2348,7 +2339,7 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
 
 	if ((!LINUX_S_ISDIR(inode->i_mode) &&
 	     fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
-	    (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
+	    (!ext2fs_has_feature_dir_index(fs->super) &&
 	     fix_problem(ctx, PR_1_HTREE_SET, pctx)))
 		return 1;
 
@@ -2982,10 +2973,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 	pctx->ino = ino;
 	pctx->errcode = 0;
 
-	extent_fs = (ctx->fs->super->s_feature_incompat &
-                     EXT3_FEATURE_INCOMPAT_EXTENTS);
-	inlinedata_fs = (ctx->fs->super->s_feature_incompat &
-			 EXT4_FEATURE_INCOMPAT_INLINE_DATA);
+	extent_fs = ext2fs_has_feature_extents(ctx->fs->super);
+	inlinedata_fs = ext2fs_has_feature_inline_data(ctx->fs->super);
 
 	if (check_ext_attr(ctx, pctx, block_buf)) {
 		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
@@ -3085,8 +3074,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 		quota_data_inodes(ctx->qctx, inode, ino, +1);
 	}
 
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	if (!ext2fs_has_feature_huge_file(fs->super) ||
 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 		pb.num_blocks *= (fs->blocksize / 512);
 	pb.num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
@@ -3170,8 +3158,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 		ctx->large_files++;
 	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
 	    ((pb.num_blocks != ext2fs_inode_i_blocks(fs, inode)) ||
-	     ((fs->super->s_feature_ro_compat &
-	       EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+	     (ext2fs_has_feature_huge_file(fs->super) &&
 	      (inode->i_flags & EXT4_HUGE_FILE_FL) &&
 	      (inode->osd2.linux2.l_i_blocks_hi != 0)))) {
 		pctx->num = pb.num_blocks;
@@ -3188,8 +3175,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 	 * a block mapped file, so rebuild it as an extent file.  We can skip
 	 * symlinks because they're never rewritten.
 	 */
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-			EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+	if (ext2fs_has_feature_bigalloc(fs->super) &&
 	    (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode)) &&
 	    ext2fs_inode_data_blocks2(fs, inode) > 0 &&
 	    (ino == EXT2_ROOT_INO || ino >= EXT2_FIRST_INO(fs->super)) &&
@@ -3655,8 +3641,7 @@ static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group,
 	 * within the flex_bg, and if that fails then try finding the
 	 * space anywhere in the filesystem.
 	 */
-	is_flexbg = EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-					      EXT4_FEATURE_INCOMPAT_FLEX_BG);
+	is_flexbg = ext2fs_has_feature_flex_bg(fs->super);
 	if (is_flexbg) {
 		flexbg_size = 1 << fs->super->s_log_groups_per_flex;
 		flexbg = group / flexbg_size;
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index e0f34e0..2cbf82a 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -327,7 +327,7 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
 					     BLOCK_FLAG_READ_ONLY, block_buf,
 					     process_pass1b_block, &pb);
 		/* If the feature is not set, attrs will be cleared later anyway */
-		if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
+		if (ext2fs_has_feature_xattr(fs->super) &&
 		    ext2fs_file_acl_block(fs, &inode)) {
 			blk64_t blk = ext2fs_file_acl_block(fs, &inode);
 			process_pass1b_block(fs, &blk,
@@ -686,7 +686,7 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
 	e2fsck_read_inode(ctx, ino, &dp->inode, "delete_file");
 	e2fsck_clear_inode(ctx, ino, &dp->inode, 0, "delete_file");
 	if (ext2fs_file_acl_block(fs, &dp->inode) &&
-	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	    ext2fs_has_feature_xattr(fs->super)) {
 		count = 1;
 		pctx.errcode = ext2fs_adjust_ea_refcount3(fs,
 					ext2fs_file_acl_block(fs, &dp->inode),
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 4b81575..532b0eb 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -155,7 +155,7 @@ void e2fsck_pass2(e2fsck_t ctx)
 	if (ctx->progress)
 		(void) (ctx->progress)(ctx, 2, 0, cd.max);
 
-	if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
+	if (ext2fs_has_feature_dir_index(fs->super))
 		ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);
 
 	check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block;
@@ -282,11 +282,9 @@ void e2fsck_pass2(e2fsck_t ctx)
 
 	clear_problem_context(&pctx);
 	if (ctx->large_files) {
-		if (!(sb->s_feature_ro_compat &
-		      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
+		if (!ext2fs_has_feature_large_file(sb) &&
 		    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
-			sb->s_feature_ro_compat |=
-				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+			ext2fs_set_feature_large_file(sb);
 			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
 			ext2fs_mark_super_dirty(fs);
 		}
@@ -520,8 +518,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
 	int	should_be = EXT2_FT_UNKNOWN;
 	struct ext2_inode	inode;
 
-	if (!(ctx->fs->super->s_feature_incompat &
-	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+	if (!ext2fs_has_feature_filetype(ctx->fs->super)) {
 		if (filetype == 0 ||
 		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
 			return 0;
@@ -611,8 +608,7 @@ static void parse_int_node(ext2_filsys fs,
 #endif
 
 	count = ext2fs_le16_to_cpu(limit->count);
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dx_tail);
 	expect_limit = (fs->blocksize -
 			(csum_size + ((char *) ent - block_buf))) /
@@ -932,14 +928,12 @@ static int check_dir_block(ext2_filsys fs,
 	if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
 		return DIRENT_ABORT;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+	if (ext2fs_has_feature_metadata_csum(fs->super)) {
 		dx_csum_size = sizeof(struct ext2_dx_tail);
 		de_csum_size = sizeof(struct ext2_dir_entry_tail);
 	}
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
+	if (ext2fs_has_feature_filetype(fs->super))
 		filetype = EXT2_FT_DIR << 8;
 
 	/*
@@ -956,8 +950,7 @@ static int check_dir_block(ext2_filsys fs,
 	cd->pctx.dirent = 0;
 	cd->pctx.num = 0;
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_INLINE_DATA)) {
+	if (ext2fs_has_feature_inline_data(fs->super)) {
 		errcode_t ec;
 
 		ec = ext2fs_inline_data_size(fs, ino, &inline_data_size);
@@ -1512,8 +1505,7 @@ skip_checksum:
 	if (dir_modified) {
 		int	flags, will_rehash;
 		/* leaf block with no tail?  Rehash dirs later. */
-		if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+		if (ext2fs_has_feature_metadata_csum(fs->super) &&
 		    is_leaf &&
 		    !inline_data_size &&
 		    !ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) {
@@ -1640,7 +1632,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
 	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
 
 	if (ext2fs_file_acl_block(fs, &inode) &&
-	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	    ext2fs_has_feature_xattr(fs->super)) {
 		pctx.errcode = ext2fs_adjust_ea_refcount3(fs,
 				ext2fs_file_acl_block(fs, &inode),
 				block_buf, -1, &count, ino);
@@ -1722,7 +1714,7 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
 	pctx.inode = &inode;
 
 	if (ext2fs_file_acl_block(fs, &inode) &&
-	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	    !ext2fs_has_feature_xattr(fs->super)) {
 		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
 			ext2fs_file_acl_block_set(fs, &inode, 0);
 			inode_modified++;
@@ -1799,8 +1791,7 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
 	}
 
 	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
-	    !(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+	    !ext2fs_has_feature_huge_file(fs->super) &&
 	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
 		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
 		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
@@ -1810,8 +1801,7 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
 	}
 
 	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
-	    !(fs->super->s_feature_incompat &
-	     EXT4_FEATURE_INCOMPAT_64BIT) &&
+	    !ext2fs_has_feature_64bit(fs->super) &&
 	    inode.osd2.linux2.l_i_file_acl_high != 0) {
 		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
 		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index d7b8802..3b076c4 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -716,8 +716,7 @@ static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
 		fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
 	}
 	dirent->inode = fp->parent;
-	if (fp->ctx->fs->super->s_feature_incompat &
-	    EXT2_FEATURE_INCOMPAT_FILETYPE)
+	if (ext2fs_has_feature_filetype(fp->ctx->fs->super))
 		ext2fs_dirent_set_file_type(dirent, EXT2_FT_DIR);
 	else
 		ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 64fb7fe..4a7e53c 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -90,8 +90,7 @@ static void check_inode_bitmap_checksum(e2fsck_t ctx)
 	ext2_ino_t	ino_itr;
 	errcode_t	retval;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
 		return;
 
 	/* If bitmap is dirty from being fixed, checksum will be corrected */
@@ -145,8 +144,7 @@ static void check_block_bitmap_checksum(e2fsck_t ctx)
 	blk64_t		blk_itr;
 	errcode_t	retval;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
 		return;
 
 	/* If bitmap is dirty from being fixed, checksum will be corrected */
diff --git a/e2fsck/quota.c b/e2fsck/quota.c
index 2293aad..4c431f8 100644
--- a/e2fsck/quota.c
+++ b/e2fsck/quota.c
@@ -37,8 +37,7 @@ static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino,
 	inode.i_links_count = 1;
 	inode.i_mode = LINUX_S_IFREG | 0600;
 	inode.i_flags = EXT2_IMMUTABLE_FL;
-	if (fs->super->s_feature_incompat &
-			EXT3_FEATURE_INCOMPAT_EXTENTS)
+	if (ext2fs_has_feature_extents(fs->super))
 		inode.i_flags |= EXT4_EXTENTS_FL;
 
 	retval = ext2fs_write_new_inode(fs, to_ino, &inode);
@@ -66,7 +65,7 @@ void e2fsck_hide_quota(e2fsck_t ctx)
 	clear_problem_context(&pctx);
 
 	if ((ctx->options & E2F_OPT_READONLY) ||
-	    !(sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA))
+	    !ext2fs_has_feature_quota(sb))
 		return;
 
 	pctx.ino = sb->s_usr_quota_inum;
diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index d5244be..41bda03 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -342,7 +342,7 @@ static inline unsigned long long read_tag_block(journal_t *journal,
 						journal_block_tag_t *tag)
 {
 	unsigned long long block = ext2fs_be32_to_cpu(tag->t_blocknr);
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(journal))
 		block |= (u64)ext2fs_be32_to_cpu(tag->t_blocknr_high) << 32;
 	return block;
 }
@@ -411,7 +411,7 @@ static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
 	csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
 	csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize);
 
-	if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum3(j))
 		return tag3->t_checksum == ext2fs_cpu_to_be32(csum32);
 
 	return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
@@ -535,8 +535,7 @@ static int do_one_pass(journal_t *journal,
 			 * just skip over the blocks it describes. */
 			if (pass != PASS_REPLAY) {
 				if (pass == PASS_SCAN &&
-				    JFS_HAS_COMPAT_FEATURE(journal,
-					    JFS_FEATURE_COMPAT_CHECKSUM) &&
+				    jfs_has_feature_checksum(journal) &&
 				    !info->end_transaction) {
 					if (calc_chksums(journal, bh,
 							&next_log_block,
@@ -691,8 +690,7 @@ static int do_one_pass(journal_t *journal,
 			 * much to do other than move on to the next sequence
 			 * number. */
 			if (pass == PASS_SCAN &&
-			    JFS_HAS_COMPAT_FEATURE(journal,
-				    JFS_FEATURE_COMPAT_CHECKSUM)) {
+			    jfs_has_feature_checksum(journal)) {
 				int chksum_err, chksum_seen;
 				struct commit_header *cbh =
 					(struct commit_header *)bh->b_data;
@@ -732,8 +730,7 @@ static int do_one_pass(journal_t *journal,
 				if (chksum_err) {
 					info->end_transaction = next_commit_ID;
 
-					if (!JFS_HAS_INCOMPAT_FEATURE(journal,
-					   JFS_FEATURE_INCOMPAT_ASYNC_COMMIT)){
+					if (!jfs_has_feature_async_commit(journal)){
 						journal->j_failed_commit =
 							next_commit_ID;
 						brelse(bh);
@@ -747,8 +744,7 @@ static int do_one_pass(journal_t *journal,
 							   bh->b_data)) {
 				info->end_transaction = next_commit_ID;
 
-				if (!JFS_HAS_INCOMPAT_FEATURE(journal,
-				     JFS_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+				if (!jfs_has_feature_async_commit(journal)) {
 					journal->j_failed_commit =
 						next_commit_ID;
 					brelse(bh);
@@ -856,7 +852,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 		return -EINVAL;
 	max = rcount;
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(journal))
 		record_len = 8;
 
 	while (offset + record_len <= max) {
diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
index bddbe19..15d3dd9 100644
--- a/e2fsck/rehash.c
+++ b/e2fsck/rehash.c
@@ -448,8 +448,7 @@ static errcode_t copy_dir_entries(e2fsck_t ctx,
 			ctx->htree_slack_percentage = 20;
 	}
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 
 	outdir->max = 0;
@@ -544,7 +543,7 @@ static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
 	int				filetype = 0;
 	int				csum_size = 0;
 
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+	if (ext2fs_has_feature_filetype(fs->super))
 		filetype = EXT2_FT_DIR;
 
 	memset(buf, 0, fs->blocksize);
@@ -569,8 +568,7 @@ static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
 	root->indirect_levels = 0;
 	root->unused_flags = 0;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dx_tail);
 
 	limits = (struct ext2_dx_countlimit *) (buf+32);
@@ -593,8 +591,7 @@ static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
 	dir->inode = 0;
 	(void) ext2fs_set_rec_len(fs, fs->blocksize, dir);
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dx_tail);
 
 	limits = (struct ext2_dx_countlimit *) (buf+8);
@@ -800,8 +797,7 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
 	outdir.hashes = 0;
 	e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+	if (ext2fs_has_feature_inline_data(fs->super) &&
 	   (inode.i_flags & EXT4_INLINE_DATA_FL))
 		return 0;
 
@@ -825,7 +821,7 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
 	fd.dir_size = 0;
 	fd.compress = 0;
 	fd.dir = ino;
-	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+	if (!ext2fs_has_feature_dir_index(fs->super) ||
 	    (inode.i_size / fs->blocksize) < 2)
 		fd.compress = 1;
 	fd.parent = 0;
diff --git a/e2fsck/super.c b/e2fsck/super.c
index 397ad0f..af6d680 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -330,8 +330,7 @@ void check_resize_inode(e2fsck_t ctx)
 	 * If the resize inode feature isn't set, then
 	 * s_reserved_gdt_blocks must be zero.
 	 */
-	if (!(fs->super->s_feature_compat &
-	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+	if (!ext2fs_has_feature_resize_inode(fs->super)) {
 		if (fs->super->s_reserved_gdt_blocks) {
 			pctx.num = fs->super->s_reserved_gdt_blocks;
 			if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
@@ -346,8 +345,7 @@ void check_resize_inode(e2fsck_t ctx)
 	pctx.ino = EXT2_RESIZE_INO;
 	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
 	if (retval) {
-		if (fs->super->s_feature_compat &
-		    EXT2_FEATURE_COMPAT_RESIZE_INODE)
+		if (ext2fs_has_feature_resize_inode(fs->super))
 			ctx->flags |= E2F_FLAG_RESIZE_INODE;
 		return;
 	}
@@ -356,8 +354,7 @@ void check_resize_inode(e2fsck_t ctx)
 	 * If the resize inode feature isn't set, check to make sure
 	 * the resize inode is cleared; then we're done.
 	 */
-	if (!(fs->super->s_feature_compat &
-	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+	if (!ext2fs_has_feature_resize_inode(fs->super)) {
 		for (i=0; i < EXT2_N_BLOCKS; i++) {
 			if (inode.i_block[i])
 				break;
@@ -444,7 +441,7 @@ static void e2fsck_fix_dirhash_hint(e2fsck_t ctx)
 	char	c;
 
 	if ((ctx->options & E2F_OPT_READONLY) ||
-	    !(sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+	    !ext2fs_has_feature_dir_index(sb) ||
 	    (sb->s_flags & (EXT2_FLAGS_SIGNED_HASH|EXT2_FLAGS_UNSIGNED_HASH)))
 		return;
 
@@ -583,43 +580,35 @@ void check_super_block(e2fsck_t ctx)
 	}
 
 	/* Are metadata_csum and uninit_bg both set? */
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
-	    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
+	if (ext2fs_has_feature_metadata_csum(fs->super) &&
+	    ext2fs_has_feature_gdt_csum(fs->super) &&
 	    fix_problem(ctx, PR_0_META_AND_GDT_CSUM_SET, &pctx)) {
-		fs->super->s_feature_ro_compat &=
-			~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+		ext2fs_clear_feature_gdt_csum(fs->super);
 		ext2fs_mark_super_dirty(fs);
 		for (i = 0; i < fs->group_desc_count; i++)
 			ext2fs_group_desc_csum_set(fs, i);
 	}
 
 	/* Is 64bit set and extents unset? */
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_64BIT) &&
-	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS) &&
+	if (ext2fs_has_feature_64bit(fs->super) &&
+	    !ext2fs_has_feature_extents(fs->super) &&
 	    fix_problem(ctx, PR_0_64BIT_WITHOUT_EXTENTS, &pctx)) {
-		fs->super->s_feature_incompat |=
-			EXT3_FEATURE_INCOMPAT_EXTENTS;
+		ext2fs_set_feature_extents(fs->super);
 		ext2fs_mark_super_dirty(fs);
 	}
 
 	/* Did user ask us to convert files to extents? */
 	if (ctx->options & E2F_OPT_CONVERT_BMAP) {
-		fs->super->s_feature_incompat |=
-			EXT3_FEATURE_INCOMPAT_EXTENTS;
+		ext2fs_set_feature_extents(fs->super);
 		ext2fs_mark_super_dirty(fs);
 	}
 
-	if ((fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
+	if (ext2fs_has_feature_meta_bg(fs->super) &&
 	    (fs->super->s_first_meta_bg > fs->desc_blocks)) {
 		pctx.group = fs->desc_blocks;
 		pctx.num = fs->super->s_first_meta_bg;
 		if (fix_problem(ctx, PR_0_FIRST_META_BG_TOO_BIG, &pctx)) {
-			fs->super->s_feature_incompat &=
-				~EXT2_FEATURE_INCOMPAT_META_BG;
+			ext2fs_clear_feature_meta_bg(fs->super);
 			fs->super->s_first_meta_bg = 0;
 			ext2fs_mark_super_dirty(fs);
 		}
@@ -635,8 +624,7 @@ void check_super_block(e2fsck_t ctx)
 	for (i = 0; i < fs->group_desc_count; i++) {
 		pctx.group = i;
 
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+		if (!ext2fs_has_feature_flex_bg(fs->super)) {
 			first_block = ext2fs_group_first_block2(fs, i);
 			last_block = ext2fs_group_last_block2(fs, i);
 		}
@@ -792,11 +780,9 @@ void check_super_block(e2fsck_t ctx)
 	 */
 	if (!(ctx->options & E2F_OPT_READONLY) &&
 	    fs->super->s_creator_os == EXT2_OS_HURD &&
-	    (fs->super->s_feature_incompat &
-	     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+	    ext2fs_has_feature_filetype(fs->super)) {
 		if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
-			fs->super->s_feature_incompat &=
-				~EXT2_FEATURE_INCOMPAT_FILETYPE;
+			ext2fs_clear_feature_filetype(fs->super);
 			ext2fs_mark_super_dirty(fs);
 			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
 		}
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 9d49a0e..bb25f29 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -1620,7 +1620,7 @@ failure:
 
 	ehandler_init(fs->io);
 
-	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
+	if (ext2fs_has_feature_mmp(fs->super) &&
 	    (flags & EXT2_FLAG_SKIP_MMP)) {
 		if (e2fsck_check_mmp(fs, ctx))
 			fatal_error(ctx, 0);
@@ -1654,7 +1654,7 @@ failure:
 	 * Check to see if we need to do ext3-style recovery.  If so,
 	 * do it, and then restart the fsck.
 	 */
-	if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
+	if (ext2fs_has_feature_journal_needs_recovery(sb)) {
 		if (ctx->options & E2F_OPT_READONLY) {
 			log_out(ctx, "%s",
 				_("Warning: skipping journal recovery because "
@@ -1776,7 +1776,7 @@ print_unsupp_features:
 	else
 		journal_size = -1;
 
-	if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA) {
+	if (ext2fs_has_feature_quota(sb)) {
 		/* Quotas were enabled. Do quota accounting during fsck. */
 		if ((sb->s_usr_quota_inum && sb->s_grp_quota_inum) ||
 		    (!sb->s_usr_quota_inum && !sb->s_grp_quota_inum))
@@ -1796,8 +1796,7 @@ print_unsupp_features:
 			if (journal_size < 1024)
 				journal_size = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
 			if (journal_size < 0) {
-				fs->super->s_feature_compat &=
-					~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+				ext2fs_clear_feature_journal(fs->super);
 				fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
 				log_out(ctx, "%s: Couldn't determine "
 					"journal size\n", ctx->program_name);


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 05/12] misc: clean up feature test macros with predicate functions
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (3 preceding siblings ...)
  2015-10-12 21:56 ` [PATCH 04/12] e2fsck: " Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-24  5:24   ` Theodore Ts'o
  2015-10-12 21:57 ` [PATCH 06/12] resize2fs: " Darrick J. Wong
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Create separate predicate functions to test/set/clear feature flags,
thereby replacing the wordy old macros.  Furthermore, clean out the
places where we open-coded feature tests.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 misc/create_inode.c |    6 +-
 misc/dumpe2fs.c     |   25 +++----
 misc/fuse2fs.c      |   31 +++------
 misc/mk_hugefiles.c |    9 +--
 misc/mke2fs.c       |  174 ++++++++++++++++++++-------------------------------
 misc/tune2fs.c      |   78 ++++++++---------------
 6 files changed, 122 insertions(+), 201 deletions(-)


diff --git a/misc/create_inode.c b/misc/create_inode.c
index 1738c36..0de5719 100644
--- a/misc/create_inode.c
+++ b/misc/create_inode.c
@@ -648,11 +648,9 @@ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
 	retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size);
 	if (retval)
 		goto out;
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_INLINE_DATA)) {
+	if (ext2fs_has_feature_inline_data(fs->super)) {
 		inode.i_flags |= EXT4_INLINE_DATA_FL;
-	} else if (fs->super->s_feature_incompat &
-		   EXT3_FEATURE_INCOMPAT_EXTENTS) {
+	} else if (ext2fs_has_feature_extents(fs->super)) {
 		ext2_extent_handle_t handle;
 
 		inode.i_flags &= ~EXT4_EXTENTS_FL;
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 9e1e5d0..a034703 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -143,8 +143,7 @@ static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable,
 		if (itable && block == first_block)
 			return;
 		printf(" (+%u)", (unsigned)(block - first_block));
-	} else if (fs->super->s_feature_incompat &
-		   EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+	} else if (ext2fs_has_feature_flex_bg(fs->super)) {
 		dgrp_t flex_grp = ext2fs_group_of_blk2(fs, block);
 		printf(" (bg #%u + %u)", flex_grp,
 		       (unsigned)(block-ext2fs_group_first_block2(fs,flex_grp)));
@@ -165,8 +164,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 	ext2_ino_t	ino_itr = 1;
 	errcode_t	retval;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (ext2fs_has_feature_bigalloc(fs->super))
 		units = _("clusters");
 
 	block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
@@ -184,7 +182,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 	reserved_gdt = fs->super->s_reserved_gdt_blocks;
 	fputc('\n', stdout);
 	first_block = fs->super->s_first_data_block;
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks = fs->desc_blocks;
@@ -258,8 +256,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 		print_number(ext2fs_block_bitmap_loc(fs, i));
 		print_bg_rel_offset(fs, ext2fs_block_bitmap_loc(fs, i), 0,
 				    first_block, last_block);
-		if (fs->super->s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
+		if (ext2fs_has_feature_metadata_csum(fs->super))
 			printf(_(", csum 0x%08x"),
 			       ext2fs_block_bitmap_checksum(fs, i));
 		if (getenv("DUMPE2FS_IGNORE_80COL"))
@@ -270,8 +267,7 @@ static void list_desc(ext2_filsys fs, int grp_only)
 		print_number(ext2fs_inode_bitmap_loc(fs, i));
 		print_bg_rel_offset(fs, ext2fs_inode_bitmap_loc(fs, i), 0,
 				    first_block, last_block);
-		if (fs->super->s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
+		if (ext2fs_has_feature_metadata_csum(fs->super))
 			printf(_(", csum 0x%08x"),
 			       ext2fs_inode_bitmap_checksum(fs, i));
 		fputs(_("\n  Inode table at "), stdout);
@@ -422,8 +418,7 @@ static void print_inline_journal_information(ext2_filsys fs)
 		printf(" (none)");
 	printf("\n");
 	fputs(_("Journal size:             "), stdout);
-	if ((fs->super->s_feature_ro_compat &
-	     EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+	if (ext2fs_has_feature_huge_file(fs->super) &&
 	    (inode.i_flags & EXT4_HUGE_FILE_FL))
 		size = inode.i_blocks / (fs->blocksize / 1024);
 	else
@@ -699,7 +694,7 @@ try_open_again:
 		exit (1);
 	}
 	fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(fs->super))
 		blocks64 = 1;
 	if (print_badblocks) {
 		list_bad_blocks(fs, 1);
@@ -707,14 +702,12 @@ try_open_again:
 		if (grp_only)
 			goto just_descriptors;
 		list_super (fs->super);
-		if (fs->super->s_feature_incompat &
-		      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		if (ext2fs_has_feature_journal_dev(fs->super)) {
 			print_journal_information(fs);
 			ext2fs_close_free(&fs);
 			exit(0);
 		}
-		if ((fs->super->s_feature_compat &
-		     EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+		if (ext2fs_has_feature_journal(fs->super) &&
 		    (fs->super->s_journal_inum != 0))
 			print_inline_journal_information(fs);
 		list_bad_blocks(fs, 0);
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 5b89821..7d8bb60 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -741,11 +741,10 @@ static blkcnt_t blocks_from_inode(ext2_filsys fs,
 	blkcnt_t b;
 
 	b = inode->i_blocks;
-	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+	if (ext2fs_has_feature_huge_file(fs->super))
 		b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
 
-	if (!(fs->super->s_feature_ro_compat &
-	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	if (!ext2fs_has_feature_huge_file(fs->super) ||
 	    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 		b *= fs->blocksize / 512;
 	b *= EXT2FS_CLUSTER_RATIO(fs);
@@ -1131,8 +1130,7 @@ static int op_mkdir(const char *path, mode_t mode)
 
 	/* Rewrite the directory block checksum, having set i_generation */
 	if ((inode.i_flags & EXT4_INLINE_DATA_FL) ||
-	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	    !ext2fs_has_feature_metadata_csum(fs->super))
 		goto out2;
 	err = ext2fs_new_dir_block(fs, child, parent, &block);
 	if (err) {
@@ -2408,8 +2406,7 @@ static int op_getxattr(const char *path, const char *key, char *value,
 	FUSE2FS_CHECK_CONTEXT(ff);
 	fs = ff->fs;
 	pthread_mutex_lock(&ff->bfl);
-	if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-				     EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	if (!ext2fs_has_feature_xattr(fs->super)) {
 		ret = -ENOTSUP;
 		goto out;
 	}
@@ -2510,8 +2507,7 @@ static int op_listxattr(const char *path, char *names, size_t len)
 	FUSE2FS_CHECK_CONTEXT(ff);
 	fs = ff->fs;
 	pthread_mutex_lock(&ff->bfl);
-	if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-				     EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	if (!ext2fs_has_feature_xattr(fs->super)) {
 		ret = -ENOTSUP;
 		goto out;
 	}
@@ -2591,8 +2587,7 @@ static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
 	FUSE2FS_CHECK_CONTEXT(ff);
 	fs = ff->fs;
 	pthread_mutex_lock(&ff->bfl);
-	if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-				     EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	if (!ext2fs_has_feature_xattr(fs->super)) {
 		ret = -ENOTSUP;
 		goto out;
 	}
@@ -2672,8 +2667,7 @@ static int op_removexattr(const char *path, const char *key)
 	FUSE2FS_CHECK_CONTEXT(ff);
 	fs = ff->fs;
 	pthread_mutex_lock(&ff->bfl);
-	if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-				     EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+	if (!ext2fs_has_feature_xattr(fs->super)) {
 		ret = -ENOTSUP;
 		goto out;
 	}
@@ -2901,7 +2895,7 @@ static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
 	inode.i_links_count = 1;
 	inode.i_extra_isize = sizeof(struct ext2_inode_large) -
 		EXT2_GOOD_OLD_INODE_SIZE;
-	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+	if (ext2fs_has_feature_extents(fs->super)) {
 		ext2_extent_handle_t handle;
 
 		inode.i_flags &= ~EXT4_EXTENTS_FL;
@@ -3722,8 +3716,7 @@ int main(int argc, char *argv[])
 	global_fs->priv_data = ff;
 
 	ret = 3;
-	if (EXT2_HAS_INCOMPAT_FEATURE(global_fs->super,
-				      EXT3_FEATURE_INCOMPAT_RECOVER)) {
+	if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
 		if (readwrite) {
 			printf(_("%s: recovering journal\n"), argv[1]);
 			err = ext2fs_run_ext3_journal(&global_fs);
@@ -3734,8 +3727,7 @@ int main(int argc, char *argv[])
 				       argv[1]);
 				goto out;
 			}
-			global_fs->super->s_feature_incompat &=
-						~EXT3_FEATURE_INCOMPAT_RECOVER;
+			ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
 			ext2fs_mark_super_dirty(global_fs);
 		} else {
 			printf("%s", _("Journal needs recovery; running "
@@ -3745,8 +3737,7 @@ int main(int argc, char *argv[])
 	}
 
 	if (readwrite) {
-		if (EXT2_HAS_COMPAT_FEATURE(global_fs->super,
-					    EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+		if (ext2fs_has_feature_journal(global_fs->super))
 			printf(_("%s: Writing to the journal is not supported.\n"),
 			       argv[1]);
 		err = ext2fs_read_inode_bitmap(global_fs);
diff --git a/misc/mk_hugefiles.c b/misc/mk_hugefiles.c
index 888b184..fb5f99a 100644
--- a/misc/mk_hugefiles.c
+++ b/misc/mk_hugefiles.c
@@ -278,8 +278,7 @@ static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num,
 
 	ext2fs_inode_alloc_stats2(fs, *ino, +1, 0);
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT3_FEATURE_INCOMPAT_EXTENTS))
+	if (ext2fs_has_feature_extents(fs->super))
 		inode.i_flags |= EXT4_EXTENTS_FL;
 	retval = ext2fs_fallocate(fs,
 				  EXT2_FALLOCATE_FORCE_INIT |
@@ -400,8 +399,7 @@ errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name)
 	if (!get_bool_from_profile(fs_types, "make_hugefiles", 0))
 		return 0;
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT3_FEATURE_INCOMPAT_EXTENTS))
+	if (!ext2fs_has_feature_extents(fs->super))
 		return EXT2_ET_EXTENT_NOT_SUPPORTED;
 
 	uid = get_int_from_profile(fs_types, "hugefiles_uid", 0);
@@ -485,8 +483,7 @@ errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name)
 
 	if ((num_blocks ? num_blocks : fs_blocks) >
 	    (0x80000000UL / fs->blocksize))
-		fs->super->s_feature_ro_compat |=
-			EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+		ext2fs_set_feature_large_file(fs->super);
 
 	if (!quiet) {
 		if (zero_hugefile && verbose)
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 179a4d1..9a2a6cc 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -444,8 +444,7 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
 
 	/* Reserved inodes must always have correct checksums */
 	if (fs->super->s_creator_os == EXT2_OS_LINUX &&
-	    fs->super->s_feature_ro_compat &
-	    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
+	    ext2fs_has_feature_metadata_csum(fs->super))
 		write_reserved_inodes(fs);
 }
 
@@ -670,8 +669,7 @@ static void show_stats(ext2_filsys fs)
 	free(os);
 	printf(_("Block size=%u (log=%u)\n"), fs->blocksize,
 		s->s_log_block_size);
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (ext2fs_has_feature_bigalloc(fs->super))
 		printf(_("Cluster size=%u (log=%u)\n"),
 		       fs->blocksize << fs->cluster_ratio_bits,
 		       s->s_log_cluster_size);
@@ -696,8 +694,7 @@ static void show_stats(ext2_filsys fs)
 		printf(_("%u block groups\n"), fs->group_desc_count);
 	else
 		printf(_("%u block group\n"), fs->group_desc_count);
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (ext2fs_has_feature_bigalloc(fs->super))
 		printf(_("%u blocks per group, %u clusters per group\n"),
 		       s->s_blocks_per_group, s->s_clusters_per_group);
 	else
@@ -804,8 +801,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
 		    strcmp(token, "desc_size") == 0) {
 			int desc_size;
 
-			if (!(fs_param.s_feature_incompat &
-			      EXT4_FEATURE_INCOMPAT_64BIT)) {
+			if (!ext2fs_has_feature_64bit(&fs_param)) {
 				fprintf(stderr,
 					_("%s requires '-O 64bit'\n"), token);
 				r_usage++;
@@ -962,8 +958,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
 					free(buf);
 					exit(1);
 				}
-				param->s_feature_compat |=
-					EXT2_FEATURE_COMPAT_RESIZE_INODE;
+				ext2fs_set_feature_resize_inode(param);
 
 				param->s_reserved_gdt_blocks = rsv_gdb;
 			}
@@ -1958,10 +1953,9 @@ profile_error:
 	}
 	/* Mask off features which aren't supported by the Hurd */
 	if (for_hurd(creator_os)) {
-		fs_param.s_feature_incompat &= ~EXT2_FEATURE_INCOMPAT_FILETYPE;
-		fs_param.s_feature_ro_compat &=
-			~(EXT4_FEATURE_RO_COMPAT_HUGE_FILE |
-			  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+		ext2fs_clear_feature_filetype(&fs_param);
+		ext2fs_clear_feature_huge_file(&fs_param);
+		ext2fs_clear_feature_metadata_csum(&fs_param);
 	}
 	edit_feature(fs_features ? fs_features : tmp,
 		     &fs_param.s_feature_compat);
@@ -1971,20 +1965,17 @@ profile_error:
 	 * If the user specified features incompatible with the Hurd, complain
 	 */
 	if (for_hurd(creator_os)) {
-		if (fs_param.s_feature_incompat &
-		    EXT2_FEATURE_INCOMPAT_FILETYPE) {
+		if (ext2fs_has_feature_filetype(&fs_param)) {
 			fprintf(stderr, "%s", _("The HURD does not support the "
 						"filetype feature.\n"));
 			exit(1);
 		}
-		if (fs_param.s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_HUGE_FILE) {
+		if (ext2fs_has_feature_huge_file(&fs_param)) {
 			fprintf(stderr, "%s", _("The HURD does not support the "
 						"huge_file feature.\n"));
 			exit(1);
 		}
-		if (fs_param.s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+		if (ext2fs_has_feature_metadata_csum(&fs_param)) {
 			fprintf(stderr, "%s", _("The HURD does not support the "
 						"metadata_csum feature.\n"));
 			exit(1);
@@ -2052,16 +2043,16 @@ profile_error:
 	 * 32-bit vs 64-bit block number support.
 	 */
 	if ((fs_blocks_count > MAX_32_NUM) &&
-	    (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT))
-		fs_param.s_feature_compat &= ~EXT2_FEATURE_COMPAT_RESIZE_INODE;
+	    ext2fs_has_feature_64bit(&fs_param))
+		ext2fs_clear_feature_resize_inode(&fs_param);
 	if ((fs_blocks_count > MAX_32_NUM) &&
-	    !(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
+	    !ext2fs_has_feature_64bit(&fs_param) &&
 	    get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) {
-		fs_param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
-		fs_param.s_feature_compat &= ~EXT2_FEATURE_COMPAT_RESIZE_INODE;
+		ext2fs_set_feature_64bit(&fs_param);
+		ext2fs_clear_feature_resize_inode(&fs_param);
 	}
 	if ((fs_blocks_count > MAX_32_NUM) &&
-	    !(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)) {
+	    !ext2fs_has_feature_64bit(&fs_param)) {
 		fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
 				  "too big to be expressed\n\t"
 				  "in 32 bits using a blocksize of %d.\n"),
@@ -2072,7 +2063,7 @@ profile_error:
 
 	ext2fs_blocks_count_set(&fs_param, fs_blocks_count);
 
-	if (fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(&fs_param)) {
 		fs_types[0] = strdup("journal");
 		fs_types[1] = 0;
 	}
@@ -2097,11 +2088,9 @@ profile_error:
 				  "with revision 0 filesystems\n"));
 			exit(1);
 		}
-		fs_param.s_feature_ro_compat |=
-			EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+		ext2fs_set_feature_sparse_super(&fs_param);
 	} else if (s_opt == 0)
-		fs_param.s_feature_ro_compat &=
-			~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+		ext2fs_clear_feature_sparse_super(&fs_param);
 
 	if (journal_size != 0) {
 		if (r_opt == EXT2_GOOD_OLD_REV) {
@@ -2109,8 +2098,7 @@ profile_error:
 						"revision 0 filesystems\n"));
 			exit(1);
 		}
-		fs_param.s_feature_compat |=
-			EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+		ext2fs_set_feature_journal(&fs_param);
 	}
 
 	/* Get reserved_ratio from profile if not specified on cmd line. */
@@ -2125,8 +2113,7 @@ profile_error:
 		}
 	}
 
-	if (fs_param.s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(&fs_param)) {
 		reserved_ratio = 0;
 		fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
 		fs_param.s_feature_compat = 0;
@@ -2135,8 +2122,8 @@ profile_error:
  	}
 
 	/* Check the user's mkfs options for 64bit */
-	if ((fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
-	    !(fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+	if (ext2fs_has_feature_64bit(&fs_param) &&
+	    !ext2fs_has_feature_extents(&fs_param)) {
 		printf("%s", _("Extents MUST be enabled for a 64-bit "
 			       "filesystem.  Pass -O extents to rectify.\n"));
 		exit(1);
@@ -2144,10 +2131,10 @@ profile_error:
 
 	/* Set first meta blockgroup via an environment variable */
 	/* (this is mostly for debugging purposes) */
-	if ((fs_param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
-	    ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
+	if (ext2fs_has_feature_meta_bg(&fs_param) &&
+	    (tmp = getenv("MKE2FS_FIRST_META_BG")))
 		fs_param.s_first_meta_bg = atoi(tmp);
-	if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+	if (ext2fs_has_feature_bigalloc(&fs_param)) {
 		if (!cluster_size)
 			cluster_size = get_int_from_profile(fs_types,
 							    "cluster_size",
@@ -2202,7 +2189,7 @@ profile_error:
 	 * can correctly handle "-E resize=NNN" if the 64-bit option
 	 * is set.
 	 */
-	if (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+	if (ext2fs_has_feature_64bit(&fs_param))
 		fs_param.s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
 
 	/* This check should happen beyond the last assignment to blocksize */
@@ -2220,8 +2207,7 @@ profile_error:
 
 	/* Metadata checksumming wasn't totally stable before 3.18. */
 	if (is_before_linux_ver(3, 18, 0) &&
-	    (fs_param.s_feature_ro_compat &
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	    ext2fs_has_feature_metadata_csum(&fs_param))
 		fprintf(stderr, _("Suggestion: Use Linux kernel >= 3.18 for "
 			"improved stability of the metadata and journal "
 			"checksum features.\n"));
@@ -2274,23 +2260,21 @@ profile_error:
 		parse_extended_opts(&fs_param, extended_opts);
 
 	/* Don't allow user to set both metadata_csum and uninit_bg bits. */
-	if ((fs_param.s_feature_ro_compat &
-	     EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
-	    (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
-		fs_param.s_feature_ro_compat &=
-				~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+	if (ext2fs_has_feature_metadata_csum(&fs_param) &&
+	    ext2fs_has_feature_gdt_csum(&fs_param))
+		ext2fs_clear_feature_gdt_csum(&fs_param);
 
 	/* Can't support bigalloc feature without extents feature */
-	if ((fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
-	    !(fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+	if (ext2fs_has_feature_bigalloc(&fs_param) &&
+	    !ext2fs_has_feature_extents(&fs_param)) {
 		com_err(program_name, 0, "%s",
 			_("Can't support bigalloc feature without "
 			  "extents feature"));
 		exit(1);
 	}
 
-	if ((fs_param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
-	    (fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+	if (ext2fs_has_feature_meta_bg(&fs_param) &&
+	    ext2fs_has_feature_resize_inode(&fs_param)) {
 		fprintf(stderr, "%s", _("The resize_inode and meta_bg "
 					"features are not compatible.\n"
 					"They can not be both enabled "
@@ -2298,8 +2282,7 @@ profile_error:
 		exit(1);
 	}
 
-	if (!quiet &&
-	    (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (!quiet && ext2fs_has_feature_bigalloc(&fs_param))
 		fprintf(stderr, "%s", _("\nWarning: the bigalloc feature is "
 				  "still under development\n"
 				  "See https://ext4.wiki.kernel.org/"
@@ -2309,8 +2292,8 @@ profile_error:
 	 * Since sparse_super is the default, we would only have a problem
 	 * here if it was explicitly disabled.
 	 */
-	if ((fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
-	    !(fs_param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+	if (ext2fs_has_feature_resize_inode(&fs_param) &&
+	    !ext2fs_has_feature_sparse_super(&fs_param)) {
 		com_err(program_name, 0, "%s",
 			_("reserved online resize blocks not supported "
 			  "on non-sparse filesystem"));
@@ -2330,20 +2313,18 @@ profile_error:
 	 * If the bigalloc feature is enabled, then the -g option will
 	 * specify the number of clusters per group.
 	 */
-	if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+	if (ext2fs_has_feature_bigalloc(&fs_param)) {
 		fs_param.s_clusters_per_group = fs_param.s_blocks_per_group;
 		fs_param.s_blocks_per_group = 0;
 	}
 
 	if (inode_size == 0)
 		inode_size = get_int_from_profile(fs_types, "inode_size", 0);
-	if (!flex_bg_size && (fs_param.s_feature_incompat &
-			      EXT4_FEATURE_INCOMPAT_FLEX_BG))
+	if (!flex_bg_size && ext2fs_has_feature_flex_bg(&fs_param))
 		flex_bg_size = get_uint_from_profile(fs_types,
 						     "flex_bg_size", 16);
 	if (flex_bg_size) {
-		if (!(fs_param.s_feature_incompat &
-		      EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+		if (!ext2fs_has_feature_flex_bg(&fs_param)) {
 			com_err(program_name, 0, "%s",
 				_("Flex_bg feature not enabled, so "
 				  "flex_bg size may not be specified"));
@@ -2369,8 +2350,7 @@ profile_error:
 	 * If inode size is 128 and inline data is enabled, we need
 	 * to notify users that inline data will never be useful.
 	 */
-	if ((fs_param.s_feature_incompat &
-	     EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+	if (ext2fs_has_feature_inline_data(&fs_param) &&
 	    fs_param.s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
 		com_err(program_name, 0,
 			_("%d byte inodes are too small for inline data; "
@@ -2384,8 +2364,7 @@ profile_error:
 		unsigned long long n;
 		n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
 		if (n > MAX_32_NUM) {
-			if (fs_param.s_feature_incompat &
-			    EXT4_FEATURE_INCOMPAT_64BIT)
+			if (ext2fs_has_feature_64bit(&fs_param))
 				num_inodes = MAX_32_NUM;
 			else {
 				com_err(program_name, 0,
@@ -2427,7 +2406,7 @@ profile_error:
 	ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
 				  ext2fs_blocks_count(&fs_param) / 100.0);
 
-	if (fs_param.s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+	if (ext2fs_has_feature_sparse_super2(&fs_param)) {
 		if (num_backups >= 1)
 			fs_param.s_backup_bgs[0] = 1;
 		if (num_backups >= 2)
@@ -2447,9 +2426,8 @@ static int should_do_undo(const char *name)
 	io_manager manager = unix_io_manager;
 	int csum_flag, force_undo;
 
-	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
-				EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
-				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+	csum_flag = ext2fs_has_feature_metadata_csum(&fs_param) ||
+		    ext2fs_has_feature_gdt_csum(&fs_param);
 	force_undo = get_int_from_profile(fs_types, "force_undo", 0);
 	if (!force_undo && (!csum_flag || !lazy_itable_init))
 		return 0;
@@ -2780,20 +2758,16 @@ int main (int argc, char *argv[])
 
 	/* Check the user's mkfs options for metadata checksumming */
 	if (!quiet &&
-	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) &&
-	    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				EXT3_FEATURE_INCOMPAT_EXTENTS))
+	    !ext2fs_has_feature_journal_dev(fs->super) &&
+	    ext2fs_has_feature_metadata_csum(fs->super)) {
+		if (!ext2fs_has_feature_extents(fs->super))
 			printf("%s",
 			       _("Extents are not enabled.  The file extent "
 				 "tree can be checksummed, whereas block maps "
 				 "cannot.  Not enabling extents reduces the "
 				 "coverage of metadata checksumming.  "
 				 "Pass -O extents to rectify.\n"));
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_INCOMPAT_64BIT))
+		if (!ext2fs_has_feature_64bit(fs->super))
 			printf("%s",
 			       _("64-bit filesystem support is not enabled.  "
 				 "The larger fields afforded by this feature "
@@ -2803,8 +2777,7 @@ int main (int argc, char *argv[])
 
 	/* Calculate journal blocks */
 	if (!journal_device && ((journal_size) ||
-		(fs_param.s_feature_compat &
-		 EXT3_FEATURE_COMPAT_HAS_JOURNAL)))
+	    ext2fs_has_feature_journal(&fs_param)))
 		journal_blocks = figure_journal_size(journal_size, fs);
 
 	/* Can't undo discard ... */
@@ -2832,13 +2805,12 @@ int main (int argc, char *argv[])
 	if (fs_param.s_flags & EXT2_FLAGS_TEST_FILESYS)
 		fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
 
-	if ((fs_param.s_feature_incompat &
-	     (EXT3_FEATURE_INCOMPAT_EXTENTS|EXT4_FEATURE_INCOMPAT_FLEX_BG)) ||
-	    (fs_param.s_feature_ro_compat &
-	     (EXT4_FEATURE_RO_COMPAT_HUGE_FILE|EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
-	      EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
-	      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|
-	      EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)))
+	if (ext2fs_has_feature_flex_bg(&fs_param) ||
+	    ext2fs_has_feature_huge_file(&fs_param) ||
+	    ext2fs_has_feature_gdt_csum(&fs_param) ||
+	    ext2fs_has_feature_dir_nlink(&fs_param) ||
+	    ext2fs_has_feature_metadata_csum(&fs_param) ||
+	    ext2fs_has_feature_extra_isize(&fs_param))
 		fs->super->s_kbytes_written = 1;
 
 	/*
@@ -2912,8 +2884,7 @@ int main (int argc, char *argv[])
 	 * support it.
 	 */
 	if (fs->super->s_creator_os == EXT2_OS_HURD)
-		fs->super->s_feature_incompat &=
-			~EXT2_FEATURE_INCOMPAT_FILETYPE;
+		ext2fs_clear_feature_filetype(fs->super);
 
 	/*
 	 * Set the volume label...
@@ -2937,15 +2908,14 @@ int main (int argc, char *argv[])
 
 	/* Set current default encryption algorithms for data and
 	 * filename encryption */
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_ENCRYPT) {
+	if (ext2fs_has_feature_encrypt(fs->super)) {
 		fs->super->s_encrypt_algos[0] =
 			EXT4_ENCRYPTION_MODE_AES_256_XTS;
 		fs->super->s_encrypt_algos[1] =
 			EXT4_ENCRYPTION_MODE_AES_256_CTS;
 	}
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM;
 
 	if (!quiet || noaction)
@@ -2954,8 +2924,7 @@ int main (int argc, char *argv[])
 	if (noaction)
 		exit(0);
 
-	if (fs->super->s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+	if (ext2fs_has_feature_journal_dev(fs->super)) {
 		create_journal_dev(fs);
 		printf("\n");
 		exit(ext2fs_close_free(&fs) ? 1 : 0);
@@ -2970,7 +2939,7 @@ int main (int argc, char *argv[])
 	fs->stride = fs_stride = fs->super->s_raid_stride;
 	if (!quiet)
 		printf("%s", _("Allocating group tables: "));
-	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+	if (ext2fs_has_feature_flex_bg(fs->super) &&
 	    packed_meta_blocks)
 		retval = packed_allocate_tables(fs);
 	else
@@ -3041,8 +3010,7 @@ int main (int argc, char *argv[])
 		create_lost_and_found(fs);
 		reserve_inodes(fs);
 		create_bad_block_inode(fs, bb_list);
-		if (fs->super->s_feature_compat &
-		    EXT2_FEATURE_COMPAT_RESIZE_INODE) {
+		if (ext2fs_has_feature_resize_inode(fs->super)) {
 			retval = ext2fs_create_resize_inode(fs);
 			if (retval) {
 				com_err("ext2fs_create_resize_inode", retval,
@@ -3087,8 +3055,7 @@ int main (int argc, char *argv[])
 		ext2fs_close_free(&jfs);
 		free(journal_device);
 	} else if ((journal_size) ||
-		   (fs_param.s_feature_compat &
-		    EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+		   ext2fs_has_feature_journal(&fs_param)) {
 		if (super_only) {
 			printf("%s", _("Skipping journal creation in super-only mode\n"));
 			fs->super->s_journal_inum = EXT2_JOURNAL_INO;
@@ -3096,8 +3063,7 @@ int main (int argc, char *argv[])
 		}
 
 		if (!journal_blocks) {
-			fs->super->s_feature_compat &=
-				~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			ext2fs_clear_feature_journal(fs->super);
 			goto no_journal;
 		}
 		if (!quiet) {
@@ -3118,7 +3084,7 @@ int main (int argc, char *argv[])
 	}
 no_journal:
 	if (!super_only &&
-	    fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) {
+	    ext2fs_has_feature_mmp(fs->super)) {
 		retval = ext2fs_mmp_init(fs);
 		if (retval) {
 			fprintf(stderr, "%s",
@@ -3132,11 +3098,9 @@ no_journal:
 			       fs->super->s_mmp_update_interval);
 	}
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (ext2fs_has_feature_bigalloc(&fs_param))
 		fix_cluster_bg_counts(fs);
-	if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
-				       EXT4_FEATURE_RO_COMPAT_QUOTA))
+	if (ext2fs_has_feature_quota(&fs_param))
 		create_quota_inodes(fs);
 
 	retval = mk_hugefiles(fs, device_name);
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 2f27d6f..8bde640 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -191,8 +191,7 @@ static int get_journal_sb(ext2_filsys jfs, char buf[SUPERBLOCK_SIZE])
 	int retval;
 	journal_superblock_t *jsb;
 
-	if (!(jfs->super->s_feature_incompat &
-	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+	if (!ext2fs_has_feature_journal_dev(jfs->super)) {
 		return EXT2_ET_UNSUPP_FEATURE;
 	}
 
@@ -479,8 +478,7 @@ static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino,
 	struct ext2_extent_info	info;
 
 	if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
-	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	    !ext2fs_has_feature_metadata_csum(fs->super))
 		return 0;
 
 	errcode = ext2fs_extent_open(fs, ino, &handle);
@@ -559,8 +557,7 @@ static int rewrite_dir_block(ext2_filsys fs,
 		ext2fs_get_dx_countlimit(fs, (struct ext2_dir_entry *)ctx->buf,
 					 &dcl, &dcl_offset);
 	if (dcl) {
-		if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+		if (!ext2fs_has_feature_metadata_csum(fs->super)) {
 			/* Ensure limit is the max size */
 			int max_entries = (fs->blocksize - dcl_offset) /
 					  sizeof(struct ext2_dx_entry);
@@ -609,8 +606,7 @@ static int rewrite_dir_block(ext2_filsys fs,
 			return BLOCK_ABORT;
 		name_size = ext2fs_dirent_name_len(last_de);
 
-		if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+		if (!ext2fs_has_feature_metadata_csum(fs->super)) {
 			if (!penultimate_de)
 				return 0;
 			if (last_de->inode ||
@@ -832,8 +828,7 @@ static void rewrite_metadata_checksums(ext2_filsys fs)
 	ext2fs_mmp_update2(fs, 1);
 	fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
 	fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM;
 	else
 		fs->super->s_checksum_type = 0;
@@ -1004,8 +999,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
 				"read-only.\n"), stderr);
 			return 1;
 		}
-		if ((sb->s_feature_incompat &
-		    EXT3_FEATURE_INCOMPAT_RECOVER) &&
+		if (ext2fs_has_feature_journal_needs_recovery(sb) &&
 		    f_flag < 2) {
 			fputs(_("The needs_recovery flag is set.  "
 				"Please run e2fsck before clearing\n"
@@ -1024,8 +1018,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
 
 	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
 		EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-		if (sb->s_feature_incompat &
-			EXT2_FEATURE_INCOMPAT_META_BG) {
+		if (ext2fs_has_feature_meta_bg(sb)) {
 			fputs(_("Setting filesystem feature 'sparse_super' "
 				"not supported\nfor filesystems with "
 				"the meta_bg feature enabled.\n"),
@@ -1108,7 +1101,7 @@ mmp_error:
 		 */
 		if (!journal_size)
 			journal_size = -1;
-		sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+		ext2fs_clear_feature_journal(sb);
 	}
 
 	if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) {
@@ -1148,16 +1141,14 @@ mmp_error:
 				"filesystem!\n"), stderr);
 			exit(1);
 		}
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				EXT3_FEATURE_INCOMPAT_EXTENTS))
+		if (!ext2fs_has_feature_extents(fs->super))
 			printf("%s",
 			       _("Extents are not enabled.  The file extent "
 				 "tree can be checksummed, whereas block maps "
 				 "cannot.  Not enabling extents reduces the "
 				 "coverage of metadata checksumming.  "
 				 "Re-run with -O extent to rectify.\n"));
-		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_INCOMPAT_64BIT))
+		if (!ext2fs_has_feature_64bit(fs->super))
 			printf("%s",
 			       _("64-bit filesystem support is not enabled.  "
 				 "The larger fields afforded by this feature "
@@ -1165,8 +1156,7 @@ mmp_error:
 				 "Run resize2fs -b to rectify.\n"));
 		rewrite_checksums = 1;
 		/* metadata_csum supersedes uninit_bg */
-		fs->super->s_feature_ro_compat &=
-			~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+		ext2fs_clear_feature_gdt_csum(fs->super);
 
 		/* if uninit_bg was previously off, rewrite group desc */
 		if (!(old_features[E2P_FEATURE_RO_INCOMPAT] &
@@ -1202,15 +1192,13 @@ mmp_error:
 				  clear_ok_features, NULL, NULL);
 		if (test_features[E2P_FEATURE_RO_INCOMPAT] &
 						EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
-			fs->super->s_feature_ro_compat |=
-						EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+			ext2fs_set_feature_gdt_csum(fs->super);
 
 		/*
 		 * If we're turning off metadata_csum and not turning on
 		 * uninit_bg, rewrite group desc.
 		 */
-		if (!(fs->super->s_feature_ro_compat &
-		      EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+		if (!ext2fs_has_feature_gdt_csum(fs->super)) {
 			err = disable_uninit_bg(fs,
 					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
 			if (err)
@@ -1229,10 +1217,8 @@ mmp_error:
 	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
 		       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
 		/* Do not enable uninit_bg when metadata_csum enabled */
-		if (fs->super->s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
-			fs->super->s_feature_ro_compat &=
-				~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+		if (ext2fs_has_feature_metadata_csum(fs->super))
+			ext2fs_clear_feature_gdt_csum(fs->super);
 		else
 			enable_uninit_bg(fs);
 	}
@@ -1257,7 +1243,7 @@ mmp_error:
 					  "while mounted!\n"));
 			exit(1);
 		}
-		sb->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_64BIT;
+		ext2fs_clear_feature_64bit(sb);
 		feature_64bit = 1;
 	}
 	if (FEATURE_OFF(E2P_FEATURE_INCOMPAT,
@@ -1267,7 +1253,7 @@ mmp_error:
 					  "while mounted!\n"));
 			exit(1);
 		}
-		sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
+		ext2fs_set_feature_64bit(sb);
 		feature_64bit = -1;
 	}
 
@@ -1283,7 +1269,7 @@ mmp_error:
 			usrquota = QOPT_ENABLE;
 			grpquota = QOPT_ENABLE;
 		}
-		sb->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
+		ext2fs_clear_feature_quota(sb);
 	}
 
 	if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
@@ -1343,8 +1329,7 @@ static int add_journal(ext2_filsys fs)
 	ext2_filsys	jfs;
 	io_manager	io_ptr;
 
-	if (fs->super->s_feature_compat &
-	    EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
+	if (ext2fs_has_feature_journal(fs->super)) {
 		fputs(_("The filesystem already has a journal.\n"), stderr);
 		goto err;
 	}
@@ -1450,11 +1435,11 @@ static void handle_quota_options(ext2_filsys fs)
 	quota_release_context(&qctx);
 
 	if ((usrquota == QOPT_ENABLE) || (grpquota == QOPT_ENABLE)) {
-		fs->super->s_feature_ro_compat |= EXT4_FEATURE_RO_COMPAT_QUOTA;
+		ext2fs_set_feature_quota(fs->super);
 		ext2fs_mark_super_dirty(fs);
 	} else if (!fs->super->s_usr_quota_inum &&
 		   !fs->super->s_grp_quota_inum) {
-		fs->super->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
+		ext2fs_clear_feature_quota(fs->super);
 		ext2fs_mark_super_dirty(fs);
 	}
 
@@ -2594,8 +2579,7 @@ fs_update_journal_user(struct ext2_super_block *sb, __u8 old_uuid[UUID_SIZE])
 	char uuid[UUID_STR_SIZE];
 	char buf[SUPERBLOCK_SIZE] __attribute__ ((aligned(8)));
 
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) ||
-		uuid_is_null(sb->s_journal_uuid))
+	if (!ext2fs_has_feature_journal(sb) || uuid_is_null(sb->s_journal_uuid))
 		return 0;
 
 	uuid_unparse(sb->s_journal_uuid, uuid);
@@ -2725,8 +2709,7 @@ retry_open:
 		ext2fs_free(fs);
 		exit(1);
 	}
-	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+	if (ext2fs_has_feature_journal_dev(fs->super)) {
 		fprintf(stderr, "%s", _("Cannot modify a journal device.\n"));
 		ext2fs_free(fs);
 		exit(1);
@@ -2855,12 +2838,10 @@ retry_open:
 		       reserved_blocks);
 	}
 	if (s_flag == 1) {
-		if (sb->s_feature_ro_compat &
-		    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
+		if (ext2fs_has_feature_sparse_super(sb)) {
 			fputs(_("\nThe filesystem already has sparse "
 				"superblocks.\n"), stderr);
-		} else if (sb->s_feature_incompat &
-			EXT2_FEATURE_INCOMPAT_META_BG) {
+		} else if (ext2fs_has_feature_meta_bg(sb)) {
 			fputs(_("\nSetting the sparse superblock flag not "
 				"supported\nfor filesystems with "
 				"the meta_bg feature enabled.\n"),
@@ -2868,8 +2849,7 @@ retry_open:
 			rc = 1;
 			goto closefs;
 		} else {
-			sb->s_feature_ro_compat |=
-				EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			ext2fs_set_feature_sparse_super(sb);
 			sb->s_state &= ~EXT2_VALID_FS;
 			ext2fs_mark_super_dirty(fs);
 			printf(_("\nSparse superblock flag set.  %s"),
@@ -3025,8 +3005,7 @@ retry_open:
 		}
 
 		ext2fs_mark_super_dirty(fs);
-		if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		if (ext2fs_has_feature_metadata_csum(fs->super))
 			rewrite_checksums = 1;
 	}
 
@@ -3038,8 +3017,7 @@ retry_open:
 			rc = 1;
 			goto closefs;
 		}
-		if (fs->super->s_feature_incompat &
-		    EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+		if (ext2fs_has_feature_flex_bg(fs->super)) {
 			fputs(_("Changing the inode size not supported for "
 				"filesystems with the flex_bg\n"
 				"feature enabled.\n"),


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 06/12] resize2fs: clean up feature test macros with predicate functions
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (4 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 05/12] misc: " Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-24  5:24   ` Theodore Ts'o
  2015-10-12 21:57 ` [PATCH 07/12] debugfs: " Darrick J. Wong
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Create separate predicate functions to test/set/clear feature flags,
thereby replacing the wordy old macros.  Furthermore, clean out the
places where we open-coded feature tests.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 resize/main.c      |   13 ++++------
 resize/online.c    |   11 +++-----
 resize/resize2fs.c |   70 +++++++++++++++++++++-------------------------------
 3 files changed, 37 insertions(+), 57 deletions(-)


diff --git a/resize/main.c b/resize/main.c
index 3be458f..f25df40 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -158,8 +158,7 @@ static void determine_fs_stride(ext2_filsys fs)
 
 static void bigalloc_check(ext2_filsys fs, int force)
 {
-	if (!force && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+	if (!force && ext2fs_has_feature_bigalloc(fs->super)) {
 		fprintf(stderr, "%s", _("\nResizing bigalloc file systems has "
 					"not been fully tested.  Proceed at\n"
 					"your own risk!  Use the force option "
@@ -511,8 +510,7 @@ int main (int argc, char ** argv)
 	if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) {
 		new_size = ext2fs_blocks_count(fs->super);
 	}
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_INCOMPAT_64BIT)) {
+	if (!ext2fs_has_feature_64bit(fs->super)) {
 		/* Take 16T down to 2^32-1 blocks */
 		if (new_size == (1ULL << 32))
 			new_size--;
@@ -578,8 +576,7 @@ int main (int argc, char ** argv)
 			exit(1);
 		}
 		if (flags & RESIZE_ENABLE_64BIT &&
-		    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+		    !ext2fs_has_feature_extents(fs->super)) {
 			fprintf(stderr, _("Please enable the extents feature "
 				"with tune2fs before enabling the 64bit "
 				"feature.\n"));
@@ -592,12 +589,12 @@ int main (int argc, char ** argv)
 		exit(0);
 	}
 	if ((flags & RESIZE_ENABLE_64BIT) &&
-	    EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_64BIT)) {
+	    ext2fs_has_feature_64bit(fs->super)) {
 		fprintf(stderr, _("The filesystem is already 64-bit.\n"));
 		exit(0);
 	}
 	if ((flags & RESIZE_DISABLE_64BIT) &&
-	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_64BIT)) {
+	    !ext2fs_has_feature_64bit(fs->super)) {
 		fprintf(stderr, _("The filesystem is already 32-bit.\n"));
 		exit(0);
 	}
diff --git a/resize/online.c b/resize/online.c
index 46d86b0..9a4d828 100644
--- a/resize/online.c
+++ b/resize/online.c
@@ -76,8 +76,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
 			no_resize_ioctl = 1;
 	}
 
-	if (EXT2_HAS_COMPAT_FEATURE(fs->super,
-				    EXT4_FEATURE_COMPAT_SPARSE_SUPER2) &&
+	if (ext2fs_has_feature_sparse_super2(fs->super) &&
 	    (access("/sys/fs/ext4/features/sparse_super2", R_OK) != 0)) {
 		com_err(program_name, 0, _("kernel does not support online "
 					   "resize with sparse_super2"));
@@ -109,16 +108,14 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
 	 */
 	if ((access("/sys/fs/ext4/features/meta_bg_resize", R_OK) != 0) ||
 	    no_meta_bg_resize) {
-		if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
-					EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
+		if (!ext2fs_has_feature_resize_inode(fs->super) &&
 		    (new_desc_blocks != fs->desc_blocks)) {
 			com_err(program_name, 0,
 				_("Filesystem does not support online resizing"));
 			exit(1);
 		}
 
-		if (EXT2_HAS_COMPAT_FEATURE(fs->super,
-					EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
+		if (ext2fs_has_feature_resize_inode(fs->super) &&
 		    new_desc_blocks > (fs->desc_blocks +
 				       fs->super->s_reserved_gdt_blocks)) {
 			com_err(program_name, 0,
@@ -213,7 +210,7 @@ errcode_t online_resize_fs(ext2_filsys fs, const char *mtpt,
 	 * the layout advantages of flex_bg in the new block groups,
 	 * but at least it allows on-line resizing to function.
 	 */
-	new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
+	ext2fs_clear_feature_flex_bg(new_fs->super);
 	retval = adjust_fs_info(new_fs, fs, 0, *new_size);
 	if (retval) {
 		close(fd);
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 07c6a0c..f8df679 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -258,8 +258,7 @@ errout:
 /* Keep the size of the group descriptor region constant */
 static void adjust_reserved_gdt_blocks(ext2_filsys old_fs, ext2_filsys fs)
 {
-	if ((fs->super->s_feature_compat &
-	     EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
+	if (ext2fs_has_feature_resize_inode(fs->super) &&
 	    (old_fs->desc_blocks != fs->desc_blocks)) {
 		int new;
 
@@ -291,12 +290,10 @@ static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size)
 		return EXT2_ET_INVALID_ARGUMENT;
 
 	if (rfs->flags & RESIZE_DISABLE_64BIT) {
-		rfs->new_fs->super->s_feature_incompat &=
-				~EXT4_FEATURE_INCOMPAT_64BIT;
+		ext2fs_clear_feature_64bit(rfs->new_fs->super);
 		rfs->new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE;
 	} else if (rfs->flags & RESIZE_ENABLE_64BIT) {
-		rfs->new_fs->super->s_feature_incompat |=
-				EXT4_FEATURE_INCOMPAT_64BIT;
+		ext2fs_set_feature_64bit(rfs->new_fs->super);
 		rfs->new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
 	}
 
@@ -358,8 +355,7 @@ static errcode_t move_bg_metadata(ext2_resize_t rfs)
 	if (retval)
 		goto out;
 
-	if (EXT2_HAS_INCOMPAT_FEATURE(rfs->old_fs->super,
-				      EXT2_FEATURE_INCOMPAT_META_BG)) {
+	if (ext2fs_has_feature_meta_bg(rfs->old_fs->super)) {
 		old_desc_blocks = rfs->old_fs->super->s_first_meta_bg;
 		new_desc_blocks = rfs->new_fs->super->s_first_meta_bg;
 	} else {
@@ -820,10 +816,9 @@ retry:
 	if (EXT2_DESC_SIZE(old_fs->super) == EXT2_DESC_SIZE(fs->super))
 		adjust_reserved_gdt_blocks(old_fs, fs);
 
-	if ((fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
+	if (ext2fs_has_feature_meta_bg(fs->super) &&
 	    (fs->super->s_first_meta_bg > fs->desc_blocks)) {
-		fs->super->s_feature_incompat &=
-			~EXT2_FEATURE_INCOMPAT_META_BG;
+		ext2fs_clear_feature_meta_bg(fs->super);
 		fs->super->s_first_meta_bg = 0;
 	}
 
@@ -831,7 +826,7 @@ retry:
 	 * Update the location of the backup superblocks if the
 	 * sparse_super2 feature is enabled.
 	 */
-	if (fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+	if (ext2fs_has_feature_sparse_super2(fs->super)) {
 		dgrp_t last_bg = fs->group_desc_count - 1;
 		dgrp_t old_last_bg = old_fs->group_desc_count - 1;
 
@@ -907,7 +902,7 @@ retry:
 	if (!getenv("RESIZE2FS_FORCE_ITABLE_INIT") &&
 	    access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0)
 		lazy_itable_init = 1;
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks = fs->desc_blocks +
@@ -948,8 +943,7 @@ retry:
 		}
 		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
 		meta_bg = i / meta_bg_size;
-		if (!(fs->super->s_feature_incompat &
-		      EXT2_FEATURE_INCOMPAT_META_BG) ||
+		if (!ext2fs_has_feature_meta_bg(fs->super) ||
 		    (meta_bg < fs->super->s_first_meta_bg)) {
 			if (has_super) {
 				for (j=0; j < old_desc_blocks; j++)
@@ -1197,7 +1191,7 @@ static void mark_fs_metablock(ext2_resize_t rfs,
 		rfs->needed_blocks++;
 		return;
 	}
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+	if (ext2fs_has_feature_flex_bg(fs->super)) {
 		dgrp_t i;
 
 		for (i=0; i < rfs->old_fs->group_desc_count; i++) {
@@ -1333,12 +1327,12 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 		ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
 	}
 
-	if (old_fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(old_fs->super))
 		old_blocks = old_fs->super->s_first_meta_bg;
 	else
 		old_blocks = old_fs->desc_blocks +
 			old_fs->super->s_reserved_gdt_blocks;
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		new_blocks = fs->super->s_first_meta_bg;
 	else
 		new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
@@ -1411,8 +1405,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 	 * gets interesting....
 	 */
 	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
-	flex_bg = fs->super->s_feature_incompat &
-		EXT4_FEATURE_INCOMPAT_FLEX_BG;
+	flex_bg = ext2fs_has_feature_flex_bg(fs->super);
 	/* first reserve all of the existing fs meta blocks */
 	for (i = 0; i < max_groups; i++) {
 		has_super = ext2fs_bg_has_super(fs, i);
@@ -1420,8 +1413,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 			mark_fs_metablock(rfs, meta_bmap, i, group_blk);
 
 		meta_bg = i / meta_bg_size;
-		if (!(fs->super->s_feature_incompat &
-		      EXT2_FEATURE_INCOMPAT_META_BG) ||
+		if (!ext2fs_has_feature_meta_bg(fs->super) ||
 		    (meta_bg < fs->super->s_first_meta_bg)) {
 			if (has_super) {
 				for (blk = group_blk+1;
@@ -1886,8 +1878,7 @@ static errcode_t migrate_ea_block(ext2_resize_t rfs, ext2_ino_t ino,
 	ext2fs_file_acl_block_set(rfs->old_fs, inode, new_block);
 
 	/* Update checksum */
-	if (EXT2_HAS_RO_COMPAT_FEATURE(rfs->new_fs->super,
-			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+	if (ext2fs_has_feature_metadata_csum(rfs->new_fs->super)) {
 		err = ext2fs_get_mem(rfs->old_fs->blocksize, &buf);
 		if (err)
 			return err;
@@ -2076,8 +2067,7 @@ remap_blocks:
 			goto errout;
 
 		/* Rewrite extent block checksums with new inode number */
-		if (EXT2_HAS_RO_COMPAT_FEATURE(rfs->old_fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+		if (ext2fs_has_feature_metadata_csum(rfs->old_fs->super) &&
 		    (inode->i_flags & EXT4_EXTENTS_FL)) {
 			rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
 			retval = rewrite_extents(rfs->old_fs, new_inode);
@@ -2172,8 +2162,7 @@ static int check_and_change_inodes(ext2_ino_t dir,
 	 * If we have checksums enabled and the inode wasn't present in the
 	 * old fs, then we must rewrite all dir blocks with new checksums.
 	 */
-	if (EXT2_HAS_RO_COMPAT_FEATURE(is->rfs->old_fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+	if (ext2fs_has_feature_metadata_csum(is->rfs->old_fs->super) &&
 	    !ext2fs_test_inode_bitmap2(is->rfs->old_fs->inode_map, dir))
 		ret |= DIRENT_CHANGED;
 
@@ -2442,7 +2431,7 @@ static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs)
 	blk64_t		sb, old_desc;
 	blk_t		num;
 
-	if (!(fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2))
+	if (!ext2fs_has_feature_sparse_super2(fs->super))
 		return 0;
 
 	if (last_bg <= old_last_bg)
@@ -2492,7 +2481,7 @@ static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
 	blk_t		i, num;
 	int		realloc = 0;
 
-	if (!(fs->super->s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2))
+	if (!ext2fs_has_feature_sparse_super2(fs->super))
 		return 0;
 
 	if (last_bg >= old_last_bg)
@@ -2576,8 +2565,7 @@ static errcode_t fix_resize_inode(ext2_filsys fs)
 	struct ext2_inode	inode;
 	errcode_t		retval;
 
-	if (!(fs->super->s_feature_compat &
-	      EXT2_FEATURE_COMPAT_RESIZE_INODE))
+	if (!ext2fs_has_feature_resize_inode(fs->super))
 		return 0;
 
 	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
@@ -2634,7 +2622,7 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
 	ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk,
 				  &new_desc_blk, 0);
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks = fs->desc_blocks +
@@ -2671,8 +2659,7 @@ static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
 			ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
 						  &old_desc_blk,
 						  &new_desc_blk, 0);
-			if (fs->super->s_feature_incompat &
-			    EXT2_FEATURE_INCOMPAT_META_BG)
+			if (ext2fs_has_feature_meta_bg(fs->super))
 				old_desc_blocks = fs->super->s_first_meta_bg;
 			else
 				old_desc_blocks = fs->desc_blocks +
@@ -2724,7 +2711,7 @@ static errcode_t fix_sb_journal_backup(ext2_filsys fs)
 	errcode_t	  retval;
 	struct ext2_inode inode;
 
-	if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+	if (!ext2fs_has_feature_journal(fs->super))
 		return 0;
 
 	/* External journal? Nothing to do. */
@@ -2796,7 +2783,7 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 	/*
 	 * number of old-style block group descriptor blocks
 	 */
-	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+	if (ext2fs_has_feature_meta_bg(fs->super))
 		old_desc_blocks = fs->super->s_first_meta_bg;
 	else
 		old_desc_blocks = fs->desc_blocks +
@@ -2819,7 +2806,7 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 	 * guaranteed to finish.
 	 */
 	flex_groups = groups;
-	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+	if (ext2fs_has_feature_flex_bg(fs->super)) {
 		dgrp_t remainder = groups & (flexbg_size - 1);
 
 		flex_groups += flexbg_size - remainder;
@@ -2877,8 +2864,7 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 
 		grp = flex_groups;
 		groups += extra_grps;
-		if (!(fs->super->s_feature_incompat &
-		      EXT4_FEATURE_INCOMPAT_FLEX_BG))
+		if (!ext2fs_has_feature_flex_bg(fs->super))
 			flex_groups = groups;
 		else if (groups > flex_groups) {
 			dgrp_t r = groups & (flexbg_size - 1);
@@ -2914,7 +2900,7 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 
 	/* now for the fun voodoo */
 	grp = groups - 1;
-	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+	if (ext2fs_has_feature_flex_bg(fs->super) &&
 	    (grp & ~(flexbg_size - 1)) == 0)
 		grp = grp & ~(flexbg_size - 1);
 	overhead = 0;
@@ -3000,7 +2986,7 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 	 * with each data block needs to be in its own extent, and
 	 * with each inode needing at least one extent block.
 	 */
-	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
+	if (ext2fs_has_feature_extents(fs->super)) {
 		blk64_t safe_margin = (ext2fs_blocks_count(fs->super) -
 				       blks_needed)/500;
 		unsigned int exts_per_blk = (fs->blocksize /


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 07/12] debugfs: clean up feature test macros with predicate functions
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (5 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 06/12] resize2fs: " Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-24  5:26   ` Theodore Ts'o
  2015-10-12 21:57 ` [PATCH 08/12] libext2fs: store checksum seed in superblock Darrick J. Wong
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Create separate predicate functions to test/set/clear feature flags,
thereby replacing the wordy old macros.  Furthermore, clean out the
places where we open-coded feature tests.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 contrib/add_ext4_encrypt.c |    5 +-
 debugfs/debugfs.c          |    6 +--
 debugfs/do_journal.c       |   91 ++++++++++++++++----------------------------
 debugfs/filefrag.c         |    3 -
 debugfs/htree.c            |    6 +--
 debugfs/journal.c          |   37 +++++++-----------
 debugfs/logdump.c          |    2 -
 debugfs/quota.c            |    3 -
 8 files changed, 57 insertions(+), 96 deletions(-)


diff --git a/contrib/add_ext4_encrypt.c b/contrib/add_ext4_encrypt.c
index 73008dc..d4e7c8c 100644
--- a/contrib/add_ext4_encrypt.c
+++ b/contrib/add_ext4_encrypt.c
@@ -42,9 +42,8 @@ int main (int argc, char *argv[])
 			argv[1]);
 		exit(1);
 	}
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
-		fs->super->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_ENCRYPT;
+	if (!ext2fs_has_feature_encrypt(fs->super)) {
+		ext2fs_set_feature_encrypt(fs->super);
 		fs->super->s_encrypt_algos[0] =
 			EXT4_ENCRYPTION_MODE_AES_256_XTS;
 		fs->super->s_encrypt_algos[1] =
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 583cf8b..175fb90 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -436,8 +436,7 @@ void do_show_super_stats(int argc, char *argv[])
 		return;
 	out = open_pager();
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super,
-				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+	if (ext2fs_has_feature_bigalloc(current_fs->super))
 		units = "cluster";
 
 	list_super2(current_fs->super, out);
@@ -893,8 +892,7 @@ void internal_dump_inode(FILE *out, const char *prefix,
 					  (struct ext2_inode_large *) inode);
 	dump_inode_attributes(out, inode_num);
 	if (current_fs->super->s_creator_os == EXT2_OS_LINUX &&
-	    current_fs->super->s_feature_ro_compat &
-		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+	    ext2fs_has_feature_metadata_csum(current_fs->super)) {
 		__u32 crc = inode->i_checksum_lo;
 		if (is_large_inode &&
 		    large_inode->i_extra_isize >=
diff --git a/debugfs/do_journal.c b/debugfs/do_journal.c
index 5c2c2a2..b8c1e59 100644
--- a/debugfs/do_journal.c
+++ b/debugfs/do_journal.c
@@ -88,8 +88,7 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
 	commit->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
 	commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK);
 	commit->h_sequence = ext2fs_cpu_to_be32(trans->tid);
-	if (JFS_HAS_COMPAT_FEATURE(trans->journal,
-				   JFS_FEATURE_COMPAT_CHECKSUM)) {
+	if (jfs_has_feature_checksum(trans->journal)) {
 		__u32 csum_v1 = ~0;
 		blk64_t cblk;
 
@@ -149,7 +148,7 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
 	trans->flags &= ~J_TRANS_OPEN;
 	trans->block++;
 
-	trans->fs->super->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
+	ext2fs_set_feature_journal_needs_recovery(trans->fs->super);
 	ext2fs_mark_super_dirty(trans->fs);
 error:
 	if (cbh)
@@ -195,8 +194,7 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
 	jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
 	offset = sizeof(*jrb);
 
-	if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
-				     JFS_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(trans->journal))
 		sz = 8;
 	else
 		sz = 4;
@@ -229,8 +227,7 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
 			goto error;
 		}
 
-		if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
-					     JFS_FEATURE_INCOMPAT_64BIT))
+		if (jfs_has_feature_64bit(trans->journal))
 			*((__u64 *)(&((char *)buf)[offset])) =
 				ext2fs_cpu_to_be64(revoke_list[i]);
 		else
@@ -364,8 +361,7 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
 			*((__u32 *)buf) = 0;
 			jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE);
 		}
-		if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
-					     JFS_FEATURE_INCOMPAT_64BIT))
+		if (jfs_has_feature_64bit(trans->journal))
 			jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32);
 		jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh,
 					trans->tid);
@@ -421,8 +417,7 @@ static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
 	bs = journal->j_blocksize;
 	if (journal_has_csum_v2or3(journal))
 		bs -= sizeof(struct journal_revoke_tail);
-	sz = JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) ?
-				sizeof(__u64) : sizeof(__u32);
+	sz = jfs_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32);
 	ret += revoke_blocks * sz / bs;
 
 	/* Estimate # of data blocks */
@@ -489,10 +484,8 @@ static errcode_t journal_close_trans(journal_transaction_t *trans)
 	trans->magic = 0;
 
 	/* Mark ourselves as needing recovery */
-	if (!(EXT2_HAS_INCOMPAT_FEATURE(trans->fs->super,
-					EXT3_FEATURE_INCOMPAT_RECOVER))) {
-		trans->fs->super->s_feature_incompat |=
-					EXT3_FEATURE_INCOMPAT_RECOVER;
+	if (!ext2fs_has_feature_journal_needs_recovery(trans->fs->super)) {
+		ext2fs_set_feature_journal_needs_recovery(trans->fs->super);
 		ext2fs_mark_super_dirty(trans->fs);
 	}
 
@@ -510,8 +503,7 @@ static errcode_t journal_write(journal_t *journal,
 	errcode_t err;
 
 	if (revoke_len > 0) {
-		journal->j_superblock->s_feature_incompat |=
-				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_REVOKE);
+		jfs_set_feature_revoke(journal);
 		mark_buffer_dirty(journal->j_sb_buffer);
 	}
 
@@ -774,33 +766,26 @@ static void update_journal_csum(journal_t *journal, int ver)
 		return;
 
 	if (journal->j_tail != 0 ||
-	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
-				      EXT3_FEATURE_INCOMPAT_RECOVER)) {
+	    ext2fs_has_feature_journal_needs_recovery(
+					journal->j_fs_dev->k_fs->super)) {
 		printf("Journal needs recovery, will not add csums.\n");
 		return;
 	}
 
 	/* metadata_csum implies journal csum v3 */
 	jsb = journal->j_superblock;
-	if (EXT2_HAS_RO_COMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+	if (ext2fs_has_feature_metadata_csum(journal->j_fs_dev->k_fs->super)) {
 		printf("Setting csum v%d\n", ver);
 		switch (ver) {
 		case 2:
-			journal->j_superblock->s_feature_incompat &=
-				ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V3);
-			journal->j_superblock->s_feature_incompat |=
-				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2);
-			journal->j_superblock->s_feature_compat &=
-				ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
+			jfs_clear_feature_csum3(journal);
+			jfs_set_feature_csum2(journal);
+			jfs_clear_feature_checksum(journal);
 			break;
 		case 3:
-			journal->j_superblock->s_feature_incompat &=
-				ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V2);
-			journal->j_superblock->s_feature_incompat |=
-				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3);
-			journal->j_superblock->s_feature_compat &=
-				ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
+			jfs_set_feature_csum3(journal);
+			jfs_clear_feature_csum2(journal);
+			jfs_clear_feature_checksum(journal);
 			break;
 		default:
 			printf("Unknown checksum v%d\n", ver);
@@ -810,11 +795,9 @@ static void update_journal_csum(journal_t *journal, int ver)
 		journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
 						   sizeof(jsb->s_uuid));
 	} else {
-		journal->j_superblock->s_feature_compat |=
-			ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM);
-		journal->j_superblock->s_feature_incompat &=
-			ext2fs_cpu_to_be32(~(JFS_FEATURE_INCOMPAT_CSUM_V2 |
-					     JFS_FEATURE_INCOMPAT_CSUM_V3));
+		jfs_clear_feature_csum3(journal);
+		jfs_clear_feature_csum2(journal);
+		jfs_set_feature_checksum(journal);
 	}
 }
 
@@ -833,18 +816,15 @@ static void update_uuid(journal_t *journal)
 		return;
 
 	fs = journal->j_fs_dev->k_fs;
-	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_INCOMPAT_64BIT))
+	if (!ext2fs_has_feature_64bit(fs->super))
 		return;
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
-	    EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT4_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(journal) &&
+	    ext2fs_has_feature_64bit(fs->super))
 		return;
 
 	if (journal->j_tail != 0 ||
-	    EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-				      EXT3_FEATURE_INCOMPAT_RECOVER)) {
+	    ext2fs_has_feature_journal_needs_recovery(fs->super)) {
 		printf("Journal needs recovery, will not set 64bit.\n");
 		return;
 	}
@@ -858,24 +838,21 @@ static void update_64bit_flag(journal_t *journal)
 	if (journal->j_format_version < 2)
 		return;
 
-	if (!EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
-				       EXT4_FEATURE_INCOMPAT_64BIT))
+	if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
 		return;
 
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
-	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
-				      EXT4_FEATURE_INCOMPAT_64BIT))
+	if (jfs_has_feature_64bit(journal) &&
+	    ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
 		return;
 
 	if (journal->j_tail != 0 ||
-	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
-				      EXT3_FEATURE_INCOMPAT_RECOVER)) {
+	    ext2fs_has_feature_journal_needs_recovery(
+				journal->j_fs_dev->k_fs->super)) {
 		printf("Journal needs recovery, will not set 64bit.\n");
 		return;
 	}
 
-	journal->j_superblock->s_feature_incompat |=
-				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_64BIT);
+	jfs_set_feature_64bit(journal);
 }
 
 void do_journal_open(int argc, char *argv[])
@@ -894,8 +871,7 @@ void do_journal_open(int argc, char *argv[])
 		printf("Journal is already open.\n");
 		return;
 	}
-	if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
-				     EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+	if (!ext2fs_has_feature_journal(current_fs->super)) {
 		printf("Journalling is not enabled on this filesystem.\n");
 		return;
 	}
@@ -978,8 +954,7 @@ void do_journal_run(int argc EXT2FS_ATTR((unused)), char *argv[])
 	if (err)
 		com_err("journal_run", err, "while recovering journal");
 	else {
-		current_fs->super->s_feature_incompat &=
-				~EXT3_FEATURE_INCOMPAT_RECOVER;
+		ext2fs_clear_feature_journal_needs_recovery(current_fs->super);
 		ext2fs_mark_super_dirty(current_fs);
 	}
 }
diff --git a/debugfs/filefrag.c b/debugfs/filefrag.c
index 49345ad..128598b 100644
--- a/debugfs/filefrag.c
+++ b/debugfs/filefrag.c
@@ -145,8 +145,7 @@ static void filefrag(ext2_ino_t ino, struct ext2_inode *inode,
 	if (fs->options & VERBOSE_OPT) {
 		blk64_t num_blocks = ext2fs_inode_i_blocks(current_fs, inode);
 
-		if (!(current_fs->super->s_feature_ro_compat &
-		     EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+		if (!ext2fs_has_feature_huge_file(current_fs->super) ||
 		    !(inode->i_flags & EXT4_HUGE_FILE_FL))
 			num_blocks /= current_fs->blocksize / 512;
 
diff --git a/debugfs/htree.c b/debugfs/htree.c
index 83f558c..54e55e2 100644
--- a/debugfs/htree.c
+++ b/debugfs/htree.c
@@ -46,8 +46,7 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
 	int		hash_alg;
 	int		csum_size = 0;
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (ext2fs_has_feature_metadata_csum(fs->super))
 		csum_size = sizeof(struct ext2_dir_entry_tail);
 
 	errcode = ext2fs_bmap2(fs, ino, inode, buf, 0, blk, 0, &pblk);
@@ -156,8 +155,7 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
 		remainder -= sizeof(struct ext2_dx_root_info) + 24;
 	else
 		remainder -= 8;
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+	if (ext2fs_has_feature_metadata_csum(fs->super) &&
 	    remainder == sizeof(struct ext2_dx_tail)) {
 		tail = (struct ext2_dx_tail *)(ent + limit);
 		fprintf(pager, "Checksum: 0x%08x\n",
diff --git a/debugfs/journal.c b/debugfs/journal.c
index 9f0d7fc..aa6325d 100644
--- a/debugfs/journal.c
+++ b/debugfs/journal.c
@@ -245,7 +245,7 @@ void wait_on_buffer(struct buffer_head *bh)
 
 static void ext2fs_clear_recover(ext2_filsys fs, int error)
 {
-	fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+	ext2fs_clear_feature_journal_needs_recovery(fs->super);
 
 	/* if we had an error doing journal recovery, we need a full fsck */
 	if (error)
@@ -451,8 +451,7 @@ try_backup_journal:
 			ext2fs_swap_super(&jsuper);
 #endif
 		if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
-		    !(jsuper.s_feature_incompat &
-		      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		    !ext2fs_has_feature_journal_dev(&jsuper)) {
 			retval = EXT2_ET_LOAD_EXT_JOURNAL;
 			brelse(bh);
 			goto errout;
@@ -466,8 +465,7 @@ try_backup_journal:
 		}
 
 		/* Check the superblock checksum */
-		if (jsuper.s_feature_ro_compat &
-		    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+		if (ext2fs_has_feature_metadata_csum(&jsuper)) {
 			struct struct_ext2_filsys fsx;
 			struct ext2_super_block	superx;
 			void *p;
@@ -476,8 +474,7 @@ try_backup_journal:
 			memcpy(&fsx, fs, sizeof(fsx));
 			memcpy(&superx, fs->super, sizeof(superx));
 			fsx.super = &superx;
-			fsx.super->s_feature_ro_compat |=
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+			ext2fs_set_feature_metadata_csum(fsx.super);
 			if (!ext2fs_superblock_csum_verify(&fsx, p)) {
 				retval = EXT2_ET_LOAD_EXT_JOURNAL;
 				brelse(bh);
@@ -522,10 +519,8 @@ errout:
 static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs)
 {
 	struct ext2_super_block *sb = fs->super;
-	int recover = fs->super->s_feature_incompat &
-		EXT3_FEATURE_INCOMPAT_RECOVER;
-	int has_journal = fs->super->s_feature_compat &
-		EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
+	int has_journal = ext2fs_has_feature_journal(fs->super);
 
 	if (has_journal || sb->s_journal_inum) {
 		/* The journal inode is bogus, remove and force full fsck */
@@ -604,12 +599,11 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
 		return EXT2_ET_RO_UNSUPP_FEATURE;
 
 	/* Checksum v1-3 are mutually exclusive features. */
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
-	    JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum2(journal) && jfs_has_feature_csum3(journal))
 		return EXT2_ET_CORRUPT_SUPERBLOCK;
 
 	if (journal_has_csum_v2or3(journal) &&
-	    JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
+	    jfs_has_feature_checksum(journal))
 		return EXT2_ET_CORRUPT_SUPERBLOCK;
 
 	if (!ext2fs_journal_verify_csum_type(journal, jsb) ||
@@ -680,12 +674,11 @@ static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
 {
 	struct ext2_super_block *sb = fs->super;
 	journal_t *journal;
-	int recover = fs->super->s_feature_incompat &
-		EXT3_FEATURE_INCOMPAT_RECOVER;
+	int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
 	errcode_t retval;
 
 	/* If we don't have any journal features, don't do anything more */
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+	if (!ext2fs_has_feature_journal(sb) &&
 	    !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
 	    uuid_is_null(sb->s_journal_uuid))
 		return 0;
@@ -703,13 +696,13 @@ static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
 	 * needs_recovery set but has_journal clear.  We can't get in a loop
 	 * with -y, -n, or -p, only if a user isn't making up their mind.
 	 */
-	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+	if (!ext2fs_has_feature_journal(sb)) {
 		retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
 		goto err;
 	}
 
-	if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
-	    !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+	if (ext2fs_has_feature_journal(sb) &&
+	    !ext2fs_has_feature_journal_needs_recovery(sb) &&
 	    journal->j_superblock->s_start != 0) {
 		retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
 		goto err;
@@ -720,7 +713,7 @@ static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
 	 * the journal's errno is set; if so, we need to mark the file
 	 * system as being corrupt and clear the journal's s_errno.
 	 */
-	if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+	if (!ext2fs_has_feature_journal_needs_recovery(sb) &&
 	    journal->j_superblock->s_errno) {
 		fs->super->s_state |= EXT2_ERROR_FS;
 		ext2fs_mark_super_dirty(fs);
@@ -929,7 +922,7 @@ void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
 	csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
 	csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);
 
-	if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+	if (jfs_has_feature_csum3(j))
 		tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
 	else
 		tag->t_checksum = ext2fs_cpu_to_be16(csum32);
diff --git a/debugfs/logdump.c b/debugfs/logdump.c
index 885e590..bab0ce9 100644
--- a/debugfs/logdump.c
+++ b/debugfs/logdump.c
@@ -364,7 +364,7 @@ static void dump_journal(char *cmdname, FILE *out_file,
 
 	if ((be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) &&
 	    (sb->s_magic == EXT2_SUPER_MAGIC) &&
-	    (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+	    ext2fs_has_feature_journal_dev(sb)) {
 		blocksize = EXT2_BLOCK_SIZE(sb);
 		blocknr = (blocksize == 1024) ? 2 : 1;
 		uuid_unparse(sb->s_uuid, jsb_buffer);
diff --git a/debugfs/quota.c b/debugfs/quota.c
index 7aa0f3b..8c94486 100644
--- a/debugfs/quota.c
+++ b/debugfs/quota.c
@@ -34,8 +34,7 @@ static int load_quota_ctx(char *progname)
 	if (check_fs_open(progname))
 		return 1;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super,
-					EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+	if (!ext2fs_has_feature_quota(current_fs->super)) {
 		com_err(progname, 0, "quota feature not enabled");
 		return 1;
 	}


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 08/12] libext2fs: store checksum seed in superblock
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (6 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 07/12] debugfs: " Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-12 21:57 ` [PATCH 09/12] tune2fs: allow user to turn on saving the checksum seed Darrick J. Wong
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Allow the filesystem to store the metadata checksum seed in the
superblock and add an incompat feature to say that we're using it.
This enables tune2fs to change the UUID on a mounted metadata_csum
FS without having to (racy!) rewrite all disk metadata.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 debugfs/set_fields.c        |    1 +
 lib/e2p/feature.c           |    2 ++
 lib/e2p/ls.c                |    4 ++++
 lib/ext2fs/csum.c           |    9 +++++++++
 lib/ext2fs/ext2_fs.h        |    6 ++++--
 lib/ext2fs/ext2fs.h         |   13 +++----------
 lib/ext2fs/swapfs.c         |    1 +
 lib/ext2fs/tst_super_size.c |    3 ++-
 8 files changed, 26 insertions(+), 13 deletions(-)


diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index b14fec9..b9206f6 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -173,6 +173,7 @@ static struct field_set_info super_fields[] = {
 	  FLAG_ARRAY, 4 },
 	{ "encrypt_pw_salt", &set_sb.s_encrypt_pw_salt, NULL, 16, parse_uuid },
 	{ "lpf_ino", &set_sb.s_lpf_ino, NULL, 4, parse_uint },
+	{ "checksum_seed", &set_sb.s_checksum_seed, NULL, 4, parse_uint },
 	{ 0, 0, 0, 0 }
 };
 
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index 737b0b9..35e8435 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -95,6 +95,8 @@ static struct feature feature_list[] = {
 			"ea_inode"},
 	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA,
 			"dirdata"},
+	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+			"metadata_csum_seed"},
 	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR,
 			"large_dir"},
 	{       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA,
diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c
index 6c82857..8df6bb2 100644
--- a/lib/e2p/ls.c
+++ b/lib/e2p/ls.c
@@ -450,6 +450,10 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
 	if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt))
 		fprintf(f, "Encryption PW Salt:       %s\n",
 			e2p_uuid2str(sb->s_encrypt_pw_salt));
+
+	if (ext2fs_has_feature_csum_seed(sb))
+		fprintf(f, "Checksum seed:            0x%08x\n",
+			sb->s_checksum_seed);
 }
 
 void list_super (struct ext2_super_block * s)
diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
index ab8b83f..ccb3057 100644
--- a/lib/ext2fs/csum.c
+++ b/lib/ext2fs/csum.c
@@ -30,6 +30,15 @@
 #define STATIC static
 #endif
 
+void ext2fs_init_csum_seed(ext2_filsys fs)
+{
+	if (ext2fs_has_feature_csum_seed(fs->super))
+		fs->csum_seed = fs->super->s_checksum_seed;
+	else if (ext2fs_has_feature_metadata_csum(fs->super))
+		fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
+						 sizeof(fs->super->s_uuid));
+}
+
 static __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp)
 {
 	int offset = offsetof(struct mmp_struct, mmp_checksum);
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 709838d..7e4d10d 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -719,7 +719,8 @@ struct ext2_super_block {
 	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
 	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
 	__le32	s_lpf_ino;		/* Location of the lost+found inode */
-	__le32	s_reserved[100];	/* Padding to the end of the block */
+	__le32	s_checksum_seed;	/* crc32c(orig_uuid) if csum_seed set */
+	__le32	s_reserved[99];		/* Padding to the end of the block */
 	__u32	s_checksum;		/* crc32c(superblock) */
 };
 
@@ -804,7 +805,7 @@ struct ext2_super_block {
 #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
 #define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400
 #define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000
-/* 0x2000 was EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM but this was never used */
+#define EXT4_FEATURE_INCOMPAT_CSUM_SEED		0x2000
 #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */
 #define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */
 #define EXT4_FEATURE_INCOMPAT_ENCRYPT		0x10000
@@ -894,6 +895,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(mmp,		4, MMP)
 EXT4_FEATURE_INCOMPAT_FUNCS(flex_bg,		4, FLEX_BG)
 EXT4_FEATURE_INCOMPAT_FUNCS(ea_inode,		4, EA_INODE)
 EXT4_FEATURE_INCOMPAT_FUNCS(dirdata,		4, DIRDATA)
+EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed,		4, CSUM_SEED)
 EXT4_FEATURE_INCOMPAT_FUNCS(largedir,		4, LARGEDIR)
 EXT4_FEATURE_INCOMPAT_FUNCS(inline_data,	4, INLINE_DATA)
 EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,		4, ENCRYPT)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 30e913c..d9ea105 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -580,7 +580,8 @@ typedef struct ext2_icount *ext2_icount_t;
 					 EXT4_LIB_INCOMPAT_MMP|\
 					 EXT4_FEATURE_INCOMPAT_64BIT|\
 					 EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
-					 EXT4_FEATURE_INCOMPAT_ENCRYPT)
+					 EXT4_FEATURE_INCOMPAT_ENCRYPT|\
+					 EXT4_FEATURE_INCOMPAT_CSUM_SEED)
 
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
 					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
@@ -985,6 +986,7 @@ extern __u32 ext2fs_crc32_be(__u32 crc, unsigned char const *p, size_t len);
 extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len);
 
 /* csum.c */
+extern void ext2fs_init_csum_seed(ext2_filsys fs);
 extern errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp);
 extern int ext2fs_mmp_csum_verify(ext2_filsys, struct mmp_struct *mmp);
 extern int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb);
@@ -1712,15 +1714,6 @@ extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type);
 #endif /* __STDC_VERSION__ >= 199901L */
 #endif
 
-static inline void ext2fs_init_csum_seed(ext2_filsys fs)
-{
-	if (!ext2fs_has_feature_metadata_csum(fs->super))
-		return;
-
-	fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
-					 sizeof(fs->super->s_uuid));
-}
-
 #ifndef EXT2_CUSTOM_MEMORY_ROUTINES
 #include <string.h>
 /*
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index ee7a455..9d2c535 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -101,6 +101,7 @@ void ext2fs_swap_super(struct ext2_super_block * sb)
 		sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
 	sb->s_backup_bgs[0] = ext2fs_swab32(sb->s_backup_bgs[0]);
 	sb->s_backup_bgs[1] = ext2fs_swab32(sb->s_backup_bgs[1]);
+	sb->s_checksum_seed = ext2fs_swab32(sb->s_checksum_seed);
 }
 
 void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp)
diff --git a/lib/ext2fs/tst_super_size.c b/lib/ext2fs/tst_super_size.c
index 8e3c21f..f815a0f 100644
--- a/lib/ext2fs/tst_super_size.c
+++ b/lib/ext2fs/tst_super_size.c
@@ -140,7 +140,8 @@ int main(int argc, char **argv)
 	check_field(s_encrypt_algos, 4);
 	check_field(s_encrypt_pw_salt, 16);
 	check_field(s_lpf_ino, 4);
-	check_field(s_reserved, 100 * 4);
+	check_field(s_checksum_seed, 4);
+	check_field(s_reserved, 99 * 4);
 	check_field(s_checksum, 4);
 	do_field("Superblock end", 0, 0, cur_offset, 1024);
 #endif


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 09/12] tune2fs: allow user to turn on saving the checksum seed
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (7 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 08/12] libext2fs: store checksum seed in superblock Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-12 21:57 ` [PATCH 10/12] e2fsck: check the checksum seed feature flag is set correctly Darrick J. Wong
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 misc/tune2fs.c |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 6 deletions(-)


diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 8bde640..af7d73c 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -149,7 +149,8 @@ static __u32 ok_features[3] = {
 		EXT4_FEATURE_INCOMPAT_FLEX_BG |
 		EXT4_FEATURE_INCOMPAT_MMP |
 		EXT4_FEATURE_INCOMPAT_64BIT |
-		EXT4_FEATURE_INCOMPAT_ENCRYPT,
+		EXT4_FEATURE_INCOMPAT_ENCRYPT |
+		EXT4_FEATURE_INCOMPAT_CSUM_SEED,
 	/* R/O compat */
 	EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
 		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -171,7 +172,8 @@ static __u32 clear_ok_features[3] = {
 	EXT2_FEATURE_INCOMPAT_FILETYPE |
 		EXT4_FEATURE_INCOMPAT_FLEX_BG |
 		EXT4_FEATURE_INCOMPAT_MMP |
-		EXT4_FEATURE_INCOMPAT_64BIT,
+		EXT4_FEATURE_INCOMPAT_64BIT |
+		EXT4_FEATURE_INCOMPAT_CSUM_SEED,
 	/* R/O compat */
 	EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
 		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -948,6 +950,15 @@ static errcode_t disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
 	return 0;
 }
 
+static void
+try_confirm_csum_seed_support(void)
+{
+	if (access("/sys/fs/ext4/features/metadata_csum_seed", R_OK))
+		fputs(_("WARNING: Could not confirm kernel support for "
+			"metadata_csum_seed.\n  This requires Linux >= "
+			"v4.4.\n"), stderr);
+}
+
 /*
  * Update the feature set as provided by the user.
  */
@@ -1212,6 +1223,8 @@ mmp_error:
 			 */
 			old_features[E2P_FEATURE_RO_INCOMPAT] |=
 				EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+		fs->super->s_checksum_seed = 0;
+		ext2fs_clear_feature_csum_seed(fs->super);
 	}
 
 	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
@@ -1294,6 +1307,37 @@ mmp_error:
 			EXT4_ENCRYPTION_MODE_AES_256_CTS;
 	}
 
+	if (FEATURE_ON(E2P_FEATURE_INCOMPAT,
+		EXT4_FEATURE_INCOMPAT_CSUM_SEED)) {
+		if (!ext2fs_has_feature_metadata_csum(sb)) {
+			fputs(_("Setting feature 'metadata_csum_seed' "
+				"is only supported\non filesystems with "
+				"the metadata_csum feature enabled.\n"),
+				stderr);
+			return 1;
+		}
+		try_confirm_csum_seed_support();
+		fs->super->s_checksum_seed = fs->csum_seed;
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_INCOMPAT,
+		EXT4_FEATURE_INCOMPAT_CSUM_SEED)) {
+		__le32 uuid_seed;
+
+		uuid_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
+					sizeof(fs->super->s_uuid));
+		if (fs->super->s_checksum_seed != uuid_seed &&
+		    (mount_flags & EXT2_MF_MOUNTED)) {
+			fputs(_("UUID has changed since enabling "
+				"metadata_csum.  Filesystem must be unmounted "
+				"\nto safely rewrite all metadata to "
+				"match the new UUID.\n"), stderr);
+			return 1;
+		}
+
+		rewrite_checksums = 1;
+	}
+
 	if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
 	    (sb->s_feature_compat || sb->s_feature_ro_compat ||
 	     sb->s_feature_incompat))
@@ -2937,13 +2981,22 @@ retry_open:
 
 		if (ext2fs_has_group_desc_csum(fs)) {
 			/*
-			 * Changing the UUID requires rewriting all metadata,
-			 * which can race with a mounted fs.  Don't allow that.
+			 * Changing the UUID on a metadata_csum FS requires
+			 * rewriting all metadata, which can race with a
+			 * mounted fs.  Don't allow that unless we're saving
+			 * the checksum seed.
 			 */
-			if ((mount_flags & EXT2_MF_MOUNTED) && !f_flag) {
+			if ((mount_flags & EXT2_MF_MOUNTED) &&
+			    !ext2fs_has_feature_csum_seed(fs->super) &&
+			    ext2fs_has_feature_metadata_csum(fs->super)) {
 				fputs(_("The UUID may only be "
 					"changed when the filesystem is "
 					"unmounted.\n"), stderr);
+				fputs(_("If you only use kernels newer than "
+					"v4.4, run 'tune2fs -O "
+					"metadata_csum_seed' and re-run this "
+					"command.\n"), stderr);
+				try_confirm_csum_seed_support();
 				exit(1);
 			}
 			if (check_fsck_needed(fs))
@@ -3005,7 +3058,8 @@ retry_open:
 		}
 
 		ext2fs_mark_super_dirty(fs);
-		if (ext2fs_has_feature_metadata_csum(fs->super))
+		if (ext2fs_has_feature_metadata_csum(fs->super) &&
+		    !ext2fs_has_feature_csum_seed(fs->super))
 			rewrite_checksums = 1;
 	}
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 10/12] e2fsck: check the checksum seed feature flag is set correctly
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (8 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 09/12] tune2fs: allow user to turn on saving the checksum seed Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-12 21:57 ` [PATCH 11/12] mke2fs: store checksum seed at format time Darrick J. Wong
  2015-10-12 21:57 ` [PATCH 12/12] tests: check proper operation of metadata_csum_seed Darrick J. Wong
  11 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/problem.c |    5 +++++
 e2fsck/problem.h |    3 +++
 e2fsck/super.c   |    9 +++++++++
 3 files changed, 17 insertions(+)


diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index f761ec9..6a35e93 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -467,6 +467,11 @@ static struct e2fsck_problem problem_table[] = {
 	  N_("External @j @S checksum does not match @S.  "),
 	  PROMPT_FIX, PR_PREEN_OK },
 
+	/* metadata_csum_seed means nothing without metadata_csum */
+	{ PR_0_CSUM_SEED_WITHOUT_META_CSUM,
+	  N_("@S metadata_csum_seed is not necessary without metadata_csum."),
+	  PROMPT_FIX, PR_PREEN_OK | PR_NO_OK},
+
 	/* Pass 1 errors */
 
 	/* Pass 1: Checking inodes, blocks, and sizes */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 2ff0f5e..943024b 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -268,6 +268,9 @@ struct problem_context {
 /* External journal has corrupt superblock */
 #define PR_0_EXT_JOURNAL_SUPER_CSUM_INVALID	0x00004A
 
+/* metadata_csum_seed means nothing without metadata_csum */
+#define PR_0_CSUM_SEED_WITHOUT_META_CSUM	0x00004B
+
 /*
  * Pass 1 errors
  */
diff --git a/e2fsck/super.c b/e2fsck/super.c
index af6d680..e09c14c 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -589,6 +589,15 @@ void check_super_block(e2fsck_t ctx)
 			ext2fs_group_desc_csum_set(fs, i);
 	}
 
+	/* We can't have ^metadata_csum,metadata_csum_seed */
+	if (!ext2fs_has_feature_metadata_csum(fs->super) &&
+	    ext2fs_has_feature_csum_seed(fs->super) &&
+	    fix_problem(ctx, PR_0_CSUM_SEED_WITHOUT_META_CSUM, &pctx)) {
+		ext2fs_clear_feature_csum_seed(fs->super);
+		fs->super->s_checksum_seed = 0;
+		ext2fs_mark_super_dirty(fs);
+	}
+
 	/* Is 64bit set and extents unset? */
 	if (ext2fs_has_feature_64bit(fs->super) &&
 	    !ext2fs_has_feature_extents(fs->super) &&


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 11/12] mke2fs: store checksum seed at format time
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (9 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 10/12] e2fsck: check the checksum seed feature flag is set correctly Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  2015-10-12 21:57 ` [PATCH 12/12] tests: check proper operation of metadata_csum_seed Darrick J. Wong
  11 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Allow users to turn on metadata_csum_seed at format time so that UUIDs
can be live-changed at any time.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 misc/mke2fs.c |   15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)


diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9a2a6cc..0c344ae 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1074,7 +1074,8 @@ static __u32 ok_features[3] = {
 		EXT4_FEATURE_INCOMPAT_MMP |
 		EXT4_FEATURE_INCOMPAT_64BIT|
 		EXT4_FEATURE_INCOMPAT_INLINE_DATA|
-		EXT4_FEATURE_INCOMPAT_ENCRYPT,
+		EXT4_FEATURE_INCOMPAT_ENCRYPT |
+		EXT4_FEATURE_INCOMPAT_CSUM_SEED,
 	/* R/O compat */
 	EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
 		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -2775,6 +2776,13 @@ int main (int argc, char *argv[])
 				 "Pass -O 64bit to rectify.\n"));
 	}
 
+	if (ext2fs_has_feature_csum_seed(fs->super) &&
+	    !ext2fs_has_feature_metadata_csum(fs->super)) {
+		printf("%s", _("The metadata_csum_seed feature "
+			       "requres the metadata_csum feature.\n"));
+		exit(1);
+	}
+
 	/* Calculate journal blocks */
 	if (!journal_device && ((journal_size) ||
 	    ext2fs_has_feature_journal(&fs_param)))
@@ -2830,6 +2838,11 @@ int main (int argc, char *argv[])
 		}
 	} else
 		uuid_generate(fs->super->s_uuid);
+
+	if (ext2fs_has_feature_csum_seed(fs->super))
+		fs->super->s_checksum_seed = ext2fs_crc32c_le(~0,
+				fs->super->s_uuid, sizeof(fs->super->s_uuid));
+
 	ext2fs_init_csum_seed(fs);
 
 	/*


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 12/12] tests: check proper operation of metadata_csum_seed
  2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
                   ` (10 preceding siblings ...)
  2015-10-12 21:57 ` [PATCH 11/12] mke2fs: store checksum seed at format time Darrick J. Wong
@ 2015-10-12 21:57 ` Darrick J. Wong
  11 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-12 21:57 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/ismounted.c                           |   14 ++++++
 tests/t_change_uuid/expect                       |    7 +++
 tests/t_change_uuid/script                       |   34 ++++++++++++++
 tests/t_change_uuid_mcsum/expect                 |    7 +++
 tests/t_change_uuid_mcsum/script                 |   34 ++++++++++++++
 tests/t_change_uuid_mcsum_mounted/expect         |    7 +++
 tests/t_change_uuid_mcsum_mounted/script         |   34 ++++++++++++++
 tests/t_change_uuid_mcsum_seed_mounted/expect    |   21 +++++++++
 tests/t_change_uuid_mcsum_seed_mounted/script    |   52 ++++++++++++++++++++++
 tests/t_change_uuid_mounted/expect               |    7 +++
 tests/t_change_uuid_mounted/script               |   34 ++++++++++++++
 tests/t_disable_changed_csum_seed/expect         |   17 +++++++
 tests/t_disable_changed_csum_seed/script         |   47 ++++++++++++++++++++
 tests/t_disable_changed_csum_seed_mounted/expect |   19 ++++++++
 tests/t_disable_changed_csum_seed_mounted/script |   47 ++++++++++++++++++++
 tests/t_disable_csum_seed/expect                 |   14 ++++++
 tests/t_disable_csum_seed/script                 |   43 ++++++++++++++++++
 tests/t_disable_meta_csum_and_seed/expect        |   14 ++++++
 tests/t_disable_meta_csum_and_seed/script        |   44 +++++++++++++++++++
 tests/t_enable_csum_seed/expect                  |   12 +++++
 tests/t_enable_csum_seed/script                  |   38 ++++++++++++++++
 tests/t_format_csum_seed/expect                  |   10 ++++
 tests/t_format_csum_seed/script                  |   34 ++++++++++++++
 23 files changed, 590 insertions(+)
 create mode 100644 tests/t_change_uuid/expect
 create mode 100755 tests/t_change_uuid/script
 create mode 100644 tests/t_change_uuid_mcsum/expect
 create mode 100755 tests/t_change_uuid_mcsum/script
 create mode 100644 tests/t_change_uuid_mcsum_mounted/expect
 create mode 100755 tests/t_change_uuid_mcsum_mounted/script
 create mode 100644 tests/t_change_uuid_mcsum_seed_mounted/expect
 create mode 100755 tests/t_change_uuid_mcsum_seed_mounted/script
 create mode 100644 tests/t_change_uuid_mounted/expect
 create mode 100755 tests/t_change_uuid_mounted/script
 create mode 100644 tests/t_disable_changed_csum_seed/expect
 create mode 100755 tests/t_disable_changed_csum_seed/script
 create mode 100644 tests/t_disable_changed_csum_seed_mounted/expect
 create mode 100755 tests/t_disable_changed_csum_seed_mounted/script
 create mode 100644 tests/t_disable_csum_seed/expect
 create mode 100755 tests/t_disable_csum_seed/script
 create mode 100644 tests/t_disable_meta_csum_and_seed/expect
 create mode 100755 tests/t_disable_meta_csum_and_seed/script
 create mode 100644 tests/t_enable_csum_seed/expect
 create mode 100755 tests/t_enable_csum_seed/script
 create mode 100644 tests/t_format_csum_seed/expect
 create mode 100755 tests/t_format_csum_seed/script


diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index b1eff85..ae2e832 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -90,6 +90,20 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file,
 	int		fd;
 
 	*mount_flags = 0;
+
+	if (getenv("EXT2FS_PRETEND_RO_MOUNT")) {
+		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY;
+		if (getenv("EXT2FS_PRETEND_ROOTFS"))
+			*mount_flags = EXT2_MF_ISROOT;
+		return 0;
+	}
+	if (getenv("EXT2FS_PRETEND_RW_MOUNT")) {
+		*mount_flags = EXT2_MF_MOUNTED;
+		if (getenv("EXT2FS_PRETEND_ROOTFS"))
+			*mount_flags = EXT2_MF_ISROOT;
+		return 0;
+	}
+
 	if ((f = setmntent (mtab_file, "r")) == NULL) {
 		if (errno == ENOENT) {
 			if (getenv("EXT2FS_NO_MTAB_OK"))
diff --git a/tests/t_change_uuid/expect b/tests/t_change_uuid/expect
new file mode 100644
index 0000000..0a9b20e
--- /dev/null
+++ b/tests/t_change_uuid/expect
@@ -0,0 +1,7 @@
+create fs without metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
diff --git a/tests/t_change_uuid/script b/tests/t_change_uuid/script
new file mode 100755
index 0000000..be8cbfa
--- /dev/null
+++ b/tests/t_change_uuid/script
@@ -0,0 +1,34 @@
+test_description="change uuid on a pre-metadata-csum"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without metadata_csum" >> $OUT
+$MKE2FS -O ^metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+$TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_change_uuid_mcsum/expect b/tests/t_change_uuid_mcsum/expect
new file mode 100644
index 0000000..fb26e72
--- /dev/null
+++ b/tests/t_change_uuid_mcsum/expect
@@ -0,0 +1,7 @@
+create fs with metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
diff --git a/tests/t_change_uuid_mcsum/script b/tests/t_change_uuid_mcsum/script
new file mode 100755
index 0000000..826d287
--- /dev/null
+++ b/tests/t_change_uuid_mcsum/script
@@ -0,0 +1,34 @@
+test_description="change uuid on a metadata-csum"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs with metadata_csum" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+$TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_change_uuid_mcsum_mounted/expect b/tests/t_change_uuid_mcsum_mounted/expect
new file mode 100644
index 0000000..e10e9a9
--- /dev/null
+++ b/tests/t_change_uuid_mcsum_mounted/expect
@@ -0,0 +1,7 @@
+create fs with metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+change UUID
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
diff --git a/tests/t_change_uuid_mcsum_mounted/script b/tests/t_change_uuid_mcsum_mounted/script
new file mode 100755
index 0000000..0efcae5
--- /dev/null
+++ b/tests/t_change_uuid_mcsum_mounted/script
@@ -0,0 +1,34 @@
+test_description="change uuid on a metadata-csum"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs with metadata_csum" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_change_uuid_mcsum_seed_mounted/expect b/tests/t_change_uuid_mcsum_seed_mounted/expect
new file mode 100644
index 0000000..b2d2d91
--- /dev/null
+++ b/tests/t_change_uuid_mcsum_seed_mounted/expect
@@ -0,0 +1,21 @@
+create fs with metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+change UUID
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
diff --git a/tests/t_change_uuid_mcsum_seed_mounted/script b/tests/t_change_uuid_mcsum_seed_mounted/script
new file mode 100755
index 0000000..05b0bd7
--- /dev/null
+++ b/tests/t_change_uuid_mcsum_seed_mounted/script
@@ -0,0 +1,52 @@
+test_description="change uuid on a metadata-csum with mcsum-seed"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs with metadata_csum" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum seed" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -O metadata_csuM_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_change_uuid_mounted/expect b/tests/t_change_uuid_mounted/expect
new file mode 100644
index 0000000..0a9b20e
--- /dev/null
+++ b/tests/t_change_uuid_mounted/expect
@@ -0,0 +1,7 @@
+create fs without metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
diff --git a/tests/t_change_uuid_mounted/script b/tests/t_change_uuid_mounted/script
new file mode 100755
index 0000000..827ff59
--- /dev/null
+++ b/tests/t_change_uuid_mounted/script
@@ -0,0 +1,34 @@
+test_description="change uuid on a mounted pre-metadata-csum"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without metadata_csum" >> $OUT
+$MKE2FS -O ^metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_disable_changed_csum_seed/expect b/tests/t_disable_changed_csum_seed/expect
new file mode 100644
index 0000000..e00f367
--- /dev/null
+++ b/tests/t_disable_changed_csum_seed/expect
@@ -0,0 +1,17 @@
+create fs without csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+turn off csum_seed
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
diff --git a/tests/t_disable_changed_csum_seed/script b/tests/t_disable_changed_csum_seed/script
new file mode 100755
index 0000000..9443731
--- /dev/null
+++ b/tests/t_disable_changed_csum_seed/script
@@ -0,0 +1,47 @@
+test_description="disable csum seed via tune2fs after changing uuid"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum_seed" >> $OUT
+$TUNE2FS -O metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+$TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn off csum_seed" >> $OUT
+$TUNE2FS -O ^metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_disable_changed_csum_seed_mounted/expect b/tests/t_disable_changed_csum_seed_mounted/expect
new file mode 100644
index 0000000..288494b
--- /dev/null
+++ b/tests/t_disable_changed_csum_seed_mounted/expect
@@ -0,0 +1,19 @@
+create fs without csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+change UUID
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+turn off csum_seed
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          a61be2e0-b3b8-4fbc-b2cd-d84b306b9731
+Checksum seed:            0x3ba62721
diff --git a/tests/t_disable_changed_csum_seed_mounted/script b/tests/t_disable_changed_csum_seed_mounted/script
new file mode 100755
index 0000000..3be6dd9
--- /dev/null
+++ b/tests/t_disable_changed_csum_seed_mounted/script
@@ -0,0 +1,47 @@
+test_description="disable csum seed on mounted fs via tune2fs after changing uuid"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum_seed" >> $OUT
+$TUNE2FS -O metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change UUID" >> $OUT
+$TUNE2FS -U a61be2e0-b3b8-4fbc-b2cd-d84b306b9731 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn off csum_seed" >> $OUT
+EXT2FS_PRETEND_RW_MOUNT=1 $TUNE2FS -O ^metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_disable_csum_seed/expect b/tests/t_disable_csum_seed/expect
new file mode 100644
index 0000000..e6c50fe
--- /dev/null
+++ b/tests/t_disable_csum_seed/expect
@@ -0,0 +1,14 @@
+create fs without csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+turn off csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
diff --git a/tests/t_disable_csum_seed/script b/tests/t_disable_csum_seed/script
new file mode 100755
index 0000000..28fdc5c
--- /dev/null
+++ b/tests/t_disable_csum_seed/script
@@ -0,0 +1,43 @@
+test_description="disable csum seed via tune2fs"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum_seed" >> $OUT
+$TUNE2FS -O metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn off csum_seed" >> $OUT
+$TUNE2FS -O ^metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_disable_meta_csum_and_seed/expect b/tests/t_disable_meta_csum_and_seed/expect
new file mode 100644
index 0000000..a1c9cca
--- /dev/null
+++ b/tests/t_disable_meta_csum_and_seed/expect
@@ -0,0 +1,14 @@
+create fs without csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+turn off metadata_csum
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+check filesystem
+fsck returns 0
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
diff --git a/tests/t_disable_meta_csum_and_seed/script b/tests/t_disable_meta_csum_and_seed/script
new file mode 100755
index 0000000..9eb18e3
--- /dev/null
+++ b/tests/t_disable_meta_csum_and_seed/script
@@ -0,0 +1,44 @@
+test_description="disable csum seed and csums via tune2fs"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum_seed" >> $OUT
+$TUNE2FS -O metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn off metadata_csum" >> $OUT
+$TUNE2FS -O ^metadata_csum $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | grep 'metadata_csum' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_enable_csum_seed/expect b/tests/t_enable_csum_seed/expect
new file mode 100644
index 0000000..07d9a4f
--- /dev/null
+++ b/tests/t_enable_csum_seed/expect
@@ -0,0 +1,12 @@
+create fs without csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+turn on csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+change uuid
+Filesystem UUID:          1dd136c6-e47a-4833-9bf5-519f8aacabe4
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          1dd136c6-e47a-4833-9bf5-519f8aacabe4
+Checksum seed:            0x3ba62721
diff --git a/tests/t_enable_csum_seed/script b/tests/t_enable_csum_seed/script
new file mode 100755
index 0000000..55cade6
--- /dev/null
+++ b/tests/t_enable_csum_seed/script
@@ -0,0 +1,38 @@
+test_description="enable csum seed via tune2fs"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs without csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,^metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "turn on csum_seed" >> $OUT
+$TUNE2FS -O metadata_csum_seed $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change uuid" >> $OUT
+$TUNE2FS -U 1dd136c6-e47a-4833-9bf5-519f8aacabe4 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+
diff --git a/tests/t_format_csum_seed/expect b/tests/t_format_csum_seed/expect
new file mode 100644
index 0000000..39e6d6a
--- /dev/null
+++ b/tests/t_format_csum_seed/expect
@@ -0,0 +1,10 @@
+create fs with csum_seed
+Filesystem UUID:          6b33f586-a183-4383-921d-30da3fef2e5c
+Checksum seed:            0x3ba62721
+change uuid
+Filesystem UUID:          1dd136c6-e47a-4833-9bf5-519f8aacabe4
+Checksum seed:            0x3ba62721
+check filesystem
+fsck returns 0
+Filesystem UUID:          1dd136c6-e47a-4833-9bf5-519f8aacabe4
+Checksum seed:            0x3ba62721
diff --git a/tests/t_format_csum_seed/script b/tests/t_format_csum_seed/script
new file mode 100755
index 0000000..1829514
--- /dev/null
+++ b/tests/t_format_csum_seed/script
@@ -0,0 +1,34 @@
+test_description="format with csum_seed"
+
+trap "rm -rf $TMPFILE $TMPFILE.conf" EXIT INT QUIT
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+OUT=$test_name.log
+EXP=$test_dir/expect
+rm -rf $OUT
+
+# Test command line option
+echo "create fs with csum_seed" >> $OUT
+$MKE2FS -O metadata_csum,metadata_csum_seed -U 6b33f586-a183-4383-921d-30da3fef2e5c -F $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "change uuid" >> $OUT
+$TUNE2FS -U 1dd136c6-e47a-4833-9bf5-519f8aacabe4 $TMPFILE > /dev/null 2>&1
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+echo "check filesystem" >> $OUT
+$FSCK $FSCK_OPT -fy $TMPFILE > /dev/null 2>&1
+echo "fsck returns $?" >> $OUT
+$DUMPE2FS $TMPFILE 2>&1 | egrep '(Checksum seed:|UUID)' >> $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+	echo "$test_name: $test_description: ok"
+	touch $test_name.ok
+else
+	echo "$test_name: $test_description: failed"
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+	rm -f $test_name.tmp
+fi
+


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0
  2015-10-12 21:56 ` [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0 Darrick J. Wong
@ 2015-10-13  2:34   ` Andreas Dilger
  2015-10-13  7:08     ` Darrick J. Wong
  2015-10-24  4:38   ` Theodore Ts'o
  1 sibling, 1 reply; 22+ messages in thread
From: Andreas Dilger @ 2015-10-13  2:34 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: tytso, linux-ext4

The commit comment says enable meta_bg if 1/2 of the block group
is full, but the code checks for 3/4 of the block group is full.  Which one
Should it be?

Cheers, Andreas

> On Oct 12, 2015, at 15:56, Darrick J. Wong <darrick.wong@oracle.com> wrote:
> 
> If during formatting we'd lose more than half of a block group to
> group descriptors and other metadata, enable the meta_bg feature.
> This enables us to create >500T filesystems with default options.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
> lib/ext2fs/initialize.c |    5 +++++
> 1 file changed, 5 insertions(+)
> 
> 
> diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
> index f672a27..b5ca928 100644
> --- a/lib/ext2fs/initialize.c
> +++ b/lib/ext2fs/initialize.c
> @@ -381,6 +381,11 @@ ipg_retry:
>    overhead = (int) (3 + fs->inode_blocks_per_group +
>              super->s_reserved_gdt_blocks);
> 
> +    /* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
> +    if (super->s_reserved_gdt_blocks + fs->desc_blocks >
> +        super->s_blocks_per_group * 3 / 4)
> +        fs->super->s_feature_incompat |= EXT2_FEATURE_INCOMPAT_META_BG;
> +
>    if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
>        overhead++;
>    else
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0
  2015-10-13  2:34   ` Andreas Dilger
@ 2015-10-13  7:08     ` Darrick J. Wong
  0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2015-10-13  7:08 UTC (permalink / raw)
  To: Andreas Dilger; +Cc: tytso, linux-ext4

On Mon, Oct 12, 2015 at 08:34:36PM -0600, Andreas Dilger wrote:
> The commit comment says enable meta_bg if 1/2 of the block group
> is full, but the code checks for 3/4 of the block group is full.  Which one
> Should it be?

Oops.  It should be 3/4 since it's generally advantageous to leave meta_bg off
as long as possible so as to keep the group descriptors nearby.

That said, I also toyed with the idea of making the switch if total overhead
(gdt + inodes) uses more than 3/4 of a BG.  But the inode size/ratio is
configurable, so I went with just checking gdt for now.

--D

> 
> Cheers, Andreas
> 
> > On Oct 12, 2015, at 15:56, Darrick J. Wong <darrick.wong@oracle.com> wrote:
> > 
> > If during formatting we'd lose more than half of a block group to
> > group descriptors and other metadata, enable the meta_bg feature.
> > This enables us to create >500T filesystems with default options.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> > lib/ext2fs/initialize.c |    5 +++++
> > 1 file changed, 5 insertions(+)
> > 
> > 
> > diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
> > index f672a27..b5ca928 100644
> > --- a/lib/ext2fs/initialize.c
> > +++ b/lib/ext2fs/initialize.c
> > @@ -381,6 +381,11 @@ ipg_retry:
> >    overhead = (int) (3 + fs->inode_blocks_per_group +
> >              super->s_reserved_gdt_blocks);
> > 
> > +    /* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
> > +    if (super->s_reserved_gdt_blocks + fs->desc_blocks >
> > +        super->s_blocks_per_group * 3 / 4)
> > +        fs->super->s_feature_incompat |= EXT2_FEATURE_INCOMPAT_META_BG;
> > +
> >    if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
> >        overhead++;
> >    else
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled
  2015-10-12 21:56 ` [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled Darrick J. Wong
@ 2015-10-24  4:37   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  4:37 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4, Dave Chinner

On Mon, Oct 12, 2015 at 02:56:35PM -0700, Darrick J. Wong wrote:
> When meta_bg is enabled at mkfs time, we put at most one group
> descriptor block in each blockgroup.  Unfortunately, the calculation
> of max overhead per bg doesn't know this, so mkfs fails when it isn't
> strictly necessary.  Fix it, since Dave reported that he couldn't
> create a 500TB ext4 filesystem.
> 
> Reported-by: Dave Chinner <david@fromorbit.com>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0
  2015-10-12 21:56 ` [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0 Darrick J. Wong
  2015-10-13  2:34   ` Andreas Dilger
@ 2015-10-24  4:38   ` Theodore Ts'o
  1 sibling, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  4:38 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:56:42PM -0700, Darrick J. Wong wrote:
> If during formatting we'd lose more than half of a block group to
> group descriptors and other metadata, enable the meta_bg feature.
> This enables us to create >500T filesystems with default options.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, with the commit description fixed up.

	      	  	 	     	   - Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions
  2015-10-12 21:56 ` [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions Darrick J. Wong
@ 2015-10-24  4:41   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  4:41 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:56:48PM -0700, Darrick J. Wong wrote:
> Create separate predicate functions to test/set/clear feature flags,
> thereby replacing the wordy old macros.  Furthermore, clean out the
> places where we open-coded feature tests.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 04/12] e2fsck: clean up feature test macros with predicate functions
  2015-10-12 21:56 ` [PATCH 04/12] e2fsck: " Darrick J. Wong
@ 2015-10-24  4:49   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  4:49 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:56:54PM -0700, Darrick J. Wong wrote:
> Create separate predicate functions to test/set/clear feature flags,
> thereby replacing the wordy old macros.  Furthermore, clean out the
> places where we open-coded feature tests.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 05/12] misc: clean up feature test macros with predicate functions
  2015-10-12 21:57 ` [PATCH 05/12] misc: " Darrick J. Wong
@ 2015-10-24  5:24   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  5:24 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:57:00PM -0700, Darrick J. Wong wrote:
> Create separate predicate functions to test/set/clear feature flags,
> thereby replacing the wordy old macros.  Furthermore, clean out the
> places where we open-coded feature tests.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 06/12] resize2fs: clean up feature test macros with predicate functions
  2015-10-12 21:57 ` [PATCH 06/12] resize2fs: " Darrick J. Wong
@ 2015-10-24  5:24   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  5:24 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:57:07PM -0700, Darrick J. Wong wrote:
> Create separate predicate functions to test/set/clear feature flags,
> thereby replacing the wordy old macros.  Furthermore, clean out the
> places where we open-coded feature tests.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 07/12] debugfs: clean up feature test macros with predicate functions
  2015-10-12 21:57 ` [PATCH 07/12] debugfs: " Darrick J. Wong
@ 2015-10-24  5:26   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2015-10-24  5:26 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Mon, Oct 12, 2015 at 02:57:13PM -0700, Darrick J. Wong wrote:
> Create separate predicate functions to test/set/clear feature flags,
> thereby replacing the wordy old macros.  Furthermore, clean out the
> places where we open-coded feature tests.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2015-10-24 10:51 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-12 21:56 [PATCH 00/12] e2fsprogs: misc fixes and cleanups; save checksum seeds Darrick J. Wong
2015-10-12 21:56 ` [PATCH 01/12] libext2fs: fix maximum bg overhead calculation with meta_bg enabled Darrick J. Wong
2015-10-24  4:37   ` Theodore Ts'o
2015-10-12 21:56 ` [PATCH 02/12] libext2fs: automatically enable meta_bg to avoid filling up BG 0 Darrick J. Wong
2015-10-13  2:34   ` Andreas Dilger
2015-10-13  7:08     ` Darrick J. Wong
2015-10-24  4:38   ` Theodore Ts'o
2015-10-12 21:56 ` [PATCH 03/12] libext2fs: clean up feature test macros with predicate functions Darrick J. Wong
2015-10-24  4:41   ` Theodore Ts'o
2015-10-12 21:56 ` [PATCH 04/12] e2fsck: " Darrick J. Wong
2015-10-24  4:49   ` Theodore Ts'o
2015-10-12 21:57 ` [PATCH 05/12] misc: " Darrick J. Wong
2015-10-24  5:24   ` Theodore Ts'o
2015-10-12 21:57 ` [PATCH 06/12] resize2fs: " Darrick J. Wong
2015-10-24  5:24   ` Theodore Ts'o
2015-10-12 21:57 ` [PATCH 07/12] debugfs: " Darrick J. Wong
2015-10-24  5:26   ` Theodore Ts'o
2015-10-12 21:57 ` [PATCH 08/12] libext2fs: store checksum seed in superblock Darrick J. Wong
2015-10-12 21:57 ` [PATCH 09/12] tune2fs: allow user to turn on saving the checksum seed Darrick J. Wong
2015-10-12 21:57 ` [PATCH 10/12] e2fsck: check the checksum seed feature flag is set correctly Darrick J. Wong
2015-10-12 21:57 ` [PATCH 11/12] mke2fs: store checksum seed at format time Darrick J. Wong
2015-10-12 21:57 ` [PATCH 12/12] tests: check proper operation of metadata_csum_seed Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.