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