Skip to content

Commit 196c81f

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: block cache/dio write 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: - hold cp_enable_rwsem write lock to block any cache/dio write - decrease DEF_ENABLE_INTERVAL from 16 to 5 In addition, dump more logs during f2fs_enable_checkpoint(). Testcase: 1. fill data into filesystem until 90% usage. 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 \ --directory=/data/fio_dir/ & 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 end, writeback:5032, lock:0, sync_inode:5552, sync_fs:84 Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent be112e7 commit 196c81f

3 files changed

Lines changed: 34 additions & 9 deletions

File tree

fs/f2fs/data.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
14181418

14191419
static void f2fs_map_lock(struct f2fs_sb_info *sbi, int flag)
14201420
{
1421+
f2fs_down_read(&sbi->cp_enable_rwsem);
14211422
if (flag == F2FS_GET_BLOCK_PRE_AIO)
14221423
f2fs_down_read(&sbi->node_change);
14231424
else
@@ -1430,6 +1431,7 @@ static void f2fs_map_unlock(struct f2fs_sb_info *sbi, int flag)
14301431
f2fs_up_read(&sbi->node_change);
14311432
else
14321433
f2fs_unlock_op(sbi);
1434+
f2fs_up_read(&sbi->cp_enable_rwsem);
14331435
}
14341436

14351437
int f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index)

fs/f2fs/f2fs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ enum {
281281
#define DEF_CP_INTERVAL 60 /* 60 secs */
282282
#define DEF_IDLE_INTERVAL 5 /* 5 secs */
283283
#define DEF_DISABLE_INTERVAL 5 /* 5 secs */
284-
#define DEF_ENABLE_INTERVAL 16 /* 16 secs */
284+
#define DEF_ENABLE_INTERVAL 5 /* 5 secs */
285285
#define DEF_DISABLE_QUICK_INTERVAL 1 /* 1 secs */
286286
#define DEF_UMOUNT_DISCARD_TIMEOUT 5 /* 5 secs */
287287

@@ -1695,6 +1695,7 @@ struct f2fs_sb_info {
16951695
long interval_time[MAX_TIME]; /* to store thresholds */
16961696
struct ckpt_req_control cprc_info; /* for checkpoint request control */
16971697
struct cp_stats cp_stats; /* for time stat of checkpoint */
1698+
struct f2fs_rwsem cp_enable_rwsem; /* block cache/dio write */
16981699

16991700
struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */
17001701

fs/f2fs/super.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,10 +2635,11 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
26352635
static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
26362636
{
26372637
unsigned int nr_pages = get_pages(sbi, F2FS_DIRTY_DATA) / 16;
2638-
long long start, writeback, end;
2638+
long long start, writeback, lock, sync_inode, end;
26392639
int ret;
26402640

2641-
f2fs_info(sbi, "f2fs_enable_checkpoint() starts, meta: %lld, node: %lld, data: %lld",
2641+
f2fs_info(sbi, "%s start, meta: %lld, node: %lld, data: %lld",
2642+
__func__,
26422643
get_pages(sbi, F2FS_DIRTY_META),
26432644
get_pages(sbi, F2FS_DIRTY_NODES),
26442645
get_pages(sbi, F2FS_DIRTY_DATA));
@@ -2657,11 +2658,18 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
26572658
}
26582659
writeback = ktime_get();
26592660

2660-
sync_inodes_sb(sbi->sb);
2661+
f2fs_down_write(&sbi->cp_enable_rwsem);
2662+
2663+
lock = ktime_get();
2664+
2665+
if (get_pages(sbi, F2FS_DIRTY_DATA))
2666+
sync_inodes_sb(sbi->sb);
26612667

26622668
if (unlikely(get_pages(sbi, F2FS_DIRTY_DATA)))
2663-
f2fs_warn(sbi, "checkpoint=enable has some unwritten data: %lld",
2664-
get_pages(sbi, F2FS_DIRTY_DATA));
2669+
f2fs_warn(sbi, "%s: has some unwritten data: %lld",
2670+
__func__, get_pages(sbi, F2FS_DIRTY_DATA));
2671+
2672+
sync_inode = ktime_get();
26652673

26662674
f2fs_down_write(&sbi->gc_lock);
26672675
f2fs_dirty_to_prefree(sbi);
@@ -2670,18 +2678,31 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
26702678
set_sbi_flag(sbi, SBI_IS_DIRTY);
26712679
f2fs_up_write(&sbi->gc_lock);
26722680

2681+
f2fs_info(sbi, "%s sync_fs, meta: %lld, imeta: %lld, node: %lld, dents: %lld, qdata: %lld",
2682+
__func__,
2683+
get_pages(sbi, F2FS_DIRTY_META),
2684+
get_pages(sbi, F2FS_DIRTY_IMETA),
2685+
get_pages(sbi, F2FS_DIRTY_NODES),
2686+
get_pages(sbi, F2FS_DIRTY_DENTS),
2687+
get_pages(sbi, F2FS_DIRTY_QDATA));
26732688
ret = f2fs_sync_fs(sbi->sb, 1);
26742689
if (ret)
26752690
f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret);
26762691

26772692
/* Let's ensure there's no pending checkpoint anymore */
26782693
f2fs_flush_ckpt_thread(sbi);
26792694

2695+
f2fs_up_write(&sbi->cp_enable_rwsem);
2696+
26802697
end = ktime_get();
26812698

2682-
f2fs_info(sbi, "f2fs_enable_checkpoint() finishes, writeback:%llu, sync:%llu",
2683-
ktime_ms_delta(writeback, start),
2684-
ktime_ms_delta(end, writeback));
2699+
f2fs_info(sbi, "%s end, writeback:%llu, "
2700+
"lock:%llu, sync_inode:%llu, sync_fs:%llu",
2701+
__func__,
2702+
ktime_ms_delta(writeback, start),
2703+
ktime_ms_delta(lock, writeback),
2704+
ktime_ms_delta(sync_inode, lock),
2705+
ktime_ms_delta(end, sync_inode));
26852706
return ret;
26862707
}
26872708

@@ -4870,6 +4891,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
48704891
init_f2fs_rwsem(&sbi->node_change);
48714892
spin_lock_init(&sbi->stat_lock);
48724893
init_f2fs_rwsem(&sbi->cp_rwsem);
4894+
init_f2fs_rwsem(&sbi->cp_enable_rwsem);
48734895
init_f2fs_rwsem(&sbi->quota_sem);
48744896
init_waitqueue_head(&sbi->cp_wait);
48754897
spin_lock_init(&sbi->error_lock);

0 commit comments

Comments
 (0)