From 8af5e2eb3cc4450ffba9496c875beac41bf4f4f8 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 20 Feb 2007 13:57:49 -0800 Subject: [PATCH] fix mempolicy's check on a system with memory-less-node bind_zonelist() can create zero-length zonelist if there is a memory-less-node. This patch checks the length of zonelist. If length is 0, returns -EINVAL. tested on ia64/NUMA with memory-less-node. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Andi Kleen Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mempolicy.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'mm/mempolicy.c') diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 259a706bd83e..cf2a5381030a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -144,7 +144,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) max++; /* space for zlcache_ptr (see mmzone.h) */ zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL); if (!zl) - return NULL; + return ERR_PTR(-ENOMEM); zl->zlcache_ptr = NULL; num = 0; /* First put in the highest zones from all nodes, then all the next @@ -162,6 +162,10 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) break; k--; } + if (num == 0) { + kfree(zl); + return ERR_PTR(-EINVAL); + } zl->zones[num] = NULL; return zl; } @@ -193,9 +197,10 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) break; case MPOL_BIND: policy->v.zonelist = bind_zonelist(nodes); - if (policy->v.zonelist == NULL) { + if (IS_ERR(policy->v.zonelist)) { + void *error_code = policy->v.zonelist; kmem_cache_free(policy_cache, policy); - return ERR_PTR(-ENOMEM); + return error_code; } break; } @@ -1667,7 +1672,7 @@ void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask) * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. */ - if (zonelist) { + if (!IS_ERR(zonelist)) { /* Good - got mem - substitute new zonelist */ kfree(pol->v.zonelist); pol->v.zonelist = zonelist; -- cgit v1.2.3 From 0dc952dc3e6d96d554a19fa7bee3f3b1d55e3cff Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Mon, 5 Mar 2007 00:30:33 -0800 Subject: [PATCH] Page migration: Fix vma flag checking Currently we do not check for vma flags if sys_move_pages is called to move individual pages. If sys_migrate_pages is called to move pages then we check for vm_flags that indicate a non migratable vma but that still includes VM_LOCKED and we can migrate mlocked pages. Extract the vma_migratable check from mm/mempolicy.c, fix it and put it into migrate.h so that is can be used from both locations. Problem was spotted by Lee Schermerhorn Signed-off-by: Christoph Lameter Signed-off-by: Lee Schermerhorn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/migrate.h | 8 ++++++++ mm/mempolicy.c | 9 --------- mm/migrate.c | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'mm/mempolicy.c') diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 48148e0cdbd1..75e55dcdeb18 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -5,6 +5,14 @@ typedef struct page *new_page_t(struct page *, unsigned long private, int **); +/* Check if a vma is migratable */ +static inline int vma_migratable(struct vm_area_struct *vma) +{ + if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED)) + return 0; + return 1; +} + #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index cf2a5381030a..d76e8eb342d0 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -321,15 +321,6 @@ static inline int check_pgd_range(struct vm_area_struct *vma, return 0; } -/* Check if a vma is migratable */ -static inline int vma_migratable(struct vm_area_struct *vma) -{ - if (vma->vm_flags & ( - VM_LOCKED|VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED)) - return 0; - return 1; -} - /* * Check if all pages in a range are on a set of nodes. * If pagelist != NULL then isolate pages from the LRU and diff --git a/mm/migrate.c b/mm/migrate.c index e9b161bde95b..7a66ca25dc8a 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -781,7 +781,7 @@ static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm, err = -EFAULT; vma = find_vma(mm, pp->addr); - if (!vma) + if (!vma || !vma_migratable(vma)) goto set_status; page = follow_page(vma, pp->addr, FOLL_GET); -- cgit v1.2.3