Commit 088ed5a5 authored by Andrew Morton's avatar Andrew Morton Committed by Ben Collins

[PATCH] dirty_writeback_centisecs fixes

This /proc tunable sets the kupdate interval.  It has a couple of problems:

- No way to turn it off completely (userspace dirty memory management
  solutions require this).

- If it has been set to one hour and then the user resets it to five
  seconds, that resetting will not take effect for up to an hour.

Fix that up by providing a sysctl handler.  Setting the tunable to zero now
disables the kupdate function.
parent a0fc2217
...@@ -1068,6 +1068,8 @@ The pdflush writeback daemons will periodically wake up and write `old' data ...@@ -1068,6 +1068,8 @@ The pdflush writeback daemons will periodically wake up and write `old' data
out to disk. This tunable expresses the interval between those wakeups, in out to disk. This tunable expresses the interval between those wakeups, in
100'ths of a second. 100'ths of a second.
Setting this to zero disables periodic writeback altogether.
dirty_expire_centisecs dirty_expire_centisecs
---------------------- ----------------------
......
...@@ -78,6 +78,10 @@ extern int vm_dirty_ratio; ...@@ -78,6 +78,10 @@ extern int vm_dirty_ratio;
extern int dirty_writeback_centisecs; extern int dirty_writeback_centisecs;
extern int dirty_expire_centisecs; extern int dirty_expire_centisecs;
struct ctl_table;
struct file;
int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *,
void *, size_t *);
void page_writeback_init(void); void page_writeback_init(void);
void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages(struct address_space *mapping);
......
...@@ -271,7 +271,6 @@ static ctl_table kern_table[] = { ...@@ -271,7 +271,6 @@ static ctl_table kern_table[] = {
/* Constants for minimum and maximum testing in vm_table. /* Constants for minimum and maximum testing in vm_table.
We use these as one-element integer vectors. */ We use these as one-element integer vectors. */
static int zero = 0; static int zero = 0;
static int one = 1;
static int one_hundred = 100; static int one_hundred = 100;
...@@ -292,20 +291,7 @@ static ctl_table vm_table[] = { ...@@ -292,20 +291,7 @@ static ctl_table vm_table[] = {
&sysctl_intvec, NULL, &zero, &one_hundred }, &sysctl_intvec, NULL, &zero, &one_hundred },
{VM_DIRTY_WB_CS, "dirty_writeback_centisecs", {VM_DIRTY_WB_CS, "dirty_writeback_centisecs",
&dirty_writeback_centisecs, sizeof(dirty_writeback_centisecs), 0644, &dirty_writeback_centisecs, sizeof(dirty_writeback_centisecs), 0644,
NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, NULL, dirty_writeback_centisecs_handler },
/* Here, we define the range of possible values for
dirty_writeback_centisecs.
The default value is 5 seconds (500 centisec). We will use 1
centisec, the smallest possible value that could make any sort of
sense. If we allowed the user to set the interval to 0 seconds
(which would presumably mean to chew up all of the CPU looking for
dirty pages and writing them out, without taking a break), the
interval would effectively become 1 second (100 centisecs), due to
some nicely documented throttling code in wb_kupdate().
There is no maximum legal value for dirty_writeback. */
&one , NULL},
{VM_DIRTY_EXPIRE_CS, "dirty_expire_centisecs", {VM_DIRTY_EXPIRE_CS, "dirty_expire_centisecs",
&dirty_expire_centisecs, sizeof(dirty_expire_centisecs), 0644, &dirty_expire_centisecs, sizeof(dirty_expire_centisecs), 0644,
NULL, &proc_dointvec}, NULL, &proc_dointvec},
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/sysctl.h>
/* /*
* The maximum number of pages to writeout in a single bdflush/kupdate * The maximum number of pages to writeout in a single bdflush/kupdate
...@@ -329,9 +330,26 @@ static void wb_kupdate(unsigned long arg) ...@@ -329,9 +330,26 @@ static void wb_kupdate(unsigned long arg)
} }
if (time_before(next_jif, jiffies + HZ)) if (time_before(next_jif, jiffies + HZ))
next_jif = jiffies + HZ; next_jif = jiffies + HZ;
if (dirty_writeback_centisecs)
mod_timer(&wb_timer, next_jif); mod_timer(&wb_timer, next_jif);
} }
/*
* sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
*/
int dirty_writeback_centisecs_handler(ctl_table *table, int write,
struct file *file, void *buffer, size_t *length)
{
proc_dointvec(table, write, file, buffer, length);
if (dirty_writeback_centisecs) {
mod_timer(&wb_timer,
jiffies + (dirty_writeback_centisecs * HZ) / 100);
} else {
del_timer(&wb_timer);
}
return 0;
}
static void wb_timer_fn(unsigned long unused) static void wb_timer_fn(unsigned long unused)
{ {
if (pdflush_operation(wb_kupdate, 0) < 0) if (pdflush_operation(wb_kupdate, 0) < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment