Commit 4fb23e43 authored by Linus Torvalds's avatar Linus Torvalds

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: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c7ef259b
...@@ -49,29 +49,20 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag ...@@ -49,29 +49,20 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag
struct vm_area_struct *vma = find_vma(current->mm, addr); struct vm_area_struct *vma = find_vma(current->mm, addr);
/* /*
* find_vma() didn't find anything: the address * find_vma() didn't find anything above us, or we're
* is above everything we have mapped. * in an unmapped hole in the address space: ENOMEM.
*/ */
if (!vma) { if (!vma || addr < vma->vm_start)
memset(vec, 0, pages); return -ENOMEM;
return pages;
}
/*
* find_vma() found something, but we might be
* below it: check for that.
*/
if (addr < vma->vm_start) {
unsigned long gap = (vma->vm_start - addr) >> PAGE_SHIFT;
if (gap > pages)
gap = pages;
memset(vec, 0, gap);
return gap;
}
/* /*
* Ok, got it. But check whether it's a segment we support * Ok, got it. But check whether it's a segment we support
* mincore() on. Right now, we don't do any anonymous mappings. * mincore() on. Right now, we don't do any anonymous mappings.
*
* FIXME: This is just stupid. And returning ENOMEM is
* stupid too. We should just look at the page tables. But
* this is what we've traditionally done, so we'll just
* continue doing it.
*/ */
if (!vma->vm_file) if (!vma->vm_file)
return -ENOMEM; return -ENOMEM;
...@@ -142,7 +133,7 @@ asmlinkage long sys_mincore(unsigned long start, size_t len, ...@@ -142,7 +133,7 @@ asmlinkage long sys_mincore(unsigned long start, size_t len,
tmp = (void *) __get_free_page(GFP_USER); tmp = (void *) __get_free_page(GFP_USER);
if (!tmp) if (!tmp)
return -ENOMEM; return -EAGAIN;
retval = 0; retval = 0;
while (pages) { while (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