Index: linux-2.6.14-mm1/mm/mempolicy.c =================================================================== --- linux-2.6.14-mm1.orig/mm/mempolicy.c 2005-11-08 12:05:48.000000000 -0800 +++ linux-2.6.14-mm1/mm/mempolicy.c 2005-11-08 12:29:11.000000000 -0800 @@ -238,12 +238,20 @@ static void migrate_page_add(struct vm_a WARN_ON(rc == 0); } } + nid = pfn_to_nid(pfn); + if (!node_isset(nid, *nodes) == !(flags & MPOL_MF_INVERT)) { + if (pagelist) { + struct page *page = pfn_to_page(pfn); + + migrate_page_add(vma, page, pagelist, flags); + } else + break; + } /* Ensure all existing pages follow the policy. */ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, unsigned long end, - const nodemask_t *nodes, unsigned long flags, - struct list_head *pagelist) + int (*func)(struct page *, void *), void *private) { pte_t *orig_pte; pte_t *pte; @@ -261,15 +269,8 @@ static int check_pte_range(struct vm_are print_bad_pte(vma, *pte, addr); continue; } - nid = pfn_to_nid(pfn); - if (!node_isset(nid, *nodes) == !(flags & MPOL_MF_INVERT)) { - if (pagelist) { - struct page *page = pfn_to_page(pfn); - - migrate_page_add(vma, page, pagelist, flags); - } else - break; - } + if (func(pfn_to_page(pfn), private)) + break; } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(orig_pte, ptl); return addr != end; @@ -277,8 +278,7 @@ static int check_pte_range(struct vm_are static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, unsigned long addr, unsigned long end, - const nodemask_t *nodes, unsigned long flags, - struct list_head *pagelist) + int (*func)(struct page *, void *), void *private) { pmd_t *pmd; unsigned long next; @@ -288,8 +288,7 @@ static inline int check_pmd_range(struct next = pmd_addr_end(addr, end); if (pmd_none_or_clear_bad(pmd)) continue; - if (check_pte_range(vma, pmd, addr, next, nodes, - flags, pagelist)) + if (check_pte_range(vma, pmd, addr, next, func, private)) return -EIO; } while (pmd++, addr = next, addr != end); return 0; @@ -297,8 +296,7 @@ static inline int check_pmd_range(struct static inline int check_pud_range(struct vm_area_struct *vma, pgd_t *pgd, unsigned long addr, unsigned long end, - const nodemask_t *nodes, unsigned long flags, - struct list_head *pagelist) + int (*func)(struct page *, void *), void *private) { pud_t *pud; unsigned long next; @@ -308,8 +306,7 @@ static inline int check_pud_range(struct next = pud_addr_end(addr, end); if (pud_none_or_clear_bad(pud)) continue; - if (check_pmd_range(vma, pud, addr, next, nodes, - flags, pagelist)) + if (check_pmd_range(vma, pud, addr, next, func, private)) return -EIO; } while (pud++, addr = next, addr != end); return 0; @@ -317,8 +314,7 @@ static inline int check_pud_range(struct static inline int check_pgd_range(struct vm_area_struct *vma, unsigned long addr, unsigned long end, - const nodemask_t *nodes, unsigned long flags, - struct list_head *pagelist) + int (*func)(struct page *, void *), void *private) { pgd_t *pgd; unsigned long next; @@ -328,8 +324,7 @@ static inline int check_pgd_range(struct next = pgd_addr_end(addr, end); if (pgd_none_or_clear_bad(pgd)) continue; - if (check_pud_range(vma, pgd, addr, next, nodes, - flags, pagelist)) + if (check_pud_range(vma, pgd, addr, next, func, private)) return -EIO; } while (pgd++, addr = next, addr != end); return 0; @@ -350,13 +345,12 @@ static inline int vma_migratable(struct } /* - * Check if all pages in a range are on a set of nodes. - * If pagelist != NULL then isolate pages from the LRU and - * put them on the pagelist. + * Run a check function against all pages in a range. */ static struct vm_area_struct * check_range(struct mm_struct *mm, unsigned long start, unsigned long end, - const nodemask_t *nodes, unsigned long flags, struct list_head *pagelist) + unsigned int flags, + int (*func)(struct page *, void *), void *private) { int err; struct vm_area_struct *first, *vma, *prev; @@ -385,8 +379,7 @@ check_range(struct mm_struct *mm, unsign endvma = end; if (vma->vm_start > start) start = vma->vm_start; - err = check_pgd_range(vma, start, endvma, nodes, - flags, pagelist); + err = check_pgd_range(vma, start, endvma, func, private); if (err) { first = ERR_PTR(err); break; @@ -510,6 +503,13 @@ out: return nr_pages; } +int mbind_check_page(struct page *page, void *private) +{ + nodemask_t *nodes = private; + + return !node_isset(page_to_nid(page), *nodes); +} + long do_mbind(unsigned long start, unsigned long len, unsigned long mode, nodemask_t *nmask, unsigned long flags) { @@ -558,8 +558,7 @@ long do_mbind(unsigned long start, unsig mode,nodes_addr(nodes)[0]); down_write(&mm->mmap_sem); - vma = check_range(mm, start, end, nmask, flags, - (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ? &pagelist : NULL); + vma = check_range(mm, start, end, nmask, flags, mbind_check_page, nodes); err = PTR_ERR(vma); if (!IS_ERR(vma)) {