Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: don't trigger data flush in foreground operation

Data flush can generate heavy IO and cause long latency during
flush, so it's not appropriate to trigger it in foreground
operation.

And also, we may face below potential deadlock during data flush:
- f2fs_write_multi_pages
- f2fs_write_raw_pages
- f2fs_write_single_data_page
- f2fs_balance_fs
- f2fs_balance_fs_bg
- f2fs_sync_dirty_inodes
- filemap_fdatawrite -- stuck on flush same cluster

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Chao Yu and committed by
Jaegeuk Kim
7bcd0cfa 62f63eea

+6 -6
+1 -1
fs/f2fs/f2fs.h
··· 3236 3236 void f2fs_drop_inmem_page(struct inode *inode, struct page *page); 3237 3237 int f2fs_commit_inmem_pages(struct inode *inode); 3238 3238 void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need); 3239 - void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi); 3239 + void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg); 3240 3240 int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino); 3241 3241 int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi); 3242 3242 int f2fs_flush_device_cache(struct f2fs_sb_info *sbi);
+1 -1
fs/f2fs/gc.c
··· 113 113 prefree_segments(sbi), free_segments(sbi)); 114 114 115 115 /* balancing f2fs's metadata periodically */ 116 - f2fs_balance_fs_bg(sbi); 116 + f2fs_balance_fs_bg(sbi, true); 117 117 next: 118 118 sb_end_write(sbi->sb); 119 119
+1 -1
fs/f2fs/node.c
··· 1976 1976 goto skip_write; 1977 1977 1978 1978 /* balancing f2fs's metadata in background */ 1979 - f2fs_balance_fs_bg(sbi); 1979 + f2fs_balance_fs_bg(sbi, true); 1980 1980 1981 1981 /* collect a number of dirty node pages and write together */ 1982 1982 if (wbc->sync_mode != WB_SYNC_ALL &&
+3 -3
fs/f2fs/segment.c
··· 496 496 497 497 /* balance_fs_bg is able to be pending */ 498 498 if (need && excess_cached_nats(sbi)) 499 - f2fs_balance_fs_bg(sbi); 499 + f2fs_balance_fs_bg(sbi, false); 500 500 501 501 if (!f2fs_is_checkpoint_ready(sbi)) 502 502 return; ··· 511 511 } 512 512 } 513 513 514 - void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) 514 + void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) 515 515 { 516 516 if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 517 517 return; ··· 540 540 excess_dirty_nats(sbi) || 541 541 excess_dirty_nodes(sbi) || 542 542 f2fs_time_over(sbi, CP_TIME)) { 543 - if (test_opt(sbi, DATA_FLUSH)) { 543 + if (test_opt(sbi, DATA_FLUSH) && from_bg) { 544 544 struct blk_plug plug; 545 545 546 546 mutex_lock(&sbi->flush_lock);