diff options
author | Andrew Morton <akpm@osdl.org> | 2006-03-24 03:18:14 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-24 07:33:26 -0800 |
commit | 676758bdb7bfca8413a85203921746f446e237be (patch) | |
tree | 23c731f429652e16f2cdba98cd503eaa059f929b /mm | |
parent | 707c21c848deeb0200ba3f07e4ba90e6dc419c2f (diff) |
[PATCH] msync: fix return value
msync() does a strange thing. Essentially:
vma = find_vma();
for ( ; ; ) {
if (!vma)
return -ENOMEM;
...
vma = vma->vm_next;
}
so an msync() request which starts within or before a valid VMA and which ends
within or beyond the final VMA will incorrectly return -ENOMEM.
Fix.
Cc: Hugh Dickins <hugh@veritas.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/msync.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/mm/msync.c b/mm/msync.c index ee9bd6759833..d6a50f3f28b6 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -146,7 +146,8 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) { unsigned long end; struct vm_area_struct *vma; - int unmapped_error, error = -EINVAL; + int unmapped_error = 0; + int error = -EINVAL; int done = 0; if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC)) @@ -171,15 +172,14 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) if (flags & MS_SYNC) current->flags |= PF_SYNCWRITE; vma = find_vma(current->mm, start); - unmapped_error = 0; + if (!vma) { + error = -ENOMEM; + goto out_unlock; + } do { unsigned long nr_pages_dirtied = 0; struct file *file; - /* Still start < end. */ - error = -ENOMEM; - if (!vma) - goto out_unlock; /* Here start < vma->vm_end. */ if (start < vma->vm_start) { unmapped_error = -ENOMEM; @@ -239,7 +239,7 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) } else { vma = vma->vm_next; } - } while (!done); + } while (vma && !done); out_unlock: current->flags &= ~PF_SYNCWRITE; up_read(¤t->mm->mmap_sem); |