[PATCH v2] f2fs: fix to avoid redundant discard during fstrim

From: Chao Yu
Date: Thu Jul 07 2016 - 10:49:22 EST


From: Chao Yu <yuchao0@xxxxxxxxxx>

With below test steps, f2fs will issue redundant discard when doing fstrim,
the reason is that we issue discards for both prefree segments and
consecutive freed region user wants to trim, part regions they covered are
overlapped, here, we change to do not to issue any discards for prefree
segments in trimmed range.

1. mount -t f2fs -o discard /dev/zram0 /mnt/f2fs
2. fstrim -o 0 -l 3221225472 -m 2097152 -v /mnt/f2fs/
3. dd if=/dev/zero of=/mnt/f2fs/a bs=2M count=1
4. dd if=/dev/zero of=/mnt/f2fs/b bs=1M count=1
5. sync
6. rm /mnt/f2fs/a /mnt/f2fs/b
7. fstrim -o 0 -l 3221225472 -m 2097152 -v /mnt/f2fs/

Before:
<...>-5428 [001] ...1 9511.052125: f2fs_issue_discard: dev = (251,0), blkstart = 0x2200, blklen = 0x200
<...>-5428 [001] ...1 9511.052787: f2fs_issue_discard: dev = (251,0), blkstart = 0x2200, blklen = 0x300

After:
<...>-6764 [000] ...1 9720.382504: f2fs_issue_discard: dev = (251,0), blkstart = 0x2200, blklen = 0x300

Signed-off-by: Chao Yu <yuchao0@xxxxxxxxxx>
---
v2: do not skip cleaning up bitmap/refcount of prefree segment.
fs/f2fs/segment.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6d16ecf..e508b15 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -710,6 +710,7 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
unsigned int start = 0, end = -1;
unsigned int secno, start_segno;
+ bool force = (cpc->reason == CP_DISCARD);

mutex_lock(&dirty_i->seglist_lock);

@@ -726,7 +727,7 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)

dirty_i->nr_dirty[PRE] -= end - start;

- if (!test_opt(sbi, DISCARD))
+ if (force || !test_opt(sbi, DISCARD))
continue;

if (!test_opt(sbi, LFS) || sbi->segs_per_sec == 1) {
@@ -750,7 +751,7 @@ next:

/* send small discards */
list_for_each_entry_safe(entry, this, head, list) {
- if (cpc->reason == CP_DISCARD && entry->len < cpc->trim_minlen)
+ if (force && entry->len < cpc->trim_minlen)
goto skip;
f2fs_issue_discard(sbi, entry->blkaddr, entry->len);
cpc->trimmed += entry->len;
--
2.7.2