Shared Policy Infrastructure - fix migration of private mappings This patch is in preparation for subsequent patch to add shared policy {get|set}_policy ops to generic files. At that point, we'll have "memory objects" that can be mapped shared in some tasks and have shared policy applied, but mapped private in other tasks. Unlikely, perhaps, be we need to handle it in some fashion. Now, if we installed a vma policy on the private mapping, it will be ignored for cache pages. If we specified MPOL_MF_MOVE_ALL on the vma range, we don't want the private mapping's vma policy to affect the cache pages--especially when the file has a shared policy. Rather, we want only to migrate any private, anon copies that the task has "COWed". This will preserve existing behavior for private mappings. Define a new internal flag--MPOL_MF_MOVE_ANON_ONLY--that we set in check_range() for private mappings of files with shared policy. Then, migrate_page_add() will skip cache [non-anon] pages when this flag is set. May also be able to use this flag to force unmapping of anon pages that may be shared with relatives during automigrate on internode task migration--e.g., by using: MPOL_MF_MOVE_ALL|MPOL_MF_MOVE_ANON_ONLY But, that's the subject of a different patch series. Signed-off-by: Lee Schermerhorn <lee.schermerhorn@xxxxxx> mm/mempolicy.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) Index: linux-2.6.36-mmotm-101103-1217/mm/mempolicy.c =================================================================== --- linux-2.6.36-mmotm-101103-1217.orig/mm/mempolicy.c +++ linux-2.6.36-mmotm-101103-1217/mm/mempolicy.c @@ -101,6 +101,7 @@ #define MPOL_MF_DISCONTIG_OK (MPOL_MF_INTERNAL << 0) /* Skip checks for continuous vmas */ #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1) /* Invert check for nodemask */ #define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2) /* Gather statistics */ +#define MPOL_MF_MOVE_ANON_ONLY (MPOL_MF_INTERNAL << 3) static struct kmem_cache *policy_cache; static struct kmem_cache *sp_cache; @@ -609,13 +610,24 @@ check_range(struct mm_struct *mm, unsign ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) && vma_migratable(vma)))) { unsigned long endvma = vma->vm_end; + unsigned long anononly = 0; if (endvma > end) endvma = end; if (vma->vm_start > start) start = vma->vm_start; + + /* + * Non-SHARED file mapping with shared policy installed: + * migrate only COWed anon pages as shared pages follow + * the shared policy. + */ + if (vma->vm_file && !(vma->vm_flags & VM_SHARED) && + vma->vm_file->f_mapping->spolicy) + anononly = MPOL_MF_MOVE_ANON_ONLY; + err = check_pgd_range(vma, start, endvma, nodes, - flags, private); + flags|anononly, private); if (err) { first = ERR_PTR(err); break; @@ -977,9 +989,11 @@ static void migrate_page_add(struct page unsigned long flags) { /* - * Avoid migrating a page that is shared with others. + * Avoid migrating a file backed page in a private mapping or + * a page that is shared with others. */ - if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { + if ((!(flags & MPOL_MF_MOVE_ANON_ONLY) || PageAnon(page)) && + ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1)) { if (!isolate_lru_page(page)) { list_add_tail(&page->lru, pagelist); inc_zone_page_state(page, NR_ISOLATED_ANON + -- To unsubscribe from this list: send the line "unsubscribe linux-numa" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html