All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Dongyang <dongyangli@ddn.com>
To: linux-ext4@vger.kernel.org
Cc: adilger@dilger.ca, sihara@ddn.com, wangshilong1991@gmail.com
Subject: [PATCH V2] e2fsprogs: support EXT2_FLAG_BG_TRIMMED and EXT2_FLAGS_TRACK_TRIM
Date: Tue, 29 Aug 2023 15:43:09 +1000	[thread overview]
Message-ID: <20230829054309.684530-1-dongyangli@ddn.com> (raw)

This adds EXT2_FLAG_BG_TRIMMED, which is set on block group
descriptors during mke2fs after discard is done for that group.
The EXT2_FLAG_BG_TRIMMED flag is cleared on the block group when
we free blocks.

Introduce EXT2_FLAGS_TRACK_TRIM, which is a new super block flag,
to indicate whether we should honour the EXT2_FLAG_BG_TRIMMED
set on each block group.
EXT2_FLAGS_TRACK_TRIM itself can be turned on/off via tune2fs.

Make dumpe2fs aware of the new flags.

Cc: Shuichi Ihara <sihara@ddn.com>
Cc: Andreas Dilger <adilger@dilger.ca>
Cc: Wang Shilong <wangshilong1991@gmail.com>
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
---
v1->v2:
set BG_TRIMMED flag on gd progressively as we discard the groups.
---
 lib/e2p/ls.c             |  4 ++++
 lib/ext2fs/alloc_stats.c |  8 ++++++--
 lib/ext2fs/ext2_fs.h     |  2 ++
 misc/dumpe2fs.c          |  2 ++
 misc/mke2fs.c            | 34 +++++++++++++++++-----------------
 misc/tune2fs.8.in        |  8 ++++++++
 misc/tune2fs.c           | 10 ++++++++++
 7 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c
index 0b74aea2b..4b356eca6 100644
--- a/lib/e2p/ls.c
+++ b/lib/e2p/ls.c
@@ -162,6 +162,10 @@ static void print_super_flags(struct ext2_super_block * s, FILE *f)
 		fputs("test_filesystem ", f);
 		flags_found++;
 	}
+	if (s->s_flags & EXT2_FLAGS_TRACK_TRIM) {
+		fputs("track_trim ", f);
+		flags_found++;
+	}
 	if (flags_found)
 		fputs("\n", f);
 	else
diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c
index 6f98bcc7c..4e03f92a4 100644
--- a/lib/ext2fs/alloc_stats.c
+++ b/lib/ext2fs/alloc_stats.c
@@ -70,10 +70,12 @@ void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
 #endif
 		return;
 	}
-	if (inuse > 0)
+	if (inuse > 0) {
 		ext2fs_mark_block_bitmap2(fs->block_map, blk);
-	else
+	} else {
 		ext2fs_unmark_block_bitmap2(fs->block_map, blk);
+		ext2fs_bg_flags_clear(fs, group, EXT2_BG_TRIMMED);
+	}
 	ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse);
 	ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
 	ext2fs_group_desc_csum_set(fs, group);
@@ -139,6 +141,8 @@ void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
 			ext2fs_bg_free_blocks_count(fs, group) -
 			inuse*n/EXT2FS_CLUSTER_RATIO(fs));
 		ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+		if (inuse < 0)
+			ext2fs_bg_flags_clear(fs, group, EXT2_BG_TRIMMED);
 		ext2fs_group_desc_csum_set(fs, group);
 		ext2fs_free_blocks_count_add(fs->super, -inuse * (blk64_t) n);
 		blk += n;
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 0fc9c09a5..88e1114c9 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -223,6 +223,7 @@ struct ext4_group_desc
 #define EXT2_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not initialized */
 #define EXT2_BG_BLOCK_UNINIT	0x0002 /* Block bitmap not initialized */
 #define EXT2_BG_INODE_ZEROED	0x0004 /* On-disk itable initialized to zero */
+#define EXT2_BG_TRIMMED		0x0008 /* Block group was trimmed */
 
 /*
  * Data structures used by the directory indexing feature
@@ -563,6 +564,7 @@ struct ext2_inode *EXT2_INODE(struct ext2_inode_large *large_inode)
 #define EXT2_FLAGS_SIGNED_HASH		0x0001  /* Signed dirhash in use */
 #define EXT2_FLAGS_UNSIGNED_HASH	0x0002  /* Unsigned dirhash in use */
 #define EXT2_FLAGS_TEST_FILESYS		0x0004	/* OK for use on development code */
+#define EXT2_FLAGS_TRACK_TRIM		0x0008	/* Track trim status in each bg */
 #define EXT2_FLAGS_IS_SNAPSHOT		0x0010	/* This is a snapshot image */
 #define EXT2_FLAGS_FIX_SNAPSHOT		0x0020	/* Snapshot inodes corrupted */
 #define EXT2_FLAGS_FIX_EXCLUDE		0x0040	/* Exclude bitmaps corrupted */
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 7c080ed9f..afe569dff 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -131,6 +131,8 @@ static void print_bg_opts(ext2_filsys fs, dgrp_t i)
  		     &first);
 	print_bg_opt(bg_flags, EXT2_BG_INODE_ZEROED, "ITABLE_ZEROED",
  		     &first);
