Subject: writeback: quit on wrap for .range_cyclic (write_cache_pages) Date: Fri Dec 16 19:10:57 CST 2011 Convert wbc.range_cyclic to new behavior: when past EOF, abort the writeback of the current inode, which instructs writeback_single_inode() to delay it for a while if necessary. This is the right behavior for - sync writeback (is already so with range_whole) we have scanned the inode address space, and don't care any more newly dirtied pages. So shall update its i_dirtied_when and exclude it from the todo list. - periodic writeback any more newly dirtied pages may be delayed for a while. This also prevents pointless IO for busy overwriters. - background writeback irrelevant because it generally don't care the dirty timestamp. That should get rid of one inefficient IO pattern of .range_cyclic when writeback_index wraps, in which the submitted pages may be consisted of two distant ranges: submit [10000-10100], (wrap), submit [0-100]. CC: Christoph Lameter CC: Peter Zijlstra CC: Jens Axboe CC: Nick Piggin CC: Jan Kara Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) --- linux.orig/mm/page-writeback.c 2011-12-16 19:05:52.000000000 +0800 +++ linux/mm/page-writeback.c 2011-12-16 19:10:23.000000000 +0800 @@ -826,11 +826,9 @@ int write_cache_pages(struct address_spa int done = 0; struct pagevec pvec; int nr_pages; - pgoff_t uninitialized_var(writeback_index); pgoff_t index; pgoff_t end; /* Inclusive */ pgoff_t done_index; - int cycled; int range_whole = 0; long nr_to_write = wbc->nr_to_write; @@ -841,21 +839,15 @@ int write_cache_pages(struct address_spa pagevec_init(&pvec, 0); if (wbc->range_cyclic) { - writeback_index = mapping->writeback_index; /* prev offset */ - index = writeback_index; - if (index == 0) - cycled = 1; - else - cycled = 0; + index = mapping->writeback_index; /* prev offset */ end = -1; } else { index = wbc->range_start >> PAGE_CACHE_SHIFT; end = wbc->range_end >> PAGE_CACHE_SHIFT; if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) range_whole = 1; - cycled = 1; /* ignore range_cyclic tests */ } -retry: + done_index = index; while (!done && (index <= end)) { int i; @@ -863,8 +855,10 @@ retry: nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, PAGECACHE_TAG_DIRTY, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); - if (nr_pages == 0) + if (nr_pages == 0) { + done_index = 0; break; + } for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; @@ -967,17 +961,6 @@ continue_unlock: pagevec_release(&pvec); cond_resched(); } - if (!cycled && !done) { - /* - * range_cyclic: - * We hit the last page and there is more work to be done: wrap - * back to the start of the file - */ - cycled = 1; - index = 0; - end = writeback_index - 1; - goto retry; - } if (!wbc->no_nrwrite_index_update) { if (wbc->range_cyclic || (range_whole && nr_to_write > 0)) mapping->writeback_index = done_index;