diff -purN -X /home/mbligh/.diff.exclude 550-gang_lookup_next/mm/page-writeback.c 555-aio-gang_lookup-fix/mm/page-writeback.c
--- 550-gang_lookup_next/mm/page-writeback.c	2004-03-14 09:59:55.000000000 -0800
+++ 555-aio-gang_lookup-fix/mm/page-writeback.c	2004-03-14 10:00:04.000000000 -0800
@@ -576,7 +576,7 @@ static ssize_t operate_on_page_range(str
 {
 	pgoff_t first = pos >> PAGE_CACHE_SHIFT;
 	pgoff_t last = (pos + count - 1) >> PAGE_CACHE_SHIFT;	/* inclusive */
-	pgoff_t next = first;
+	pgoff_t next = first, curr = first;
 	struct pagevec pvec;
 	ssize_t ret = 0, bytes = 0;
 	int i;
@@ -585,25 +585,25 @@ static ssize_t operate_on_page_range(str
 		return 0;
 
 	pagevec_init(&pvec, 0);
-	while (pagevec_lookup(&pvec, mapping, next,
+	while (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];
 
-			lock_page(page);	/* stabilise ->index */
-			if (!page->mapping) {	/* truncated */
-				unlock_page(page);
-				next++;
-				continue;
-			}
-			next = page->index + 1;
-			ret = (*operator)(page);
-			if (ret == -EIOCBRETRY)
+			curr = page->index;
+			if ((curr > next) || !page->mapping) /* truncated ?*/ {
+				curr = next;
 				break;
-			if (PageError(page)) {
-				if (!ret)
-					ret = -EIO;
+			} else {
+				ret = (*operator)(page);
+				if (ret == -EIOCBRETRY)
+					break;
+				if (PageError(page)) {
+					if (!ret)
+						ret = -EIO;
+				}
 			}
+			curr++;
 			if (next > last)
 				break;
 		}
@@ -611,7 +611,7 @@ static ssize_t operate_on_page_range(str
 		if ((next > last) || (ret == -EIOCBRETRY))
 			break;
 	}
-	bytes = (next << PAGE_CACHE_SHIFT) - pos;
+	bytes = (curr << PAGE_CACHE_SHIFT) - pos;
 	if (bytes > count)
 		bytes = count;
 	return (bytes && (!ret || (ret == -EIOCBRETRY))) ? bytes : ret;
@@ -619,7 +619,6 @@ static ssize_t operate_on_page_range(str
 
 static int page_waiter(struct page *page)
 {
-	unlock_page(page);
 	return wait_on_page_writeback_wq(page, current->io_wait);
 }
 
@@ -636,6 +635,11 @@ static int page_writer(struct page *page
 		.nr_to_write	= 1,
 	};
 
+	lock_page(page);
+	if (!page->mapping) {	/* truncated */
+		unlock_page(page);
+		return 0;
+	}
 	if (!test_clear_page_dirty(page)) {
 		unlock_page(page);
 		return 0;