mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
jbd2: check need_resched() when skipping busy checkpoint buffers
journal_shrink_one_cp_list() skips busy checkpoint buffers when called
with JBD2_SHRINK_BUSY_SKIP. The continue statement on this path also
skips the need_resched() check at the end of the loop body.
Consequently, when a checkpoint list contains mostly busy buffers, the
shrinker can walk the entire list while holding journal->j_list_lock,
even when a reschedule has been requested. Large checkpoint lists under
memory pressure can therefore cause long lock hold times and leave other
CPUs spinning on j_list_lock, resulting in soft lockups or RCU stalls.
Route the busy-buffer path through the need_resched() check so that the
shrinker can release j_list_lock and reschedule promptly, restoring
parity with the clean-buffer path, which already checks need_resched().
This does not change which checkpoint buffers are eligible for removal.
Fixes: b98dba273a ("jbd2: remove journal_clean_one_cp_list()")
Cc: stable@vger.kernel.org
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260713102229.1598812-2-max.kellermann@ionos.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
fef5265969
commit
f213e12ff5
|
|
@ -389,7 +389,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
|
|||
ret = jbd2_journal_try_remove_checkpoint(jh);
|
||||
if (ret < 0) {
|
||||
if (type == JBD2_SHRINK_BUSY_SKIP)
|
||||
continue;
|
||||
goto next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -400,6 +400,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
|
|||
break;
|
||||
}
|
||||
|
||||
next:
|
||||
if (need_resched())
|
||||
break;
|
||||
} while (jh != last_jh);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user