[PATCH] Direct Migration V9: Avoid writeback / page_migrate() method
Migrate a page with buffers without requiring writeback
This introduces a new address space operation migratepage() that may be used
by a filesystem to implement its own version of page migration.
A version is provided that migrates buffers attached to pages. Some
filesystems (ext2, ext3, xfs) are modified to utilize this feature.
The swapper address space operation are modified so that a regular
migrate_page() will occur for anonymous pages without writeback (migrate_pages
forces every anonymous page to have a swap entry).
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/mm/rmap.c b/mm/rmap.c
index f4b91d7..df2c41c 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -233,6 +233,7 @@
delete_from_swap_cache(page);
}
+EXPORT_SYMBOL(remove_from_swap);
#endif
/*
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 7b09ac5..db8a3d3 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -27,6 +27,7 @@
.writepage = swap_writepage,
.sync_page = block_sync_page,
.set_page_dirty = __set_page_dirty_nobuffers,
+ .migratepage = migrate_page,
};
static struct backing_dev_info swap_backing_dev_info = {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5e98b86..5a61080 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -615,6 +615,15 @@
}
/*
+ * Non migratable page
+ */
+int fail_migrate_page(struct page *newpage, struct page *page)
+{
+ return -EIO;
+}
+EXPORT_SYMBOL(fail_migrate_page);
+
+/*
* swapout a single page
* page is locked upon entry, unlocked on exit
*/
@@ -659,6 +668,7 @@
retry:
return -EAGAIN;
}
+EXPORT_SYMBOL(swap_page);
/*
* Page migration was first developed in the context of the memory hotplug
@@ -674,7 +684,7 @@
* Remove references for a page and establish the new page with the correct
* basic settings to be able to stop accesses to the page.
*/
-static int migrate_page_remove_references(struct page *newpage,
+int migrate_page_remove_references(struct page *newpage,
struct page *page, int nr_refs)
{
struct address_space *mapping = page_mapping(page);
@@ -749,6 +759,7 @@
return 0;
}
+EXPORT_SYMBOL(migrate_page_remove_references);
/*
* Copy the page to its new location
@@ -788,6 +799,7 @@
if (PageWriteback(newpage))
end_page_writeback(newpage);
}
+EXPORT_SYMBOL(migrate_page_copy);
/*
* Common logic to directly migrate a single page suitable for
@@ -815,6 +827,7 @@
remove_from_swap(newpage);
return 0;
}
+EXPORT_SYMBOL(migrate_page);
/*
* migrate_pages
@@ -914,6 +927,11 @@
if (!mapping)
goto unlock_both;
+ if (mapping->a_ops->migratepage) {
+ rc = mapping->a_ops->migratepage(newpage, page);
+ goto unlock_both;
+ }
+
/*
* Trigger writeout if page is dirty
*/