diff options
Diffstat (limited to 'mm/mempolicy.c')
| -rw-r--r-- | mm/mempolicy.c | 30 | 
1 files changed, 24 insertions, 6 deletions
| diff --git a/mm/mempolicy.c b/mm/mempolicy.c index d80fa7d8f72..b21869a39f0 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -330,9 +330,19 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,  	int err;  	struct vm_area_struct *first, *vma, *prev; -	/* Clear the LRU lists so pages can be isolated */ -	if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) +	if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { +		/* Must have swap device for migration */ +		if (nr_swap_pages <= 0) +			return ERR_PTR(-ENODEV); + +		/* +		 * Clear the LRU lists so pages can be isolated. +		 * Note that pages may be moved off the LRU after we have +		 * drained them. Those pages will fail to migrate like other +		 * pages that may be busy. +		 */  		lru_add_drain_all(); +	}  	first = find_vma(mm, start);  	if (!first) @@ -748,7 +758,7 @@ long do_mbind(unsigned long start, unsigned long len,  				      MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))  	    || mode > MPOL_MAX)  		return -EINVAL; -	if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_RESOURCE)) +	if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))  		return -EPERM;  	if (start & ~PAGE_MASK) @@ -942,20 +952,20 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,  	 */  	if ((current->euid != task->suid) && (current->euid != task->uid) &&  	    (current->uid != task->suid) && (current->uid != task->uid) && -	    !capable(CAP_SYS_ADMIN)) { +	    !capable(CAP_SYS_NICE)) {  		err = -EPERM;  		goto out;  	}  	task_nodes = cpuset_mems_allowed(task);  	/* Is the user allowed to access the target nodes? */ -	if (!nodes_subset(new, task_nodes) && !capable(CAP_SYS_ADMIN)) { +	if (!nodes_subset(new, task_nodes) && !capable(CAP_SYS_NICE)) {  		err = -EPERM;  		goto out;  	}  	err = do_migrate_pages(mm, &old, &new, -		capable(CAP_SYS_ADMIN) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE); +		capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);  out:  	mmput(mm);  	return err; @@ -1789,6 +1799,7 @@ static void gather_stats(struct page *page, void *private, int pte_dirty)  	cond_resched();  } +#ifdef CONFIG_HUGETLB_PAGE  static void check_huge_range(struct vm_area_struct *vma,  		unsigned long start, unsigned long end,  		struct numa_maps *md) @@ -1814,6 +1825,13 @@ static void check_huge_range(struct vm_area_struct *vma,  		gather_stats(page, md, pte_dirty(*ptep));  	}  } +#else +static inline void check_huge_range(struct vm_area_struct *vma, +		unsigned long start, unsigned long end, +		struct numa_maps *md) +{ +} +#endif  int show_numa_map(struct seq_file *m, void *v)  { | 
