Whamcloud - gitweb
LU-14712 e2fsprogs: support EXT2_FLAG_BG_TRIMMED and EXT2_FLAGS_TRACK_TRIM
authorLi Dongyang <dongyangli@ddn.com>
Fri, 11 Aug 2023 05:17:36 +0000 (15:17 +1000)
committerLi Dongyang <dongyangli@ddn.com>
Tue, 28 May 2024 05:53:20 +0000 (15:53 +1000)
This adds EXT2_FLAG_BG_TRIMMED, which is used on block group
descriptors during mke2fs after discard is done.
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.

Change-Id: I5af88fe4a32c8c9ab5604b84362a7140ae2cdde5
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/tools/e2fsprogs/+/51924
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lib/e2p/ls.c
lib/ext2fs/alloc_stats.c
lib/ext2fs/ext2_fs.h
misc/dumpe2fs.c
misc/mke2fs.c
misc/tune2fs.8.in
misc/tune2fs.c

index fead530..b40929c 100644 (file)
@@ -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 (s->s_flags & EXT2_FLAGS_HAS_IOPS) {
                fputs("iops ", f);
                flags_found++;
index 6f98bcc..4e03f92 100644 (file)
@@ -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;
index 9c2df51..b769725 100644 (file)
@@ -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 */
 #define EXT2_BG_IOPS           0x0010 /* In IOPS/fast storage */
 
 /*
@@ -570,6 +571,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 */
index ccea20d..41b7dce 100644 (file)
@@ -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);
        print_bg_opt(bg_flags, EXT2_BG_IOPS, "IOPS",
                     &first);
        if (!first)
index c4a6232..1368347 100644 (file)
@@ -67,8 +67,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);
 
@@ -2985,9 +2983,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;
 
        /*
@@ -2999,22 +2995,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 = 0;
 
-               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) {
index 1fce818..42ba8dd 100644 (file)
@@ -282,6 +282,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
index 86e1809..9754a5d 100644 (file)
@@ -2436,6 +2436,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++;
@@ -2633,6 +2641,8 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
                        "\tiops=[^]<iops storage size range>\n"
                        "\ttest_fs\n"
                        "\t^test_fs\n"
+                       "\ttrack_trim\n"
+                       "\t^track_trim\n"
                        "\tencoding=<encoding>\n"
                        "\tencoding_flags=<flags>\n"));
                free(buf);