diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/fs/hugetlbfs/inode.c 550-gang_lookup_next/fs/hugetlbfs/inode.c
--- 545-aio-O_SYNC/fs/hugetlbfs/inode.c	2004-02-18 14:57:15.000000000 -0800
+++ 550-gang_lookup_next/fs/hugetlbfs/inode.c	2004-02-20 15:41:06.000000000 -0800
@@ -165,7 +165,7 @@ void truncate_hugepages(struct address_s
 	pagevec_init(&pvec, 0);
 	next = start;
 	while (1) {
-		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+		if (!pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
 			if (next == start)
 				break;
 			next = start;
@@ -176,9 +176,6 @@ void truncate_hugepages(struct address_s
 			struct page *page = pvec.pages[i];
 
 			lock_page(page);
-			if (page->index > next)
-				next = page->index;
-			++next;
 			truncate_huge_page(page);
 			unlock_page(page);
 			hugetlb_put_quota(mapping);
diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/include/linux/pagemap.h 550-gang_lookup_next/include/linux/pagemap.h
--- 545-aio-O_SYNC/include/linux/pagemap.h	2004-02-20 15:40:47.000000000 -0800
+++ 550-gang_lookup_next/include/linux/pagemap.h	2004-02-20 15:41:06.000000000 -0800
@@ -70,7 +70,7 @@ extern struct page * find_trylock_page(s
 extern struct page * find_or_create_page(struct address_space *mapping,
 				unsigned long index, unsigned int gfp_mask);
 extern unsigned int find_get_pages(struct address_space *mapping,
-				pgoff_t start, unsigned int nr_pages,
+				pgoff_t *next, unsigned int nr_pages,
 				struct page **pages);
 
 /*
diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/include/linux/pagevec.h 550-gang_lookup_next/include/linux/pagevec.h
--- 545-aio-O_SYNC/include/linux/pagevec.h	2002-12-09 18:46:25.000000000 -0800
+++ 550-gang_lookup_next/include/linux/pagevec.h	2004-02-20 15:41:06.000000000 -0800
@@ -23,7 +23,7 @@ void __pagevec_lru_add(struct pagevec *p
 void __pagevec_lru_add_active(struct pagevec *pvec);
 void pagevec_strip(struct pagevec *pvec);
 unsigned int pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
-		pgoff_t start, unsigned int nr_pages);
+		pgoff_t *next, unsigned int nr_pages);
 
 static inline void pagevec_init(struct pagevec *pvec, int cold)
 {
diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/mm/filemap.c 550-gang_lookup_next/mm/filemap.c
--- 545-aio-O_SYNC/mm/filemap.c	2004-02-20 15:41:01.000000000 -0800
+++ 550-gang_lookup_next/mm/filemap.c	2004-02-20 15:41:06.000000000 -0800
@@ -571,9 +571,12 @@ EXPORT_SYMBOL(find_or_create_page);
  * The search returns a group of mapping-contiguous pages with ascending
  * indexes.  There may be holes in the indices due to not-present pages.
  *
- * find_get_pages() returns the number of pages which were found.
+ * find_get_pages() returns the number of pages which were found
+ * and also atomically sets the next offset to continue looking up
+ * mapping contiguous pages from (useful when doing a range of
+ * pagevec lookups in chunks of PAGEVEC_SIZE).
  */
-unsigned int find_get_pages(struct address_space *mapping, pgoff_t start,
+unsigned int find_get_pages(struct address_space *mapping, pgoff_t *next,
 			    unsigned int nr_pages, struct page **pages)
 {
 	unsigned int i;
@@ -581,9 +584,12 @@ unsigned int find_get_pages(struct addre
 
 	spin_lock(&mapping->page_lock);
 	ret = radix_tree_gang_lookup(&mapping->page_tree,
-				(void **)pages, start, nr_pages);
+				(void **)pages, *next, nr_pages);
 	for (i = 0; i < ret; i++)
 		page_cache_get(pages[i]);
+	if (ret)
+		*next = pages[ret - 1]->index + 1;
+
 	spin_unlock(&mapping->page_lock);
 	return ret;
 }
diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/mm/swap.c 550-gang_lookup_next/mm/swap.c
--- 545-aio-O_SYNC/mm/swap.c	2004-01-15 10:41:20.000000000 -0800
+++ 550-gang_lookup_next/mm/swap.c	2004-02-20 15:41:06.000000000 -0800
@@ -348,12 +348,15 @@ void pagevec_strip(struct pagevec *pvec)
  * The search returns a group of mapping-contiguous pages with ascending
  * indexes.  There may be holes in the indices due to not-present pages.
  *
- * pagevec_lookup() returns the number of pages which were found.
+ * pagevec_lookup() returns the number of pages which were found
+ * and also atomically sets the next offset to continue looking up
+ * mapping contiguous pages from (useful when doing a range of
+ * pagevec lookups in chunks of PAGEVEC_SIZE).
  */
 unsigned int pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
-		pgoff_t start, unsigned int nr_pages)
+		pgoff_t *next, unsigned int nr_pages)
 {
-	pvec->nr = find_get_pages(mapping, start, nr_pages, pvec->pages);
+	pvec->nr = find_get_pages(mapping, next, nr_pages, pvec->pages);
 	return pagevec_count(pvec);
 }
 
diff -purN -X /home/mbligh/.diff.exclude 545-aio-O_SYNC/mm/truncate.c 550-gang_lookup_next/mm/truncate.c
--- 545-aio-O_SYNC/mm/truncate.c	2003-10-14 15:50:36.000000000 -0700
+++ 550-gang_lookup_next/mm/truncate.c	2004-02-20 15:41:06.000000000 -0800
@@ -122,14 +122,10 @@ void truncate_inode_pages(struct address
 
 	pagevec_init(&pvec, 0);
 	next = start;
-	while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+	while (pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
-			pgoff_t page_index = page->index;
 
-			if (page_index > next)
-				next = page_index;
-			next++;
 			if (TestSetPageLocked(page))
 				continue;
 			if (PageWriteback(page)) {
@@ -155,7 +151,7 @@ void truncate_inode_pages(struct address
 
 	next = start;
 	for ( ; ; ) {
-		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+		if (!pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
 			if (next == start)
 				break;
 			next = start;
@@ -166,9 +162,6 @@ void truncate_inode_pages(struct address
 
 			lock_page(page);
 			wait_on_page_writeback(page);
-			if (page->index > next)
-				next = page->index;
-			next++;
 			truncate_complete_page(mapping, page);
 			unlock_page(page);
 		}
@@ -201,17 +194,13 @@ unsigned long invalidate_mapping_pages(s
 
 	pagevec_init(&pvec, 0);
 	while (next <= end &&
-			pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+			pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 
 			if (TestSetPageLocked(page)) {
-				next++;
 				continue;
 			}
-			if (page->index > next)
-				next = page->index;
-			next++;
 			if (PageDirty(page) || PageWriteback(page))
 				goto unlock;
 			if (page_mapped(page))
@@ -250,14 +239,13 @@ void invalidate_inode_pages2(struct addr
 	int i;
 
 	pagevec_init(&pvec, 0);
-	while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+	while (pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 
 			lock_page(page);
 			if (page->mapping == mapping) {	/* truncate race? */
 				wait_on_page_writeback(page);
-				next = page->index + 1;
 				if (page_mapped(page))
 					clear_page_dirty(page);
 				else