Commit 4fb23e439ce09157d64b89a21061b9fc08f2b495

Authored by Linus Torvalds
1 parent c7ef259bfb

Fix up mm/mincore.c error value cases

Hugh Dickins correctly points out that mincore() is actually _supposed_
to fail on an unmapped hole in the user address space, rather than
return valid ("empty") information about the hole.  This just simplifies
the problem further (I had been misled by our previous confusing and
complicated way of doing mincore()).

Also, in the unlikely situation that we can't allocate a temporary
kernel buffer, we should actually return EAGAIN, not ENOMEM, to keep the
"unmapped hole" and "allocation failure" error cases separate.

Finally, add a comment about our stupid historical lack of support for
anonymous mappings.  I'll fix that if somebody reminds me after 2.6.20
is out.

Acked-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 10 additions and 19 deletions Side-by-side Diff

... ... @@ -49,29 +49,20 @@
49 49 struct vm_area_struct *vma = find_vma(current->mm, addr);
50 50  
51 51 /*
52   - * find_vma() didn't find anything: the address
53   - * is above everything we have mapped.
  52 + * find_vma() didn't find anything above us, or we're
  53 + * in an unmapped hole in the address space: ENOMEM.
54 54 */
55   - if (!vma) {
56   - memset(vec, 0, pages);
57   - return pages;
58   - }
  55 + if (!vma || addr < vma->vm_start)
  56 + return -ENOMEM;
59 57  
60 58 /*
61   - * find_vma() found something, but we might be
62   - * below it: check for that.
63   - */
64   - if (addr < vma->vm_start) {
65   - unsigned long gap = (vma->vm_start - addr) >> PAGE_SHIFT;
66   - if (gap > pages)
67   - gap = pages;
68   - memset(vec, 0, gap);
69   - return gap;
70   - }
71   -
72   - /*
73 59 * Ok, got it. But check whether it's a segment we support
74 60 * mincore() on. Right now, we don't do any anonymous mappings.
  61 + *
  62 + * FIXME: This is just stupid. And returning ENOMEM is
  63 + * stupid too. We should just look at the page tables. But
  64 + * this is what we've traditionally done, so we'll just
  65 + * continue doing it.
75 66 */
76 67 if (!vma->vm_file)
77 68 return -ENOMEM;
... ... @@ -142,7 +133,7 @@
142 133  
143 134 tmp = (void *) __get_free_page(GFP_USER);
144 135 if (!tmp)
145   - return -ENOMEM;
  136 + return -EAGAIN;
146 137  
147 138 retval = 0;
148 139 while (pages) {