|
@@ -797,16 +797,19 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static int lookup_node(unsigned long addr)
|
|
|
|
|
|
+static int lookup_node(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
{
|
|
struct page *p;
|
|
struct page *p;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- err = get_user_pages(addr & PAGE_MASK, 1, 0, &p, NULL);
|
|
|
|
|
|
+ int locked = 1;
|
|
|
|
+ err = get_user_pages_locked(addr & PAGE_MASK, 1, 0, &p, &locked);
|
|
if (err >= 0) {
|
|
if (err >= 0) {
|
|
err = page_to_nid(p);
|
|
err = page_to_nid(p);
|
|
put_page(p);
|
|
put_page(p);
|
|
}
|
|
}
|
|
|
|
+ if (locked)
|
|
|
|
+ up_read(&mm->mmap_sem);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -817,7 +820,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
|
|
int err;
|
|
int err;
|
|
struct mm_struct *mm = current->mm;
|
|
struct mm_struct *mm = current->mm;
|
|
struct vm_area_struct *vma = NULL;
|
|
struct vm_area_struct *vma = NULL;
|
|
- struct mempolicy *pol = current->mempolicy;
|
|
|
|
|
|
+ struct mempolicy *pol = current->mempolicy, *pol_refcount = NULL;
|
|
|
|
|
|
if (flags &
|
|
if (flags &
|
|
~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED))
|
|
~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED))
|
|
@@ -857,7 +860,16 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
|
|
|
|
|
|
if (flags & MPOL_F_NODE) {
|
|
if (flags & MPOL_F_NODE) {
|
|
if (flags & MPOL_F_ADDR) {
|
|
if (flags & MPOL_F_ADDR) {
|
|
- err = lookup_node(addr);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Take a refcount on the mpol, lookup_node()
|
|
|
|
+ * wil drop the mmap_sem, so after calling
|
|
|
|
+ * lookup_node() only "pol" remains valid, "vma"
|
|
|
|
+ * is stale.
|
|
|
|
+ */
|
|
|
|
+ pol_refcount = pol;
|
|
|
|
+ vma = NULL;
|
|
|
|
+ mpol_get(pol);
|
|
|
|
+ err = lookup_node(mm, addr);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto out;
|
|
goto out;
|
|
*policy = err;
|
|
*policy = err;
|
|
@@ -892,7 +904,9 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
|
|
out:
|
|
out:
|
|
mpol_cond_put(pol);
|
|
mpol_cond_put(pol);
|
|
if (vma)
|
|
if (vma)
|
|
- up_read(¤t->mm->mmap_sem);
|
|
|
|
|
|
+ up_read(&mm->mmap_sem);
|
|
|
|
+ if (pol_refcount)
|
|
|
|
+ mpol_put(pol_refcount);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|