From: Suparna Bhattacharya <suparna@in.ibm.com>

The attached patch helped fix some short writes I was seeing with O_SYNC
and AIO.  Most likely this happened in the situation when pagevec_lookup()
didn't find all the pages being looked up in the page cache.  In that
situation accounting of how much of the range was written back wasn't being
taken care of correctly.




 mm/page-writeback.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff -puN mm/page-writeback.c~aio-O_SYNC-short-write-fix mm/page-writeback.c
--- 25/mm/page-writeback.c~aio-O_SYNC-short-write-fix	2004-01-04 17:39:52.000000000 -0800
+++ 25-akpm/mm/page-writeback.c	2004-01-04 17:39:52.000000000 -0800
@@ -643,19 +643,19 @@ static ssize_t operate_on_page_range(str
 	pgoff_t next = first, curr = first;
 	struct pagevec pvec;
 	ssize_t ret = 0, bytes = 0;
-	int i;
+	int i, nr;
 
 	if (count == 0)
 		return 0;
 
 	pagevec_init(&pvec, 0);
-	while (pagevec_lookup(&pvec, mapping, &next,
-				min((pgoff_t)PAGEVEC_SIZE, last - next + 1))) {
+	while ((nr = pagevec_lookup(&pvec, mapping, &next,
+				min((pgoff_t)PAGEVEC_SIZE, last - next + 1)))) {
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 
 			curr = page->index;
-			if ((curr > next) || !page->mapping) /* truncated ?*/ {
+			if (page->mapping != mapping) /* truncated ?*/ {
 				curr = next;
 				break;
 			} else {
@@ -665,16 +665,17 @@ static ssize_t operate_on_page_range(str
 				if (PageError(page)) {
 					if (!ret)
 						ret = -EIO;
-				}
+				} else
+					curr++;
 			}
-			curr++;
-			if (next > last)
-				break;
 		}
 		pagevec_release(&pvec);
-		if ((next > last) || (ret == -EIOCBRETRY))
+		if ((ret == -EIOCBRETRY) || (next > last))
 			break;
 	}
+	if (!nr)
+		curr = last + 1;
+
 	bytes = (curr << PAGE_CACHE_SHIFT) - pos;
 	if (bytes > count)
 		bytes = count;

_