[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250928092050.287779-1-chao@kernel.org>
Date: Sun, 28 Sep 2025 17:20:50 +0800
From: Chao Yu <chao@...nel.org>
To: jaegeuk@...nel.org
Cc: linux-f2fs-devel@...ts.sourceforge.net,
linux-kernel@...r.kernel.org,
Chao Yu <chao@...nel.org>
Subject: [PATCH RFC] f2fs: freeze fs operations during f2fs_enable_checkpoint()
If there are too many background IOs during f2fs_enable_checkpoint(),
sync_inodes_sb() may be blocked for long time due to it will loop to
write dirty datas which are generated by in parallel write()
continuously.
Let's change as below to resolve this issue:
- freeze fs operations to avoid race condition
- decrease DEF_ENABLE_INTERVAL from 16 to 5
In addition, dump more logs during f2fs_enable_checkpoint().
Testcase:
1. fill data to dirty filesystem
2. mount -o remount,checkpoint=disable:10% /data
3. fio --rw=randwrite --bs=4kb --size=1GB --numjobs=10 \
--iodepth=64 --ioengine=psync --time_based --runtime=600 &
4. mount -o remount,checkpoint=enable /data
Before:
F2FS-fs (dm-51): f2fs_enable_checkpoint() finishes, writeback:7232, sync:39793, cp:457
After:
F2FS-fs (dm-51): f2fs_enable_checkpoint() finishes, writeback:5945, lock:28, sync:9289, cp:0, 434, 0
Signed-off-by: Chao Yu <chao@...nel.org>
---
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/super.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c4a197c4d804..060a4603a779 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -281,7 +281,7 @@ enum {
#define DEF_CP_INTERVAL 60 /* 60 secs */
#define DEF_IDLE_INTERVAL 5 /* 5 secs */
#define DEF_DISABLE_INTERVAL 5 /* 5 secs */
-#define DEF_ENABLE_INTERVAL 16 /* 16 secs */
+#define DEF_ENABLE_INTERVAL 5 /* 5 secs */
#define DEF_DISABLE_QUICK_INTERVAL 1 /* 1 secs */
#define DEF_UMOUNT_DISCARD_TIMEOUT 5 /* 5 secs */
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1e0678e37a30..dfdd3c3795a2 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2626,12 +2626,25 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
return err;
}
+static void f2fs_freeze_operations(struct super_block *sb)
+{
+ percpu_down_write(sb->s_writers.rw_sem + SB_FREEZE_WRITE - 1);
+ percpu_down_write(sb->s_writers.rw_sem + SB_FREEZE_PAGEFAULT - 1);
+}
+
+static void f2fs_unfreeze_operations(struct super_block *sb)
+{
+ percpu_up_write(sb->s_writers.rw_sem + SB_FREEZE_PAGEFAULT - 1);
+ percpu_up_write(sb->s_writers.rw_sem + SB_FREEZE_WRITE - 1);
+}
+
static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
{
unsigned int nr_pages = get_pages(sbi, F2FS_DIRTY_DATA) / 16;
- long long start, writeback, end;
+ long long start, writeback, lock, sync_inode, end;
- f2fs_info(sbi, "f2fs_enable_checkpoint() starts, meta: %lld, node: %lld, data: %lld",
+ f2fs_info(sbi, "%s start, meta: %lld, node: %lld, data: %lld",
+ __func__,
get_pages(sbi, F2FS_DIRTY_META),
get_pages(sbi, F2FS_DIRTY_NODES),
get_pages(sbi, F2FS_DIRTY_DATA));
@@ -2650,11 +2663,18 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
}
writeback = ktime_get();
- sync_inodes_sb(sbi->sb);
+ f2fs_freeze_operations(sbi->sb);
+
+ lock = ktime_get();
+
+ if (get_pages(sbi, F2FS_DIRTY_DATA))
+ sync_inodes_sb(sbi->sb);
if (unlikely(get_pages(sbi, F2FS_DIRTY_DATA)))
- f2fs_warn(sbi, "checkpoint=enable has some unwritten data: %lld",
- get_pages(sbi, F2FS_DIRTY_DATA));
+ f2fs_warn(sbi, "%s: has some unwritten data: %lld",
+ __func__, get_pages(sbi, F2FS_DIRTY_DATA));
+
+ sync_inode = ktime_get();
f2fs_down_write(&sbi->gc_lock);
f2fs_dirty_to_prefree(sbi);
@@ -2663,16 +2683,29 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
set_sbi_flag(sbi, SBI_IS_DIRTY);
f2fs_up_write(&sbi->gc_lock);
+ f2fs_info(sbi, "%s sync_fs, meta: %lld, imeta: %lld, node: %lld, dents: %lld, qdata: %lld",
+ __func__,
+ get_pages(sbi, F2FS_DIRTY_META),
+ get_pages(sbi, F2FS_DIRTY_IMETA),
+ get_pages(sbi, F2FS_DIRTY_NODES),
+ get_pages(sbi, F2FS_DIRTY_DENTS),
+ get_pages(sbi, F2FS_DIRTY_QDATA));
f2fs_sync_fs(sbi->sb, 1);
/* Let's ensure there's no pending checkpoint anymore */
f2fs_flush_ckpt_thread(sbi);
+ f2fs_unfreeze_operations(sbi->sb);
+
end = ktime_get();
- f2fs_info(sbi, "f2fs_enable_checkpoint() finishes, writeback:%llu, sync:%llu",
- ktime_ms_delta(writeback, start),
- ktime_ms_delta(end, writeback));
+ f2fs_info(sbi, "%s end, writeback:%llu, "
+ "lock:%llu, sync_inode:%llu, sync_fs:%llu",
+ __func__,
+ ktime_ms_delta(writeback, start),
+ ktime_ms_delta(lock, writeback),
+ ktime_ms_delta(sync_inode, lock),
+ ktime_ms_delta(end, sync_inode));
}
static int __f2fs_remount(struct fs_context *fc, struct super_block *sb)
--
2.49.0
Powered by blists - more mailing lists