git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
vserver 1.9.5.x5
[linux-2.6.git]
/
mm
/
madvise.c
diff --git
a/mm/madvise.c
b/mm/madvise.c
index
81c4ea3
..
944b5e5
100644
(file)
--- a/
mm/madvise.c
+++ b/
mm/madvise.c
@@
-7,7
+7,8
@@
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/mman.h>
#include <linux/pagemap.h>
-
+#include <linux/syscalls.h>
+#include <linux/hugetlb.h>
/*
* We can potentially split a vm area into separate
/*
* We can potentially split a vm area into separate
@@
-17,21
+18,23
@@
static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
unsigned long end, int behavior)
{
struct mm_struct * mm = vma->vm_mm;
unsigned long end, int behavior)
{
struct mm_struct * mm = vma->vm_mm;
- int error;
+ int error
= 0
;
if (start != vma->vm_start) {
error = split_vma(mm, vma, start, 1);
if (error)
if (start != vma->vm_start) {
error = split_vma(mm, vma, start, 1);
if (error)
-
return -EAGAIN
;
+
goto out
;
}
if (end != vma->vm_end) {
error = split_vma(mm, vma, end, 0);
if (error)
}
if (end != vma->vm_end) {
error = split_vma(mm, vma, end, 0);
if (error)
-
return -EAGAIN
;
+
goto out
;
}
}
- spin_lock(&mm->page_table_lock);
+ /*
+ * vm_flags is protected by the mmap_sem held in write mode.
+ */
VM_ClearReadHint(vma);
switch (behavior) {
VM_ClearReadHint(vma);
switch (behavior) {
@@
-44,9
+47,11
@@
static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
default:
break;
}
default:
break;
}
- spin_unlock(&mm->page_table_lock);
- return 0;
+out:
+ if (error == -ENOMEM)
+ error = -EAGAIN;
+ return error;
}
/*
}
/*
@@
-92,16
+97,14
@@
static long madvise_willneed(struct vm_area_struct * vma,
static long madvise_dontneed(struct vm_area_struct * vma,
unsigned long start, unsigned long end)
{
static long madvise_dontneed(struct vm_area_struct * vma,
unsigned long start, unsigned long end)
{
- struct zap_details details;
-
- if (vma->vm_flags & VM_LOCKED)
+ if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma))
return -EINVAL;
if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
return -EINVAL;
if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
- details.check_mapping = NULL;
- details.nonlinear_vma = vma;
- details.first_index = 0;
-
details.last_index = ULONG_MAX
;
+ struct zap_details details = {
+ .nonlinear_vma = vma,
+ .last_index = ULONG_MAX,
+
}
;
zap_page_range(vma, start, end - start, &details);
} else
zap_page_range(vma, start, end - start, NULL);
zap_page_range(vma, start, end - start, &details);
} else
zap_page_range(vma, start, end - start, NULL);
@@
-170,18
+173,24
@@
static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
* -EBADF - map exists, but area maps something that isn't a file.
* -EAGAIN - a kernel resource was temporarily unavailable.
*/
* -EBADF - map exists, but area maps something that isn't a file.
* -EAGAIN - a kernel resource was temporarily unavailable.
*/
-asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior)
+asmlinkage long sys_madvise(unsigned long start, size_t len
_in
, int behavior)
{
unsigned long end;
struct vm_area_struct * vma;
int unmapped_error = 0;
int error = -EINVAL;
{
unsigned long end;
struct vm_area_struct * vma;
int unmapped_error = 0;
int error = -EINVAL;
+ size_t len;
down_write(¤t->mm->mmap_sem);
if (start & ~PAGE_MASK)
goto out;
down_write(¤t->mm->mmap_sem);
if (start & ~PAGE_MASK)
goto out;
- len = (len + ~PAGE_MASK) & PAGE_MASK;
+ len = (len_in + ~PAGE_MASK) & PAGE_MASK;
+
+ /* Check to see whether len was rounded up from small -ve to zero */
+ if (len_in && !len)
+ goto out;
+
end = start + len;
if (end < start)
goto out;
end = start + len;
if (end < start)
goto out;