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@xxxxxxxxxx> --- fs/fs-writeback.c | 30 +++++++++++++++++++++++++----- include/linux/backing-dev.h | 5 +++++ include/linux/writeback.h | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 0423880..7e139d5 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -373,7 +373,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; @@ -417,8 +417,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; } /* @@ -427,10 +429,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); diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 90a1910..7a23f2f 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -110,6 +110,11 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi); extern spinlock_t bdi_lock; extern struct list_head bdi_list; +static inline int wb_is_default_task(struct bdi_writeback *wb) +{ + return wb == &wb->bdi->wb; +} + static inline int bdi_wblist_needs_lock(struct backing_dev_info *bdi) { return test_bit(BDI_wblist_lock, &bdi->state); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 588a449..e070b91 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -68,7 +68,7 @@ struct writeback_control { void writeback_inodes(struct writeback_control *wbc); int inode_wait(void *); void sync_inodes_sb(struct super_block *, int wait); -void wb_do_writeback(struct bdi_writeback *wb, int force_wait); +long wb_do_writeback(struct bdi_writeback *wb, int force_wait); /* writeback.h requires fs.h; it, too, is not included from here. */ static inline void wait_on_inode(struct inode *inode) -- 1.6.4.1.207.g68ea -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html