mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/4] SwapMig: [resend] CONFIG_MIGRATION fixes
@ 2005-11-18  1:02 Christoph Lameter
  2005-11-18  1:03 ` [PATCH 2/4] SwapMig: add_to_swap() avoid atomic allocations Christoph Lameter
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Christoph Lameter @ 2005-11-18  1:02 UTC (permalink / raw)
  To: akpm; +Cc: lhms-devel, Christoph Lameter, linux-kernel

Move move_to_lru, putback_lru_pages and isolate_lru in section surrounded
by CONFIG_MIGRATION saving some codesize for single processor kernels.

[posted earlier in a different form but somehow missing from 2.6.15-rc1-mm1]

Signed-off-by: Christoph Lameter <clameter@sgi.com>

Index: linux-2.6.15-rc1-mm1/mm/vmscan.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/vmscan.c	2005-11-17 15:17:32.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/vmscan.c	2005-11-17 16:55:49.000000000 -0800
@@ -571,6 +571,40 @@ keep:
 }
 
 #ifdef CONFIG_MIGRATION
+static inline void move_to_lru(struct page *page)
+{
+	list_del(&page->lru);
+	if (PageActive(page)) {
+		/*
+		 * lru_cache_add_active checks that
+		 * the PG_active bit is off.
+		 */
+		ClearPageActive(page);
+		lru_cache_add_active(page);
+	} else {
+		lru_cache_add(page);
+	}
+	put_page(page);
+}
+
+/*
+ * Add isolated pages on the list back to the LRU
+ *
+ * returns the number of pages put back.
+ */
+int putback_lru_pages(struct list_head *l)
+{
+	struct page *page;
+	struct page *page2;
+	int count = 0;
+
+	list_for_each_entry_safe(page, page2, l, lru) {
+		move_to_lru(page);
+		count++;
+	}
+	return count;
+}
+
 /*
  * swapout a single page
  * page is locked upon entry, unlocked on exit
@@ -720,6 +754,48 @@ retry_later:
 
 	return nr_failed + retry;
 }
+
+static void lru_add_drain_per_cpu(void *dummy)
+{
+	lru_add_drain();
+}
+
+/*
+ * Isolate one page from the LRU lists and put it on the
+ * indicated list. Do necessary cache draining if the
+ * page is not on the LRU lists yet.
+ *
+ * Result:
+ *  0 = page not on LRU list
+ *  1 = page removed from LRU list and added to the specified list.
+ * -ENOENT = page is being freed elsewhere.
+ */
+int isolate_lru_page(struct page *page)
+{
+	int rc = 0;
+	struct zone *zone = page_zone(page);
+
+redo:
+	spin_lock_irq(&zone->lru_lock);
+	rc = __isolate_lru_page(page);
+	if (rc == 1) {
+		if (PageActive(page))
+			del_page_from_active_list(zone, page);
+		else
+			del_page_from_inactive_list(zone, page);
+	}
+	spin_unlock_irq(&zone->lru_lock);
+	if (rc == 0) {
+		/*
+		 * Maybe this page is still waiting for a cpu to drain it
+		 * from one of the lru lists?
+		 */
+		on_each_cpu(lru_add_drain_per_cpu, NULL, 0, 1);
+		if (PageLRU(page))
+			goto redo;
+	}
+	return rc;
+}
 #endif
 
 /*
@@ -769,48 +845,6 @@ static int isolate_lru_pages(int nr_to_s
 	return nr_taken;
 }
 
-static void lru_add_drain_per_cpu(void *dummy)
-{
-	lru_add_drain();
-}
-
-/*
- * Isolate one page from the LRU lists and put it on the
- * indicated list. Do necessary cache draining if the
- * page is not on the LRU lists yet.
- *
- * Result:
- *  0 = page not on LRU list
- *  1 = page removed from LRU list and added to the specified list.
- * -ENOENT = page is being freed elsewhere.
- */
-int isolate_lru_page(struct page *page)
-{
-	int rc = 0;
-	struct zone *zone = page_zone(page);
-
-redo:
-	spin_lock_irq(&zone->lru_lock);
-	rc = __isolate_lru_page(page);
-	if (rc == 1) {
-		if (PageActive(page))
-			del_page_from_active_list(zone, page);
-		else
-			del_page_from_inactive_list(zone, page);
-	}
-	spin_unlock_irq(&zone->lru_lock);
-	if (rc == 0) {
-		/*
-		 * Maybe this page is still waiting for a cpu to drain it
-		 * from one of the lru lists?
-		 */
-		on_each_cpu(lru_add_drain_per_cpu, NULL, 0, 1);
-		if (PageLRU(page))
-			goto redo;
-	}
-	return rc;
-}
-
 /*
  * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed
  */
@@ -876,40 +910,6 @@ done:
 	pagevec_release(&pvec);
 }
 
-static inline void move_to_lru(struct page *page)
-{
-	list_del(&page->lru);
-	if (PageActive(page)) {
-		/*
-		 * lru_cache_add_active checks that
-		 * the PG_active bit is off.
-		 */
-		ClearPageActive(page);
-		lru_cache_add_active(page);
-	} else {
-		lru_cache_add(page);
-	}
-	put_page(page);
-}
-
-/*
- * Add isolated pages on the list back to the LRU
- *
- * returns the number of pages put back.
- */
-int putback_lru_pages(struct list_head *l)
-{
-	struct page *page;
-	struct page *page2;
-	int count = 0;
-
-	list_for_each_entry_safe(page, page2, l, lru) {
-		move_to_lru(page);
-		count++;
-	}
-	return count;
-}
-
 /*
  * This moves pages from the active list to the inactive list.
  *
Index: linux-2.6.15-rc1-mm1/include/linux/swap.h
===================================================================
--- linux-2.6.15-rc1-mm1.orig/include/linux/swap.h	2005-11-17 16:55:00.000000000 -0800
+++ linux-2.6.15-rc1-mm1/include/linux/swap.h	2005-11-17 16:55:05.000000000 -0800
@@ -176,10 +176,9 @@ extern int zone_reclaim(struct zone *, g
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
+#ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p);
 extern int putback_lru_pages(struct list_head *l);
-
-#ifdef CONFIG_MIGRATION
 extern int migrate_pages(struct list_head *l, struct list_head *t);
 #endif
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/4] SwapMig: add_to_swap() avoid atomic allocations
  2005-11-18  1:02 [PATCH 1/4] SwapMig: [resend] CONFIG_MIGRATION fixes Christoph Lameter
@ 2005-11-18  1:03 ` Christoph Lameter
  2005-11-18  1:03 ` [PATCH 3/4] SwapMig: Drop unused pages immediately Christoph Lameter
  2005-11-18  1:03 ` [PATCH 4/4] SwapMig: Extend parameters for migrate_pages() Christoph Lameter
  2 siblings, 0 replies; 4+ messages in thread
