|
@@ -2664,12 +2664,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
|
|
if (!vma || !(vma->vm_flags & VM_SHARED))
|
|
|
goto out;
|
|
|
|
|
|
- if (start < vma->vm_start || start + size > vma->vm_end)
|
|
|
+ if (start < vma->vm_start)
|
|
|
goto out;
|
|
|
|
|
|
- if (pgoff == linear_page_index(vma, start)) {
|
|
|
- ret = 0;
|
|
|
- goto out;
|
|
|
+ if (start + size > vma->vm_end) {
|
|
|
+ struct vm_area_struct *next;
|
|
|
+
|
|
|
+ for (next = vma->vm_next; next; next = next->vm_next) {
|
|
|
+ /* hole between vmas ? */
|
|
|
+ if (next->vm_start != next->vm_prev->vm_end)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (next->vm_file != vma->vm_file)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (next->vm_flags != vma->vm_flags)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (start + size <= next->vm_end)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!next)
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
prot |= vma->vm_flags & VM_READ ? PROT_READ : 0;
|
|
@@ -2679,9 +2696,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
|
|
|
flags &= MAP_NONBLOCK;
|
|
|
flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE;
|
|
|
if (vma->vm_flags & VM_LOCKED) {
|
|
|
+ struct vm_area_struct *tmp;
|
|
|
flags |= MAP_LOCKED;
|
|
|
+
|
|
|
/* drop PG_Mlocked flag for over-mapped range */
|
|
|
- munlock_vma_pages_range(vma, start, start + size);
|
|
|
+ for (tmp = vma; tmp->vm_start >= start + size;
|
|
|
+ tmp = tmp->vm_next) {
|
|
|
+ munlock_vma_pages_range(tmp,
|
|
|
+ max(tmp->vm_start, start),
|
|
|
+ min(tmp->vm_end, start + size));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
file = get_file(vma->vm_file);
|