Skip to content

Commit 68be7f6

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 <[email protected]> Signed-off-by: Jan Kara <[email protected]> Signed-off-by: Christian Brauner <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent cd572b9 commit 68be7f6

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

fs/fs-writeback.c

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

480+
inodep = isw->inodes;
480481
/*
481482
* By the time control reaches here, RCU grace period has passed
482483
* since I_WB_SWITCH assertion and all wb stat update transactions
@@ -487,6 +488,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
487488
* gives us exclusion against all wb related operations on @inode
488489
* including IO list manipulations and stat updates.
489490
*/
491+
relock:
490492
if (old_wb < new_wb) {
491493
spin_lock(&old_wb->list_lock);
492494
spin_lock_nested(&new_wb->list_lock, SINGLE_DEPTH_NESTING);
@@ -495,10 +497,17 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
495497
spin_lock_nested(&old_wb->list_lock, SINGLE_DEPTH_NESTING);
496498
}
497499

498-
for (inodep = isw->inodes; *inodep; inodep++) {
500+
while (*inodep) {
499501
WARN_ON_ONCE((*inodep)->i_wb != old_wb);
500502
if (inode_do_switch_wbs(*inodep, old_wb, new_wb))
501503
nr_switched++;
504+
inodep++;
505+
if (*inodep && need_resched()) {
506+
spin_unlock(&new_wb->list_lock);
507+
spin_unlock(&old_wb->list_lock);
508+
cond_resched();
509+
goto relock;
510+
}
502511
}
503512

504513
spin_unlock(&new_wb->list_lock);

0 commit comments

Comments
 (0)