[PATCH/RFC 4/5] numa - migration cache - use for lazy migration

Lee Schermerhorn <[email protected]> Thu, 11 Nov 2010 15:22:48 -0500
Newsgroups org.kernel.vger.linux-numa
Message-ID <[email protected]>
Migration Cache  4/5 - use migration cache for lazy migration

Separate migration cache patch for migrate_pages_unmap_only().
That function is only present when the MPOL_MF_LAZY feature of
the "Migrate-on-Fault" patch series is present.

Call __add_to_swap() with the 'migration' argument set to 1
to select the migration cache--if it's configured.  Add removal
from mig cache to error path if try_to_unmap() fails.  This
call is a no-op if any of the mappings to the page were successfully
unmapped because the migration cache entry will have a non-zero
ref count.  Calling migration_remove_reference() with a decrement
count of '0' will only remove the entry if it already has zero
refs--i.e., no ptes reference it.

Note that here is a case where the migration cache is visible
outside of the swap infrastructure.

Added a check for migration cache() entry to migration_remove_reference()
to handle the case where a page is already in the real swap cache, but
try_to_unmap() fails when called from migrate_pages_unmap_only().  We
don't want to pass a real swap entry further down into the mig cache.

Signed-off-by:  Lee Schermerhorn <[email protected]>

 mm/migrate.c |   17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

Index: linux-2.6.36-mmotm-101103-1217/mm/migrate.c
===================================================================
--- linux-2.6.36-mmotm-101103-1217.orig/mm/migrate.c
+++ linux-2.6.36-mmotm-101103-1217/mm/migrate.c
@@ -952,7 +952,17 @@ int migrate_pages_unmap_only(struct list
 			goto unlock_page;
 
 		if (PageAnon(page)) {
-			if (!PageSwapCache(page) && !add_to_swap(page)) {
+			if (PageSwapCache(page)) {
+				/*
+				 * add an extra ref while we hold the page
+				 * lock so that do_swap_page() can't rip the
+				 * entry out from under us.
+				 */
+				if (migration_add_reference_page(page)) {
+					nr_failed++;
+					goto unlock_page;
+				}
+			} else if (!__add_to_swap(page, 1)) {
 				nr_failed++;
 				goto unlock_page;
 			}
@@ -965,6 +975,11 @@ int migrate_pages_unmap_only(struct list
 
 		ret = try_to_unmap(page,
 	             TTU_MIGRATE_DEFERRED|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
+		/*
+		 * Remove extra ref.  This will free the migration cache
+		 * entry if try_to_unmap() failed to replace any ptes.
+		 */
+		migration_remove_reference_page(page);
 		if (ret != SWAP_SUCCESS || page_mapped(page)) {
 			nr_failed++;
 			goto unlock_page;