Commit f0e10c64 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] pdflush cleanup

Writeback/pdflush cleanup patch from Steven Augart

* Exposes nr_pdflush_threads as /proc/sys/vm/nr_pdflush_threads, read-only.

  (I like this - I expect that management of the pdflush thread pool
  will be important for many-spindle machines, and this is a neat way
  of getting at the info).

* Adds minimum and maximum checking to the five writable pdflush
  and fs-writeback  parameters.

* Minor indentation fix in sysctl.c

* mm/pdflush.c now includes linux/writeback.h, which prototypes
  pdflush_operation.  This is so that the compiler can
  automatically check that the prototype matches the definition.

* Adds a few comments to existing code.
parent 06be3a5e
...@@ -30,7 +30,10 @@ ...@@ -30,7 +30,10 @@
struct file; struct file;
#define CTL_MAXNAME 10 #define CTL_MAXNAME 10 /* how many path components do we allow in a
call to sysctl? In other words, what is
the largest acceptable value for the nlen
member of a struct __sysctl_args to have? */
struct __sysctl_args { struct __sysctl_args {
int *name; int *name;
...@@ -145,6 +148,7 @@ enum ...@@ -145,6 +148,7 @@ enum
VM_DIRTY_SYNC=13, /* dirty_sync_ratio */ VM_DIRTY_SYNC=13, /* dirty_sync_ratio */
VM_DIRTY_WB_CS=14, /* dirty_writeback_centisecs */ VM_DIRTY_WB_CS=14, /* dirty_writeback_centisecs */
VM_DIRTY_EXPIRE_CS=15, /* dirty_expire_centisecs */ VM_DIRTY_EXPIRE_CS=15, /* dirty_expire_centisecs */
VM_NR_PDFLUSH_THREADS=16, /* nr_pdflush_threads */
}; };
......
...@@ -49,15 +49,22 @@ static inline void wait_on_inode(struct inode *inode) ...@@ -49,15 +49,22 @@ static inline void wait_on_inode(struct inode *inode)
/* /*
* mm/page-writeback.c * mm/page-writeback.c
*/ */
/* These 5 are exported to sysctl. */
extern int dirty_background_ratio; extern int dirty_background_ratio;
extern int dirty_async_ratio; extern int dirty_async_ratio;
extern int dirty_sync_ratio; extern int dirty_sync_ratio;
extern int dirty_writeback_centisecs; extern int dirty_writeback_centisecs;
extern int dirty_expire_centisecs; extern int dirty_expire_centisecs;
void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages(struct address_space *mapping);
void balance_dirty_pages_ratelimited(struct address_space *mapping); void balance_dirty_pages_ratelimited(struct address_space *mapping);
int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
int do_writepages(struct address_space *mapping, int *nr_to_write); int do_writepages(struct address_space *mapping, int *nr_to_write);
/* pdflush.c */
extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
read-only. */
#endif /* WRITEBACK_H */ #endif /* WRITEBACK_H */
...@@ -258,6 +258,13 @@ static ctl_table kern_table[] = { ...@@ -258,6 +258,13 @@ static ctl_table kern_table[] = {
{0} {0}
}; };
/* Constants for minimum and maximum testing in vm_table.
We use these as one-element integer vectors. */
static int zero = 0;
static int one = 1;
static int one_hundred = 100;
static ctl_table vm_table[] = { static ctl_table vm_table[] = {
{VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory, {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec}, sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
...@@ -266,18 +273,37 @@ static ctl_table vm_table[] = { ...@@ -266,18 +273,37 @@ static ctl_table vm_table[] = {
{VM_PAGE_CLUSTER, "page-cluster", {VM_PAGE_CLUSTER, "page-cluster",
&page_cluster, sizeof(int), 0644, NULL, &proc_dointvec}, &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
{VM_DIRTY_BACKGROUND, "dirty_background_ratio", {VM_DIRTY_BACKGROUND, "dirty_background_ratio",
&dirty_background_ratio, sizeof(dirty_background_ratio), &dirty_background_ratio, sizeof(dirty_background_ratio),
0644, NULL, &proc_dointvec}, 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
&zero, &one_hundred },
{VM_DIRTY_ASYNC, "dirty_async_ratio", &dirty_async_ratio, {VM_DIRTY_ASYNC, "dirty_async_ratio", &dirty_async_ratio,
sizeof(dirty_async_ratio), 0644, NULL, &proc_dointvec}, sizeof(dirty_async_ratio), 0644, NULL, &proc_dointvec_minmax,
&sysctl_intvec, NULL, &zero, &one_hundred },
{VM_DIRTY_SYNC, "dirty_sync_ratio", &dirty_sync_ratio, {VM_DIRTY_SYNC, "dirty_sync_ratio", &dirty_sync_ratio,
sizeof(dirty_sync_ratio), 0644, NULL, &proc_dointvec}, sizeof(dirty_sync_ratio), 0644, NULL, &proc_dointvec_minmax,
&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}, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
/* 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},
{ VM_NR_PDFLUSH_THREADS, "nr_pdflush_threads",
&nr_pdflush_threads, sizeof nr_pdflush_threads,
0444 /* read-only*/, NULL, &proc_dointvec},
{0} {0}
}; };
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#define SYNC_WRITEBACK_PAGES 1500 #define SYNC_WRITEBACK_PAGES 1500
/* The following parameters are exported via /proc/sys/vm */
/* /*
* Dirty memory thresholds, in percentages * Dirty memory thresholds, in percentages
*/ */
...@@ -67,15 +69,18 @@ int dirty_async_ratio = 50; ...@@ -67,15 +69,18 @@ int dirty_async_ratio = 50;
int dirty_sync_ratio = 60; int dirty_sync_ratio = 60;
/* /*
* The interval between `kupdate'-style writebacks. * The interval between `kupdate'-style writebacks, in centiseconds
* (hundredths of a second)
*/ */
int dirty_writeback_centisecs = 5 * 100; int dirty_writeback_centisecs = 5 * 100;
/* /*
* The largest amount of time for which data is allowed to remain dirty * The longest amount of time for which data is allowed to remain dirty
*/ */
int dirty_expire_centisecs = 30 * 100; int dirty_expire_centisecs = 30 * 100;
/* End of sysctl-exported parameters */
static void background_writeout(unsigned long _min_pages); static void background_writeout(unsigned long _min_pages);
...@@ -233,7 +238,8 @@ static void wb_kupdate(unsigned long arg) ...@@ -233,7 +238,8 @@ static void wb_kupdate(unsigned long arg)
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)
mod_timer(&wb_timer, jiffies + HZ); mod_timer(&wb_timer, jiffies + HZ); /* delay 1 second */
} }
static int __init wb_timer_init(void) static int __init wb_timer_init(void)
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/sched.h> // Needed by writeback.h
#include <linux/fs.h> // Needed by writeback.h
#include <linux/writeback.h> // Prototypes pdflush_operation()
/* /*
...@@ -44,8 +47,11 @@ static spinlock_t pdflush_lock = SPIN_LOCK_UNLOCKED; ...@@ -44,8 +47,11 @@ static spinlock_t pdflush_lock = SPIN_LOCK_UNLOCKED;
/* /*
* The count of currently-running pdflush threads. Protected * The count of currently-running pdflush threads. Protected
* by pdflush_lock. * by pdflush_lock.
*
* Readable by sysctl, but not writable. Published to userspace at
* /proc/sys/vm/nr_pdflush_threads.
*/ */
static int nr_pdflush_threads = 0; int nr_pdflush_threads = 0;
/* /*
* The time at which the pdflush thread pool last went empty * The time at which the pdflush thread pool last went empty
......
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