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++;
#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);
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;
#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 */
/*
#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 */
&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)
#define ZAP_BOOTBLOCK
#endif
-#define DISCARD_STEP_MB (2048)
-
extern int isatty(int);
extern FILE *fpopen(const char *cmd, const char *mode);
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;
/*
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) {
.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
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++;
"\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);