From: Christoph Lameter @ 2005-11-18  1:03 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, Christoph Lameter, lhms-devel

Add gfp_mask to add_to_swap

add_to_swap does allocations with GFP_ATOMIC in order not to
interfere with swapping. During migration we may have
use add_to_swap extensively which may lead to out of memory
errors.

This patch makes add_to_swap take a parameter that specifies
the gfp mask. The page migration code can then make add_to_swap
use GFP_KERNEL.

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

Index: linux-2.6.15-rc1-mm1/include/linux/swap.h
===================================================================
--- linux-2.6.15-rc1-mm1.orig/include/linux/swap.h	2005-11-17 16:55:05.000000000 -0800
+++ linux-2.6.15-rc1-mm1/include/linux/swap.h	2005-11-17 16:57:30.000000000 -0800
@@ -231,7 +231,7 @@ extern int rw_swap_page_sync(int, swp_en
 extern struct address_space swapper_space;
 #define total_swapcache_pages  swapper_space.nrpages
 extern void show_swap_cache_info(void);
-extern int add_to_swap(struct page *);
+extern int add_to_swap(struct page *, gfp_t);
 extern void __delete_from_swap_cache(struct page *);
 extern void delete_from_swap_cache(struct page *);
 extern int move_to_swap_cache(struct page *, swp_entry_t);
Index: linux-2.6.15-rc1-mm1/mm/swap_state.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/swap_state.c	2005-11-17 15:17:32.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/swap_state.c	2005-11-17 16:57:30.000000000 -0800
@@ -142,7 +142,7 @@ void __delete_from_swap_cache(struct pag
  * Allocate swap space for the page and add the page to the
  * swap cache.  Caller needs to hold the page lock. 
  */
-int add_to_swap(struct page * page)
+int add_to_swap(struct page * page, gfp_t gfp_mask)
 {
 	swp_entry_t entry;
 	int err;
@@ -170,7 +170,7 @@ int add_to_swap(struct page * page)
 		 * Add it to the swap cache and mark it dirty
 		 */
 		err = __add_to_swap_cache(page, entry,
-				GFP_ATOMIC|__GFP_NOMEMALLOC|__GFP_NOWARN);
+				gfp_mask|__GFP_NOMEMALLOC|__GFP_NOWARN);
 
 		switch (err) {
 		case 0:				/* Success */
Index: linux-2.6.15-rc1-mm1/mm/vmscan.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/vmscan.c	2005-11-17 16:55:49.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/vmscan.c	2005-11-17 16:57:30.000000000 -0800
@@ -455,7 +455,7 @@ static int shrink_list(struct list_head 
 		if (PageAnon(page) && !PageSwapCache(page)) {
 			if (!sc->may_swap)
 				goto keep_locked;
-			if (!add_to_swap(page))
+			if (!add_to_swap(page, GFP_ATOMIC))
 				goto activate_locked;
 		}
 #endif /* CONFIG_SWAP */
@@ -726,7 +726,7 @@ redo:
 		}
 
 		if (PageAnon(page) && !PageSwapCache(page)) {
-			if (!add_to_swap(page)) {
+			if (!add_to_swap(page, GFP_KERNEL)) {
 				unlock_page(page);
 				list_move(&page->lru, &failed);
 				nr_failed++;

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/4] SwapMig: Drop unused pages immediately
  2005-11-18  1:02 [PATCH 1/4] SwapMig: [resend] CONFIG_MIGRATION fixes Christoph Lameter
  2005-11-18  1:03 ` [PATCH 2/4] SwapMig: add_to_swap() avoid atomic allocations Christoph Lameter
@ 2005-11-18  1:03 ` Christoph Lameter
  2005-11-18  1:03 ` [PATCH 4/4] SwapMig: Extend parameters for migrate_pages() Christoph Lameter
  2 siblings, 0 replies; 4+ messages in thread
From: Christoph Lameter @ 2005-11-18  1:03 UTC (permalink / raw)
  To: akpm; +Cc: lhms-devel, linux-kernel, Christoph Lameter

Drop unused pages immediately

If a page is encountered that is only referenced by the migration code
then there is no reason to swap or migrate the page. Release
the page by calling move_to_lru().

Signed-off-by: Christoph Lameter <clameter@sgi.com>

Index: linux-2.6.15-rc1-mm1/mm/vmscan.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/vmscan.c	2005-11-17 15:59:07.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/vmscan.c	2005-11-17 16:05:18.000000000 -0800
@@ -700,6 +700,11 @@ redo:
 	list_for_each_entry_safe(page, page2, l, lru) {
 		cond_resched();
 
+		if (page_count(page) == 1) {
+			/* page was freed from under us. So we are done. */
+			move_to_lru(page);
+			continue;
+		}
 		/*
 		 * Skip locked pages during the first two passes to give the
 		 * functions holding the lock time to release the page. Later we

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 4/4] SwapMig: Extend parameters for migrate_pages()
  2005-11-18  1:02 [PATCH 1/4] SwapMig: [resend] CONFIG_MIGRATION fixes Christoph Lameter
  2005-11-18  1:03 ` [PATCH 2/4] SwapMig: add_to_swap() avoid atomic allocations Christoph Lameter
  2005-11-18  1:03 ` [PATCH 3/4] SwapMig: Drop unused pages immediately Christoph Lameter
@ 2005-11-18  1:03 ` Christoph Lameter
  2 siblings, 0 replies; 4+ messages in thread
From: Christoph Lameter @ 2005-11-18  1:03 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, Christoph Lameter, lhms-devel

Extend the parameters of migrate_pages() to allow the caller control
over the fate of successfully migrated or impossible to migrate pages.

Swap migration and direct migration will have the same interface after this
patch so that patches can be independently applied to the policy layer
and the core migration code.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

Index: linux-2.6.15-rc1-mm1/include/linux/swap.h
===================================================================
--- linux-2.6.15-rc1-mm1.orig/include/linux/swap.h	2005-11-17 16:57:30.000000000 -0800
+++ linux-2.6.15-rc1-mm1/include/linux/swap.h	2005-11-17 16:58:18.000000000 -0800
@@ -179,7 +179,8 @@ extern int vm_swappiness;
 #ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p);
 extern int putback_lru_pages(struct list_head *l);
-extern int migrate_pages(struct list_head *l, struct list_head *t);
+extern int migrate_pages(struct list_head *l, struct list_head *t,
+		struct list_head *moved, struct list_head *failed);
 #endif
 
 #ifdef CONFIG_MMU
Index: linux-2.6.15-rc1-mm1/mm/vmscan.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/vmscan.c	2005-11-17 16:57:35.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/vmscan.c	2005-11-17 16:57:46.000000000 -0800
@@ -681,10 +681,10 @@ retry:
  * list. The direct migration patchset
  * extends this function to avoid the use of swap.
  */
-int migrate_pages(struct list_head *l, struct list_head *t)
+int migrate_pages(struct list_head *from, struct list_head *to,
+		  struct list_head *moved, struct list_head *failed)
 {
 	int retry;
-	LIST_HEAD(failed);
 	int nr_failed = 0;
 	int pass = 0;
 	struct page *page;
@@ -697,12 +697,12 @@ int migrate_pages(struct list_head *l, s
 redo:
 	retry = 0;
 
-	list_for_each_entry_safe(page, page2, l, lru) {
+	list_for_each_entry_safe(page, page2, from, lru) {
 		cond_resched();
 
 		if (page_count(page) == 1) {
 			/* page was freed from under us. So we are done. */
-			move_to_lru(page);
+			list_move(&page->lru, moved);
 			continue;
 		}
 		/*
@@ -733,7 +733,7 @@ redo:
 		if (PageAnon(page) && !PageSwapCache(page)) {
 			if (!add_to_swap(page, GFP_KERNEL)) {
 				unlock_page(page);
-				list_move(&page->lru, &failed);
+				list_move(&page->lru, failed);
 				nr_failed++;
 				continue;
 			}
@@ -743,8 +743,10 @@ redo:
 		 * Page is properly locked and writeback is complete.
 		 * Try to migrate the page.
 		 */
-		if (!swap_page(page))
+		if (!swap_page(page)) {
+			list_move(&page->lru, moved);
 			continue;
+		}
 retry_later:
 		retry++;
 	}
@@ -754,9 +756,6 @@ retry_later:
 	if (!swapwrite)
 		current->flags &= ~PF_SWAPWRITE;
 
-	if (!list_empty(&failed))
-		list_splice(&failed, l);
-
 	return nr_failed + retry;
 }
 
Index: linux-2.6.15-rc1-mm1/mm/mempolicy.c
===================================================================
--- linux-2.6.15-rc1-mm1.orig/mm/mempolicy.c	2005-11-17 16:54:24.000000000 -0800
+++ linux-2.6.15-rc1-mm1/mm/mempolicy.c	2005-11-17 16:57:46.000000000 -0800
@@ -438,6 +438,19 @@ static int contextualize_policy(int mode
 	return mpol_check_policy(mode, nodes);
 }
 
+static int swap_pages(struct list_head *pagelist)
+{
+	LIST_HEAD(moved);
+	LIST_HEAD(failed);
+	int n;
+
+	n = migrate_pages(pagelist, NULL, &moved, &failed);
+	putback_lru_pages(&failed);
+	putback_lru_pages(&moved);
+
+	return n;
+}
+
 long do_mbind(unsigned long start, unsigned long len,
 		unsigned long mode, nodemask_t *nmask, unsigned long flags)
 {
@@ -490,10 +503,13 @@ long do_mbind(unsigned long start, unsig
 	      (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ? &pagelist : NULL);
 	err = PTR_ERR(vma);
 	if (!IS_ERR(vma)) {
+		int nr_failed = 0;
+
 		err = mbind_range(vma, start, end, new);
 		if (!list_empty(&pagelist))
-			migrate_pages(&pagelist, NULL);
-		if (!err && !list_empty(&pagelist) && (flags & MPOL_MF_STRICT))
+			nr_failed = swap_pages(&pagelist);
+
+		if (!err && nr_failed && (flags & MPOL_MF_STRICT))
 			err = -EIO;
 	}
 	if (!list_empty(&pagelist))
@@ -644,11 +660,12 @@ int do_migrate_pages(struct mm_struct *m
 	down_read(&mm->mmap_sem);
 	check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes,
 			flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+
 	if (!list_empty(&pagelist)) {
-		migrate_pages(&pagelist, NULL);
-		if (!list_empty(&pagelist))
-			count = putback_lru_pages(&pagelist);
+		count = swap_pages(&pagelist);
+		putback_lru_pages(&pagelist);
 	}
+
 	up_read(&mm->mmap_sem);
 	return count;
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-11-18  1:03 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-11-18  1:02 [PATCH 1/4] SwapMig: [resend] CONFIG_MIGRATION fixes Christoph Lameter
2005-11-18  1:03 ` [PATCH 2/4] SwapMig: add_to_swap() avoid atomic allocations Christoph Lameter
2005-11-18  1:03 ` [PATCH 3/4] SwapMig: Drop unused pages immediately Christoph Lameter
2005-11-18  1:03 ` [PATCH 4/4] SwapMig: Extend parameters for migrate_pages() Christoph Lameter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome