Commit b6de4056 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds

[PATCH] mlock-vs-VM_IO hang fix

With Andrea Arcangeli <andrea@novell.com>

Fix a hang which occurs when mlock() encounters a mapping of /dev/mem.
These have VM_IO set.  follow_page() keeps returning zero (not a valid pfn)
and handle_mm_fault() keeps on returning VM_FAULT_MINOR (there's a pte
there), so get_user_pages() locks up.

The patch changes get_user_pages() to just bale out when it hits a VM_IO
region.  make_pages_present() is taught to ignore the resulting -EFAULT.

We still have two bugs:

a) If a process has a VM_IO vma, get_user_pages() will bale early,
   without having considered the vmas at higher virtual addresses.

   As do_mlock() also walks the vma list this bug is fairly benign, but
   get_user_pages() is doing the wrong thing there.

b) The `len' argument to get_user_pages should be long, not int.  We
   presently have a 16TB limit on 64-bit.
Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2f8b7fcf
......@@ -761,7 +761,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
continue;
}
if (!vma || (pages && (vma->vm_flags & VM_IO))
if (!vma || (vma->vm_flags & VM_IO)
|| !(flags & vma->vm_flags))
return i ? : -EFAULT;
......
......@@ -47,7 +47,8 @@ static int mlock_fixup(struct vm_area_struct * vma,
pages = (end - start) >> PAGE_SHIFT;
if (newflags & VM_LOCKED) {
pages = -pages;
ret = make_pages_present(start, end);
if (!(newflags & VM_IO))
ret = make_pages_present(start, end);
}
vma->vm_mm->locked_vm -= pages;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment