Each filesystem can define its own page-migrating method. If a filesystem has the method, the method is invoked instead of generic page-migrating function. Each filesystem have to move its own data when migrating a page because private member of struct page may point filesystem specific data or some cluster filesystems might increment the count of the page to pin it for its performance or somthing else. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen --- memhotplug-dave/include/linux/fs.h | 1 + memhotplug-dave/include/linux/mmigrate.h | 9 +++++++++ memhotplug-dave/mm/mmigrate.c | 15 ++++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff -puN include/linux/fs.h~AA-PM-13.1-migrate_page-operation include/linux/fs.h --- memhotplug/include/linux/fs.h~AA-PM-13.1-migrate_page-operation 2005-07-28 13:50:44.000000000 -0700 +++ memhotplug-dave/include/linux/fs.h 2005-07-28 13:50:44.000000000 -0700 @@ -333,6 +333,7 @@ struct address_space_operations { loff_t offset, unsigned long nr_segs); struct page* (*get_xip_page)(struct address_space *, sector_t, int); + int (*migrate_page)(struct page *, struct page *); }; struct backing_dev_info; diff -puN include/linux/mmigrate.h~AA-PM-13.1-migrate_page-operation include/linux/mmigrate.h --- memhotplug/include/linux/mmigrate.h~AA-PM-13.1-migrate_page-operation 2005-07-28 13:50:44.000000000 -0700 +++ memhotplug-dave/include/linux/mmigrate.h 2005-07-28 13:50:44.000000000 -0700 @@ -5,9 +5,18 @@ #include +#ifdef CONFIG_MEMORY_MIGRATE +extern int generic_migrate_page(struct page *, struct page *, + int (*)(struct page *, struct page *)); +extern int migrate_page_common(struct page *, struct page *); +extern int page_migratable(struct page *, struct page *, int); extern struct page * migrate_onepage(struct page *); extern int try_to_migrate_pages(struct list_head *); +#else +#define generic_migrate_page(p1, p2, fn) (-ENOSYS) +#endif + #ifdef ARCH_HAS_PAGEMIGRATION extern void arch_migrate_page(struct page *, struct page *); #else diff -puN mm/mmigrate.c~AA-PM-13.1-migrate_page-operation mm/mmigrate.c --- memhotplug/mm/mmigrate.c~AA-PM-13.1-migrate_page-operation 2005-07-28 13:50:44.000000000 -0700 +++ memhotplug-dave/mm/mmigrate.c 2005-07-28 13:50:44.000000000 -0700 @@ -104,7 +104,7 @@ replace_pages(struct page *page, struct /* * Check whether the page can be migrated or not. */ -static inline int +int page_migratable(struct page *page, struct page *newpage, int freeable_page_count) { @@ -234,8 +234,9 @@ out: * - Lock for the page must be held when invoked. * - The page must be attached to an address_space. */ -static int -generic_migrate_page(struct page *page, struct page *newpage) +int +generic_migrate_page(struct page *page, struct page *newpage, + int (*migrate_fn)(struct page *, struct page *)) { int ret; @@ -276,7 +277,7 @@ generic_migrate_page(struct page *page, } /* Wait for all operations against the page to finish. */ - ret = migrate_page_common(page, newpage); + ret = migrate_fn(page, newpage); switch (ret) { default: /* The page is busy. Try it later. */ @@ -377,7 +378,10 @@ migrate_onepage(struct page *page) return ERR_PTR(-ENOMEM); } - ret = generic_migrate_page(page, newpage); + if (mapping->a_ops->migrate_page) + ret = mapping->a_ops->migrate_page(page, newpage); + else + ret = generic_migrate_page(page, newpage, migrate_page_common); if (ret) { BUG_ON(page_count(newpage) != 1); page_cache_release(newpage); @@ -396,6 +400,7 @@ need_writeback(struct page *page) /* * Start writeback I/O if it's a dirty page with buffers + * and it doesn't have migrate_page method. */ static inline void page_start_writeback(struct page *page) { _