Skip to content

Commit 76ee199

Browse files
laveeshbgregkh
authored andcommitted
writeback: fix 100% CPU usage when dirtytime_expire_interval is 0
[ Upstream commit 543467d ] When vm.dirtytime_expire_seconds is set to 0, wakeup_dirtytime_writeback() schedules delayed work with a delay of 0, causing immediate execution. The function then reschedules itself with 0 delay again, creating an infinite busy loop that causes 100% kworker CPU usage. Fix by: - Only scheduling delayed work in wakeup_dirtytime_writeback() when dirtytime_expire_interval is non-zero - Cancelling the delayed work in dirtytime_interval_handler() when the interval is set to 0 - Adding a guard in start_dirtytime_writeback() for defensive coding Tested by booting kernel in QEMU with virtme-ng: - Before fix: kworker CPU spikes to ~73% - After fix: CPU remains at normal levels - Setting interval back to non-zero correctly resumes writeback Fixes: a2f4870 ("fs: make sure the timestamps for lazytime inodes eventually get written") Cc: stable@vger.kernel.org Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220227 Signed-off-by: Laveesh Bansal <laveeshb@laveeshbansal.com> Link: https://patch.msgid.link/20260106145059.543282-2-laveeshb@laveeshbansal.com Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org> [ adapted system_percpu_wq to system_wq for the workqueue used in dirtytime_interval_handler() ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5aac392 commit 76ee199

1 file changed

Lines changed: 10 additions & 4 deletions

File tree

fs/fs-writeback.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,12 +2418,14 @@ static void wakeup_dirtytime_writeback(struct work_struct *w)
24182418
wb_wakeup(wb);
24192419
}
24202420
rcu_read_unlock();
2421-
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
2421+
if (dirtytime_expire_interval)
2422+
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
24222423
}
24232424

24242425
static int __init start_dirtytime_writeback(void)
24252426
{
2426-
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
2427+
if (dirtytime_expire_interval)
2428+
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
24272429
return 0;
24282430
}
24292431
__initcall(start_dirtytime_writeback);
@@ -2434,8 +2436,12 @@ int dirtytime_interval_handler(const struct ctl_table *table, int write,
24342436
int ret;
24352437

24362438
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2437-
if (ret == 0 && write)
2438-
mod_delayed_work(system_wq, &dirtytime_work, 0);
2439+
if (ret == 0 && write) {
2440+
if (dirtytime_expire_interval)
2441+
mod_delayed_work(system_wq, &dirtytime_work, 0);
2442+
else
2443+
cancel_delayed_work_sync(&dirtytime_work);
2444+
}
24392445
return ret;
24402446
}
24412447

0 commit comments

Comments
 (0)