summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2009-06-25 09:35:01 +0200
committerJens Axboe <jens.axboe@oracle.com>2009-06-25 12:36:33 +0200
commit3336a136d7ae49d91f4da35250feffb886f85344 (patch)
tree3829c54f9fd654f932904170d8d54c521466e051 /fs
parentf5a0e4626031b61e1ebb20b2d6c643788847aa3b (diff)
writeback: allow sleepy exit of default writeback task
Since we do lazy create of default writeback tasks for a bdi, we can allow sleepy exit if it has been completely idle for 5 minutes. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/fs-writeback.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 806948389ab2..796b24389485 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -369,7 +369,7 @@ static struct bdi_work *get_next_work_item(struct backing_dev_info *bdi,
/*
* Retrieve work items and do the writeback they describe
*/
-void wb_do_writeback(struct bdi_writeback *wb, int force_wait)
+long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
{
struct backing_dev_info *bdi = wb->bdi;
struct bdi_work *work;
@@ -414,8 +414,10 @@ void wb_do_writeback(struct bdi_writeback *wb, int force_wait)
global_page_state(NR_UNSTABLE_NFS) +
(inodes_stat.nr_inodes - inodes_stat.nr_unused);
- wb_writeback(wb, nr_pages, NULL, WB_SYNC_NONE, 1);
+ wrote = wb_writeback(wb, nr_pages, NULL, WB_SYNC_NONE, 1);
}
+
+ return wrote;
}
/*
@@ -424,10 +426,28 @@ void wb_do_writeback(struct bdi_writeback *wb, int force_wait)
*/
int bdi_writeback_task(struct bdi_writeback *wb)
{
+ unsigned long last_active = jiffies;
+ unsigned long wait_jiffies = -1UL;
+ long pages_written;
+
while (!kthread_should_stop()) {
- unsigned long wait_jiffies;
+ pages_written = wb_do_writeback(wb, 0);
+
+ if (pages_written)
+ last_active = jiffies;
+ else if (wait_jiffies != -1UL) {
+ unsigned long max_idle;
- wb_do_writeback(wb, 0);
+ /*
+ * Longest period of inactivity that we tolerate. If we
+ * see dirty data again later, the task will get
+ * recreated automatically.
+ */
+ max_idle = max(5UL * 60 * HZ, wait_jiffies);
+ if (time_after(jiffies, max_idle + last_active) &&
+ wb_is_default_task(wb))
+ break;
+ }
wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10);
set_current_state(TASK_INTERRUPTIBLE);