

__remove_exlusive_swap_page() can detach a page from the swap-cache
when page_count(page) - page_mapcount(page) == 2 while the original
remove_exlusive_swap_page() can do this only when a target page
isn't mapped to any spaces and isn't shared.

__remove_exlusive_swap_page() is called not to waste swap space
right after memory migration is done.

Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 memhotplug-dave/include/linux/swap.h |   13 +++++++++++--
 memhotplug-dave/mm/swapfile.c        |    8 +++++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff -puN include/linux/swap.h~AA-PM-16-remove_exclusive_swap_page include/linux/swap.h
--- memhotplug/include/linux/swap.h~AA-PM-16-remove_exclusive_swap_page	2005-03-28 16:38:24.000000000 -0800
+++ memhotplug-dave/include/linux/swap.h	2005-03-28 16:38:24.000000000 -0800
@@ -228,7 +228,11 @@ extern void free_swap_and_cache(swp_entr
 extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t);
 extern struct swap_info_struct *get_swap_info_struct(unsigned);
 extern int can_share_swap_page(struct page *);
-extern int remove_exclusive_swap_page(struct page *);
+extern int __remove_exclusive_swap_page(struct page *, int);
+static inline int remove_exclusive_swap_page(struct page *p)
+{
+	return __remove_exclusive_swap_page(p, 0);
+}
 struct backing_dev_info;
 
 extern struct swap_list_t swap_list;
@@ -282,11 +286,16 @@ static inline void put_swap_token(struct
 #define delete_from_swap_cache(p)		/*NOTHING*/
 #define swap_token_default_timeout		0
 
-static inline int remove_exclusive_swap_page(struct page *p)
+static inline int __remove_exclusive_swap_page(struct page *p, int force)
 {
 	return 0;
 }
 
+static inline int remove_exclusive_swap_page(struct page *p)
+{
+	return __remove_exclusive_swap_page(p, 0);
+}
+
 static inline swp_entry_t get_swap_page(void)
 {
 	swp_entry_t entry;
diff -puN mm/swapfile.c~AA-PM-16-remove_exclusive_swap_page mm/swapfile.c
--- memhotplug/mm/swapfile.c~AA-PM-16-remove_exclusive_swap_page	2005-03-28 16:38:24.000000000 -0800
+++ memhotplug-dave/mm/swapfile.c	2005-03-28 16:38:24.000000000 -0800
@@ -337,11 +337,12 @@ int can_share_swap_page(struct page *pag
  * Work out if there are any other processes sharing this
  * swap cache page. Free it if you can. Return success.
  */
-int remove_exclusive_swap_page(struct page *page)
+int __remove_exclusive_swap_page(struct page *page, int force)
 {
 	int retval;
 	struct swap_info_struct * p;
 	swp_entry_t entry;
+	int mapcount = force ? page_mapcount(page) : 0;
 
 	BUG_ON(PagePrivate(page));
 	BUG_ON(!PageLocked(page));
@@ -350,7 +351,7 @@ int remove_exclusive_swap_page(struct pa
 		return 0;
 	if (PageWriteback(page))
 		return 0;
-	if (page_count(page) != 2) /* 2: us + cache */
+	if (page_count(page) - mapcount != 2) /* 2: us + cache */
 		return 0;
 
 	entry.val = page->private;
@@ -363,7 +364,8 @@ int remove_exclusive_swap_page(struct pa
 	if (p->swap_map[swp_offset(entry)] == 1) {
 		/* Recheck the page count with the swapcache lock held.. */
 		write_lock_irq(&swapper_space.tree_lock);
-		if ((page_count(page) == 2) && !PageWriteback(page)) {
+		mapcount = force ? page_mapcount(page) : 0;
+		if ((page_count(page) - mapcount == 2) && !PageWriteback(page)) {
 			__delete_from_swap_cache(page);
 			SetPageDirty(page);
 			retval = 1;
_
