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:44:14.000000000 -0800 @@ -90,6 +90,7 @@ /* Internal MPOL_MF_xxx flags */ #define MPOL_MF_DISCONTIG_OK (1<<20) /* Skip checks for continuous vmas */ #define MPOL_MF_INVERT (1<<21) /* Invert check for nodemask */ +#define MPOL_MF_STATS (1<<22) /* Gather statistics */ /* The number of pages to migrate per call to migrate_pages() */ #define MIGRATE_CHUNK_SIZE 256 @@ -239,11 +240,13 @@ static void migrate_page_add(struct vm_a } } +static void gather_stats(struct page *, void *); + /* 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) + void *private) { pte_t *orig_pte; pte_t *pte; @@ -253,6 +256,7 @@ static int check_pte_range(struct vm_are do { unsigned long pfn; unsigned int nid; + struct page *page; if (!pte_present(*pte)) continue; @@ -261,15 +265,19 @@ 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); + page = pfn_to_page(pfn); + nid = page_to_nid(page); + if (node_isset(nid, *nodes) == !(flags & MPOL_MF_INVERT)) + break; + + if (flags & MPOL_MF_STATS) + gather_stats(page, private); + + else + if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) + migrate_page_add(vma, page, private, flags); + - migrate_page_add(vma, page, pagelist, flags); - } else - break; - } } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(orig_pte, ptl); return addr != end; @@ -278,7 +286,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) + void *private) { pmd_t *pmd; unsigned long next; @@ -289,7 +297,7 @@ static inline int check_pmd_range(struct if (pmd_none_or_clear_bad(pmd)) continue; if (check_pte_range(vma, pmd, addr, next, nodes, - flags, pagelist)) + flags, private)) return -EIO; } while (pmd++, addr = next, addr != end); return 0; @@ -298,7 +306,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) + void *private) { pud_t *pud; unsigned long next; @@ -309,7 +317,7 @@ static inline int check_pud_range(struct if (pud_none_or_clear_bad(pud)) continue; if (check_pmd_range(vma, pud, addr, next, nodes, - flags, pagelist)) + flags, private)) return -EIO; } while (pud++, addr = next, addr != end); return 0; @@ -318,7 +326,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) + void *private) { pgd_t *pgd; unsigned long next; @@ -329,7 +337,7 @@ static inline int check_pgd_range(struct if (pgd_none_or_clear_bad(pgd)) continue; if (check_pud_range(vma, pgd, addr, next, nodes, - flags, pagelist)) + flags, private)) return -EIO; } while (pgd++, addr = next, addr != end); return 0; @@ -356,7 +364,7 @@ static inline int vma_migratable(struct */ 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) + const nodemask_t *nodes, unsigned long flags, void *private) { int err; struct vm_area_struct *first, *vma, *prev; @@ -386,7 +394,7 @@ check_range(struct mm_struct *mm, unsign if (vma->vm_start > start) start = vma->vm_start; err = check_pgd_range(vma, start, endvma, nodes, - flags, pagelist); + flags, private); if (err) { first = ERR_PTR(err); break; @@ -558,8 +566,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, &pagelist); err = PTR_ERR(vma); if (!IS_ERR(vma)) {