

This function is setting page->mapping = swapper_space, but isn't actually
adding the page to swapcache.  This triggers soon-to-be-added BUGs in the
radix tree code.

So temporarily add these pages to swapcache for real.

Also, make rw_swap_page_sync() go away if it has no callers.


---

 25-akpm/mm/page_io.c |   28 ++++++++++++++++++++++++----
 1 files changed, 24 insertions(+), 4 deletions(-)

diff -puN mm/page_io.c~rw_swap_page_sync-fix mm/page_io.c
--- 25/mm/page_io.c~rw_swap_page_sync-fix	2004-04-03 03:00:10.555626856 -0800
+++ 25-akpm/mm/page_io.c	2004-04-03 03:00:10.558626400 -0800
@@ -137,9 +137,11 @@ struct address_space_operations swap_aop
 	.set_page_dirty	= __set_page_dirty_nobuffers,
 };
 
+#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_PM_DISK)
+
 /*
  * A scruffy utility function to read or write an arbitrary swap page
- * and wait on the I/O.
+ * and wait on the I/O.  The caller must have a ref on the page.
  */
 int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page)
 {
@@ -151,8 +153,18 @@ int rw_swap_page_sync(int rw, swp_entry_
 	lock_page(page);
 
 	BUG_ON(page->mapping);
-	page->mapping = &swapper_space;
-	page->index = entry.val;
+	ret = add_to_page_cache(page, &swapper_space,
+				entry.val, GFP_NOIO|__GFP_NOFAIL);
+	if (ret) {
+		unlock_page(page);
+		goto out;
+	}
+
+	/*
+	 * get one more reference to make page non-exclusive so
+	 * remove_exclusive_swap_page won't mess with it.
+	 */
+	page_cache_get(page);
 
 	if (rw == READ) {
 		ret = swap_readpage(NULL, page);
@@ -161,8 +173,16 @@ int rw_swap_page_sync(int rw, swp_entry_
 		ret = swap_writepage(page, &swap_wbc);
 		wait_on_page_writeback(page);
 	}
-	page->mapping = NULL;
+
+	lock_page(page);
+	remove_from_page_cache(page);
+	unlock_page(page);
+	page_cache_release(page);
+	page_cache_release(page);	/* For add_to_page_cache() */
+
 	if (ret == 0 && (!PageUptodate(page) || PageError(page)))
 		ret = -EIO;
+out:
 	return ret;
 }
+#endif

_
