Skip to content

Commit 7594dae

Browse files
jankaragregkh
authored andcommitted
writeback: Avoid softlockup when switching many inodes
[ Upstream commit 66c14dc ] process_inode_switch_wbs_work() can be switching over 100 inodes to a different cgroup. Since switching an inode requires counting all dirty & under-writeback pages in the address space of each inode, this can take a significant amount of time. Add a possibility to reschedule after processing each inode to avoid softlockups. Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ab0d013 commit 7594dae

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

fs/fs-writeback.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
479479
*/
480480
down_read(&bdi->wb_switch_rwsem);
481481

482+
inodep = isw->inodes;
482483
/*
483484
* By the time control reaches here, RCU grace period has passed
484485
* since I_WB_SWITCH assertion and all wb stat update transactions
@@ -489,6 +490,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
489490
* gives us exclusion against all wb related operations on @inode
490491
* including IO list manipulations and stat updates.
491492
*/
493+
relock:
492494
if (old_wb < new_wb) {
493495
spin_lock(&old_wb->list_lock);
494496
spin_lock_nested(&new_wb->list_lock, SINGLE_DEPTH_NESTING);
@@ -497,10 +499,17 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
497499
spin_lock_nested(&old_wb->list_lock, SINGLE_DEPTH_NESTING);
498500
}
499501

500-
for (inodep = isw->inodes; *inodep; inodep++) {
502+
while (*inodep) {
501503
WARN_ON_ONCE((*inodep)->i_wb != old_wb);
502504
if (inode_do_switch_wbs(*inodep, old_wb, new_wb))
503505
nr_switched++;
506+
inodep++;
507+
if (*inodep && need_resched()) {
508+
spin_unlock(&new_wb->list_lock);
509+
spin_unlock(&old_wb->list_lock);
510+
cond_resched();
511+
goto relock;
512+
}
504513
}
505514

506515
spin_unlock(&new_wb->list_lock);

0 commit comments

Comments
 (0)