From: Suparna Bhattacharya Implements async support for wait_on_page_writeback_range. Accepts a wait queue entry as an additional parameter, invokes the async version wait_on_page_writeback and takes care of propagating how much of writeback in the range completed so far (in terms of number of pages), on an -EIOCBRETRY, so that subqueuent retries can accordingly check/wait only on the remaining part of the range. --- mm3osync/mm/filemap.c 2004-04-01 16:22:13.109791312 +0530 +++ linux-2.6.5-rc2-mm1-aio/mm/filemap.c 2004-04-01 15:16:59.923686024 +0530 @@ -190,24 +190,29 @@ EXPORT_SYMBOL(filemap_flush); /* * Wait for writeback to complete against pages indexed by start->end - * inclusive + * inclusive. + * This could be a synchronous wait or could just queue an async + * notification callback depending on the wait queue entry parameter + * Returns the size of the range for which writeback has been completed + * in terms of number of pages. This value is used in the AIO case + * to retry the wait for the remaining part of the range through on + * async notification. */ -static int wait_on_page_writeback_range(struct address_space *mapping, - pgoff_t start, pgoff_t end) +static ssize_t wait_on_page_writeback_range_wq(struct address_space *mapping, + pgoff_t start, pgoff_t end, wait_queue_t *wait) { struct pagevec pvec; int nr_pages; - int ret = 0; - pgoff_t index; + int ret = 0, done = 0; + pgoff_t index, curr = start; if (end < start) return 0; pagevec_init(&pvec, 0); index = start; - while ((index <= end) && - (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, - PAGECACHE_TAG_WRITEBACK, + while (!done && (index <= end) && (nr_pages = pagevec_lookup_tag(&pvec, + mapping, &index, PAGECACHE_TAG_WRITEBACK, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { unsigned i; @@ -218,7 +223,20 @@ static int wait_on_page_writeback_range( if (page->index > end) { continue; } - wait_on_page_writeback(page); + lock_page(page); + if (unlikely(page->mapping != mapping)) { + unlock_page(page); + continue; + } + curr = page->index; + unlock_page(page); + ret = wait_on_page_writeback_wq(page, wait); + if (ret == -EIOCBRETRY) { + if (curr > start) + ret = curr - start; + done = 1; + break; + } if (PageError(page)) ret = -EIO; } @@ -232,9 +250,17 @@ static int wait_on_page_writeback_range( if (test_and_clear_bit(AS_EIO, &mapping->flags)) ret = -EIO; + if (ret == 0) + ret = end - start + 1; + return ret; } +static inline ssize_t wait_on_page_writeback_range(struct address_space + *mapping, pgoff_t start, pgoff_t end) +{ + return wait_on_page_writeback_range_wq(mapping, start, end, NULL); +} /* * Write and wait upon all the pages in the passed range. This is a "data