Index: linux-2.6/include/linux/mempolicy.h =================================================================== --- linux-2.6.orig/include/linux/mempolicy.h 2007-10-26 15:19:18.000000000 -0700 +++ linux-2.6/include/linux/mempolicy.h 2007-10-26 15:28:11.000000000 -0700 @@ -134,13 +134,13 @@ struct shared_policy { }; void mpol_shared_policy_init(struct shared_policy *info, int policy, - nodemask_t *nodes); + nodemask_t *nodes); int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, struct mempolicy *new); void mpol_free_shared_policy(struct shared_policy *p); struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp, - unsigned long idx); + unsigned long idx, int *refs); extern void numa_default_policy(void); extern void numa_policy_init(void); @@ -151,7 +151,8 @@ extern void mpol_fix_fork_child_flag(str extern struct mempolicy default_policy; extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags); + unsigned long addr, gfp_t gfp_flags, + struct mempolicy **mpol, int *refs); extern unsigned slab_node(struct mempolicy *policy); extern enum zone_type policy_zone; @@ -239,7 +240,7 @@ static inline void mpol_fix_fork_child_f } static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags) + unsigned long addr, gfp_t gfp_flags, int *refs) { return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags); } Index: linux-2.6/include/linux/mm.h =================================================================== --- linux-2.6.orig/include/linux/mm.h 2007-10-26 15:19:18.000000000 -0700 +++ linux-2.6/include/linux/mm.h 2007-10-26 15:23:02.000000000 -0700 @@ -173,7 +173,7 @@ struct vm_operations_struct { #ifdef CONFIG_NUMA int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new); struct mempolicy *(*get_policy)(struct vm_area_struct *vma, - unsigned long addr); + unsigned long addr, int *refs); int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from, const nodemask_t *to, unsigned long flags); #endif Index: linux-2.6/mm/mempolicy.c =================================================================== --- linux-2.6.orig/mm/mempolicy.c 2007-10-26 15:19:18.000000000 -0700 +++ linux-2.6/mm/mempolicy.c 2007-10-26 15:26:37.000000000 -0700 @@ -531,6 +531,7 @@ static long do_get_mempolicy(int *policy struct mm_struct *mm = current->mm; struct vm_area_struct *vma = NULL; struct mempolicy *pol = current->mempolicy; + int refs = 0; cpuset_update_task_memory_state(); if (flags & @@ -553,7 +554,7 @@ static long do_get_mempolicy(int *policy return -EFAULT; } if (vma->vm_ops && vma->vm_ops->get_policy) - pol = vma->vm_ops->get_policy(vma, addr); + pol = vma->vm_ops->get_policy(vma, addr, &refs); else pol = vma->vm_policy; } else if (addr) @@ -587,7 +588,9 @@ static long do_get_mempolicy(int *policy if (nmask) get_zonemask(pol, nmask); - out: +out: + if (refs) + mpol_free(pol); if (vma) up_read(¤t->mm->mmap_sem); return err; @@ -1097,13 +1100,13 @@ asmlinkage long compat_sys_mbind(compat_ /* Return effective policy for a VMA */ static struct mempolicy * get_vma_policy(struct task_struct *task, - struct vm_area_struct *vma, unsigned long addr) + struct vm_area_struct *vma, unsigned long addr, int *refs) { struct mempolicy *pol = task->mempolicy; if (vma) { if (vma->vm_ops && vma->vm_ops->get_policy) - pol = vma->vm_ops->get_policy(vma, addr); + pol = vma->vm_ops->get_policy(vma, addr, refs); else if (vma->vm_policy && vma->vm_policy->policy != MPOL_DEFAULT) pol = vma->vm_policy; @@ -1227,17 +1230,16 @@ static inline unsigned interleave_nid(st #ifdef CONFIG_HUGETLBFS /* Return a zonelist suitable for a huge page allocation. */ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, - gfp_t gfp_flags) + gfp_t gfp_flags, struct mempolicy **mpol, int *refs) { - struct mempolicy *pol = get_vma_policy(current, vma, addr); - - if (pol->policy == MPOL_INTERLEAVE) { + *mpol = get_vma_policy(current, vma, addr, refs); + if ((*mpol)->policy == MPOL_INTERLEAVE) { unsigned nid; - nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); + nid = interleave_nid(*mpol, vma, addr, HPAGE_SHIFT); return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags); } - return zonelist_policy(GFP_HIGHUSER, pol); + return zonelist_policy(GFP_HIGHUSER, *mpol); } #endif @@ -1281,7 +1283,9 @@ static struct page *alloc_page_interleav struct page * alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) { - struct mempolicy *pol = get_vma_policy(current, vma, addr); + int refs = 0; + struct mempolicy *pol = get_vma_policy(current, vma, addr, &refs); + struct page *page; cpuset_update_task_memory_state(); @@ -1289,9 +1293,12 @@ alloc_page_vma(gfp_t gfp, struct vm_area unsigned nid; nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); - return alloc_page_interleave(gfp, 0, nid); - } - return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); + page = alloc_page_interleave(gfp, 0, nid); + } else + page = __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); + if (refs) + mpol_free(pol); + return page; } /** @@ -1464,7 +1471,8 @@ static void sp_insert(struct shared_poli /* Find shared policy intersecting idx */ struct mempolicy * -mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) +mpol_shared_policy_lookup(struct shared_policy *sp, + unsigned long idx, int *refs) { struct mempolicy *pol = NULL; struct sp_node *sn; @@ -1476,6 +1484,7 @@ mpol_shared_policy_lookup(struct shared_ if (sn) { mpol_get(sn->policy); pol = sn->policy; + (*refs)++; } spin_unlock(&sp->lock); return pol; @@ -1891,6 +1900,8 @@ int show_numa_map(struct seq_file *m, vo struct file *file = vma->vm_file; struct mm_struct *mm = vma->vm_mm; int n; + int refs = 0; + struct mempolicy *mpol; char buffer[50]; if (!mm) @@ -1900,8 +1911,10 @@ int show_numa_map(struct seq_file *m, vo if (!md) return 0; - mpol_to_str(buffer, sizeof(buffer), - get_vma_policy(priv->task, vma, vma->vm_start)); + mpol = get_vma_policy(priv->task, vma, vma->vm_start, &refs); + mpol_to_str(buffer, sizeof(buffer), mpol); + if (refs) + mpol_free(mpol); seq_printf(m, "%08lx %s", vma->vm_start, buffer); Index: linux-2.6/ipc/shm.c =================================================================== --- linux-2.6.orig/ipc/shm.c 2007-10-26 15:19:18.000000000 -0700 +++ linux-2.6/ipc/shm.c 2007-10-26 15:32:37.000000000 -0700 @@ -279,14 +279,14 @@ static int shm_set_policy(struct vm_area } static struct mempolicy *shm_get_policy(struct vm_area_struct *vma, - unsigned long addr) + unsigned long addr, int *refs) { struct file *file = vma->vm_file; struct shm_file_data *sfd = shm_file_data(file); struct mempolicy *pol = NULL; if (sfd->vm_ops->get_policy) - pol = sfd->vm_ops->get_policy(vma, addr); + pol = sfd->vm_ops->get_policy(vma, addr, refs; else if (vma->vm_policy) pol = vma->vm_policy; else