+	print_bg_opt(bg_flags, EXT2_BG_TRIMMED, "TRIMMED",
+		     &first);
 	if (!first)
 		fputc(']', stdout);
 	fputc('\n', stdout);
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 4a9c1b092..0eff41aad 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -71,8 +71,6 @@ extern int optind;
 #define ZAP_BOOTBLOCK
 #endif
 
-#define DISCARD_STEP_MB		(2048)
-
 extern int isatty(int);
 extern FILE *fpopen(const char *cmd, const char *mode);
 
@@ -2872,9 +2870,7 @@ err:
 static int mke2fs_discard_device(ext2_filsys fs)
 {
 	struct ext2fs_numeric_progress_struct progress;
-	blk64_t blocks = ext2fs_blocks_count(fs->super);
-	blk64_t count = DISCARD_STEP_MB;
-	blk64_t cur = 0;
+	dgrp_t group;
 	int retval = 0;
 
 	/*
@@ -2886,22 +2882,26 @@ static int mke2fs_discard_device(ext2_filsys fs)
 	if (retval)
 		return retval;
 
-	count *= (1024 * 1024);
-	count /= fs->blocksize;
-
 	ext2fs_numeric_progress_init(fs, &progress,
 				     _("Discarding device blocks: "),
-				     blocks);
-	while (cur < blocks) {
-		ext2fs_numeric_progress_update(fs, &progress, cur);
+				     ext2fs_blocks_count(fs->super));
 
-		if (cur + count > blocks)
-			count = blocks - cur;
+	for (group = 0; group < fs->group_desc_count; group++) {
+		blk64_t start = ext2fs_group_first_block2(fs, group);
+		blk64_t count = ext2fs_group_blocks_count(fs, group);
+		int retval_discard;
 
-		retval = io_channel_discard(fs->io, cur, count);
-		if (retval)
-			break;
-		cur += count;
+		retval_discard = io_channel_discard(fs->io, start, count);
+		if (!retval_discard) {
+			ext2fs_bg_flags_set(fs, group, EXT2_BG_TRIMMED);
+			ext2fs_group_desc_csum_set(fs, group);
+			fs->super->s_flags |= EXT2_FLAGS_TRACK_TRIM;
+		} else if (!retval) {
+			retval = retval_discard;
+		}
+
+		ext2fs_numeric_progress_update(fs, &progress,
+					ext2fs_group_last_block2(fs, group));
 	}
 
 	if (retval) {
diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in
index dcf108c1f..2eb7e88ed 100644
--- a/misc/tune2fs.8.in
+++ b/misc/tune2fs.8.in
@@ -273,6 +273,14 @@ mounted using experimental kernel code, such as the ext4dev file system.
 .B ^test_fs
 Clear the test_fs flag, indicating the file system should only be mounted
 using production-level file system code.
+.TP
+.B track_trim
+Set a flag in the file system superblock to make fstrim save the trim status
+in each block group and skip the block groups already been trimmed.
+.TP
+.B ^track_trim
+Clear the track_trim flag to make fstrim ignore the trim status saved in
+each block group, and trim every block group.
 .RE
 .TP
 .B \-f
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 458f7cf6a..dd9e8eab0 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -2312,6 +2312,14 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
 			sb->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
 			printf("Clearing test filesystem flag\n");
 			ext2fs_mark_super_dirty(fs);
+		} else if (!strcmp(token, "track_trim")) {
+			sb->s_flags |= EXT2_FLAGS_TRACK_TRIM;
+			printf("Setting track_trim flag\n");
+			ext2fs_mark_super_dirty(fs);
+		} else if (!strcmp(token, "^track_trim")) {
+			sb->s_flags &= ~EXT2_FLAGS_TRACK_TRIM;
+			printf("Clearing track_trim flag\n");
+			ext2fs_mark_super_dirty(fs);
 		} else if (strcmp(token, "stride") == 0) {
 			if (!arg) {
 				r_usage++;
@@ -2458,6 +2466,8 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
 			"\tforce_fsck\n"
 			"\ttest_fs\n"
 			"\t^test_fs\n"
+			"\ttrack_trim\n"
+			"\t^track_trim\n"
 			"\tencoding=<encoding>\n"
 			"\tencoding_flags=<flags>\n"));
 		free(buf);
-- 
2.41.0


                 reply	other threads:[~2023-08-29  5:44 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230829054309.684530-1-dongyangli@ddn.com \
    --to=dongyangli@ddn.com \
    --cc=adilger@dilger.ca \
    --cc=linux-ext4@vger.kernel.org \
    --cc=sihara@ddn.com \
    --cc=wangshilong1991@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.