Skip to content

Commit e166880

Browse files
committed
Merge patch series "Fix vm.dirtytime_expire_seconds=0 causing 100% CPU"
Laveesh Bansal <laveeshb@laveeshbansal.com> says: Setting vm.dirtytime_expire_seconds to 0 causes wakeup_dirtytime_writeback() to reschedule itself with a delay of 0, creating an infinite busy loop that spins kworker at 100% CPU. This series: - Patch 1: Fixes the bug by handling interval=0 as "disable writeback" (consistent with dirty_writeback_centisecs behavior) - Patch 2: Documents that setting the value to 0 disables writeback Tested by booting kernels in QEMU with virtme-ng: - Buggy kernel: kworker CPU spikes to ~73% when interval set to 0 - Fixed kernel: CPU remains normal, writeback correctly disabled - Re-enabling (0 -> non-zero): writeback resumes correctly * patches from https://patch.msgid.link/20260106145059.543282-1-laveeshb@laveeshbansal.com: docs: clarify that dirtytime_expire_seconds=0 disables writeback writeback: fix 100% CPU usage when dirtytime_expire_interval is 0 Link: https://patch.msgid.link/20260106145059.543282-1-laveeshb@laveeshbansal.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents c644bce + 30ef9a2 commit e166880

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

Documentation/admin-guide/sysctl/vm.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ eventually gets pushed out to disk. This tunable is used to define when dirty
231231
inode is old enough to be eligible for writeback by the kernel flusher threads.
232232
And, it is also used as the interval to wakeup dirtytime_writeback thread.
233233

234+
Setting this to zero disables periodic dirtytime writeback.
235+
234236

235237
dirty_writeback_centisecs
236238
=========================

fs/fs-writeback.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,7 +2492,8 @@ static void wakeup_dirtytime_writeback(struct work_struct *w)
24922492
wb_wakeup(wb);
24932493
}
24942494
rcu_read_unlock();
2495-
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
2495+
if (dirtytime_expire_interval)
2496+
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
24962497
}
24972498

24982499
static int dirtytime_interval_handler(const struct ctl_table *table, int write,
@@ -2501,8 +2502,12 @@ static int dirtytime_interval_handler(const struct ctl_table *table, int write,
25012502
int ret;
25022503

25032504
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2504-
if (ret == 0 && write)
2505-
mod_delayed_work(system_percpu_wq, &dirtytime_work, 0);
2505+
if (ret == 0 && write) {
2506+
if (dirtytime_expire_interval)
2507+
mod_delayed_work(system_percpu_wq, &dirtytime_work, 0);
2508+
else
2509+
cancel_delayed_work_sync(&dirtytime_work);
2510+
}
25062511
return ret;
25072512
}
25082513

@@ -2519,7 +2524,8 @@ static const struct ctl_table vm_fs_writeback_table[] = {
25192524

25202525
static int __init start_dirtytime_writeback(void)
25212526
{
2522-
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
2527+
if (dirtytime_expire_interval)
2528+
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
25232529
register_sysctl_init("vm", vm_fs_writeback_table);
25242530
return 0;
25252531
}

0 commit comments

Comments
 (0)