From 7ecebe5e07958a0b7e54a560dbc24144287c6b41 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 27 Feb 2015 13:13:14 +0100 Subject: [PATCH] f2fs: add cond_resched() to sync_dirty_dir_inodes() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In a preempt-off enviroment a alot of FS activity (write/delete) I run into a CPU stall: | NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [kworker/u2:2:59] | Modules linked in: | CPU: 0 PID: 59 Comm: kworker/u2:2 Tainted: G W 3.19.0-00010-g10c11c51ffed #153 | Workqueue: writeback bdi_writeback_workfn (flush-179:0) | task: df230000 ti: df23e000 task.ti: df23e000 | PC is at __submit_merged_bio+0x6c/0x110 | LR is at f2fs_submit_merged_bio+0x74/0x80 … | [] (gic_handle_irq) from [] (__irq_svc+0x44/0x5c) | Exception stack(0xdf23fb48 to 0xdf23fb90) | fb40: deef3484 ffff0001 ffff0001 00000027 deef3484 00000000 | fb60: deef3440 00000000 de426000 deef34ec deefc440 df23fbb4 df23fbb8 df23fb90 | fb80: c02191f0 c0218fa0 60000013 ffffffff | [] (__irq_svc) from [] (__submit_merged_bio+0x6c/0x110) | [] (__submit_merged_bio) from [] (f2fs_submit_merged_bio+0x74/0x80) | [] (f2fs_submit_merged_bio) from [] (sync_dirty_dir_inodes+0x70/0x78) | [] (sync_dirty_dir_inodes) from [] (write_checkpoint+0x104/0xc10) | [] (write_checkpoint) from [] (f2fs_sync_fs+0x80/0xbc) | [] (f2fs_sync_fs) from [] (f2fs_balance_fs_bg+0x4c/0x68) | [] (f2fs_balance_fs_bg) from [] (f2fs_write_node_pages+0x40/0x110) | [] (f2fs_write_node_pages) from [] (do_writepages+0x34/0x48) | [] (do_writepages) from [] (__writeback_single_inode+0x50/0x228) | [] (__writeback_single_inode) from [] (writeback_sb_inodes+0x1a8/0x378) | [] (writeback_sb_inodes) from [] (__writeback_inodes_wb+0x90/0xc8) | [] (__writeback_inodes_wb) from [] (wb_writeback+0x1dc/0x28c) | [] (wb_writeback) from [] (bdi_writeback_workfn+0x2ac/0x460) | [] (bdi_writeback_workfn) from [] (process_one_work+0x11c/0x3a4) | [] (process_one_work) from [] (worker_thread+0x17c/0x490) | [] (worker_thread) from [] (kthread+0xec/0x100) | [] (kthread) from [] (ret_from_fork+0x14/0x24) As it turns out, the code loops in sync_dirty_dir_inodes() and waits for others to make progress but since it never leaves the CPU there is no progress made. At the time of this stall, there is also a rm process blocked: | rm R running 0 1989 1774 0x00000000 | [] (__schedule) from [] (__cond_resched+0x30/0x4c) | [] (__cond_resched) from [] (_cond_resched+0x4c/0x54) | [] (_cond_resched) from [] (truncate_inode_pages_range+0x1f0/0x5e8) | [] (truncate_inode_pages_range) from [] (truncate_inode_pages+0x28/0x30) | [] (truncate_inode_pages) from [] (truncate_inode_pages_final+0x60/0x64) | [] (truncate_inode_pages_final) from [] (f2fs_evict_inode+0x4c/0x268) | [] (f2fs_evict_inode) from [] (evict+0x94/0x140) | [] (evict) from [] (iput+0xc8/0x134) | [] (iput) from [] (d_delete+0x154/0x180) | [] (d_delete) from [] (vfs_rmdir+0x114/0x12c) | [] (vfs_rmdir) from [] (do_rmdir+0x158/0x168) | [] (do_rmdir) from [] (SyS_unlinkat+0x30/0x3c) | [] (SyS_unlinkat) from [] (ret_fast_syscall+0x0/0x4c) As explained by Jaegeuk Kim: |This inode is the directory (c.f., do_rmdir) causing a infinite loop on |sync_dirty_dir_inodes. |The sync_dirty_dir_inodes tries to flush dirty dentry pages, but if the |inode is under eviction, it submits bios and do it again until eviction |is finished. This patch adds a cond_resched() (as suggested by Jaegeuk) after a BIO is submitted so other thread can make progress. Signed-off-by: Sebastian Andrzej Siewior [Jaegeuk Kim: change fs/f2fs to f2fs in subject as naming convention] Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 81d6d2f0e8ed..53bc32804841 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -795,6 +795,7 @@ retry: * wribacking dentry pages in the freeing inode. */ f2fs_submit_merged_bio(sbi, DATA, WRITE); + cond_resched(); } goto retry; } -- 2.20.1