]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
f2fs: don't trigger data flush in foreground operation
authorChao Yu <yuchao0@huawei.com>
Thu, 19 Mar 2020 11:57:58 +0000 (19:57 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 31 Mar 2020 03:46:24 +0000 (20:46 -0700)
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>
fs/f2fs/f2fs.h
fs/f2fs/gc.c
fs/f2fs/node.c
fs/f2fs/segment.c

index 47c8c763a9b5f5258cc0c5e209074531b84cb119..d84c53782c06df04104963266906325f168c935a 100644 (file)
@@ -3236,7 +3236,7 @@ void f2fs_drop_inmem_pages(struct inode *inode);
 void f2fs_drop_inmem_page(struct inode *inode, struct page *page);
 int f2fs_commit_inmem_pages(struct inode *inode);
 void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need);
-void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi);
+void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg);
 int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino);
 int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi);
 int f2fs_flush_device_cache(struct f2fs_sb_info *sbi);
index f122fe3dbba3bcde069cc9ed245938343d13374a..26248c8936db0f121ead3384215103399c8bb2dd 100644 (file)
@@ -113,7 +113,7 @@ do_gc:
                                prefree_segments(sbi), free_segments(sbi));
 
                /* balancing f2fs's metadata periodically */
-               f2fs_balance_fs_bg(sbi);
+               f2fs_balance_fs_bg(sbi, true);
 next:
                sb_end_write(sbi->sb);
 
index 542335bdc10020353c75730dfd928dc3d8e4f8f8..ecbd6bd14a494529a30590e30a26c6838c7bd4de 100644 (file)
@@ -1976,7 +1976,7 @@ static int f2fs_write_node_pages(struct address_space *mapping,
                goto skip_write;
 
        /* balancing f2fs's metadata in background */
-       f2fs_balance_fs_bg(sbi);
+       f2fs_balance_fs_bg(sbi, true);
 
        /* collect a number of dirty node pages and write together */
        if (wbc->sync_mode != WB_SYNC_ALL &&
index 601d67e72c50780638399895a4b3cf2b52b42763..aece09a184fa0a0ad71113150567272dac6cca03 100644 (file)
@@ -496,7 +496,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
 
        /* balance_fs_bg is able to be pending */
        if (need && excess_cached_nats(sbi))
-               f2fs_balance_fs_bg(sbi);
+               f2fs_balance_fs_bg(sbi, false);
 
        if (!f2fs_is_checkpoint_ready(sbi))
                return;
@@ -511,7 +511,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
        }
 }
 
-void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
+void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
 {
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                return;
@@ -540,7 +540,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
                        excess_dirty_nats(sbi) ||
                        excess_dirty_nodes(sbi) ||
                        f2fs_time_over(sbi, CP_TIME)) {
-               if (test_opt(sbi, DATA_FLUSH)) {
+               if (test_opt(sbi, DATA_FLUSH) && from_bg) {
                        struct blk_plug plug;
 
                        mutex_lock(&sbi->flush_lock);