aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h1
-rw-r--r--include/linux/mman.h4
-rw-r--r--mm/fremap.c12
-rw-r--r--mm/mlock.c19
-rw-r--r--mm/mmap.c4
5 files changed, 25 insertions, 15 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0c34d3486816..9a5fcdeaa3a0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -87,6 +87,7 @@ extern unsigned int kobjsize(const void *objp);
87#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */ 87#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
88#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ 88#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
89 89
90#define VM_POPULATE 0x00001000
90#define VM_LOCKED 0x00002000 91#define VM_LOCKED 0x00002000
91#define VM_IO 0x00004000 /* Memory mapped I/O or similar */ 92#define VM_IO 0x00004000 /* Memory mapped I/O or similar */
92 93
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 9aa863da287f..61c7a87e5d2b 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -79,6 +79,8 @@ calc_vm_flag_bits(unsigned long flags)
79{ 79{
80 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | 80 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
81 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | 81 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
82 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); 82 ((flags & MAP_LOCKED) ? (VM_LOCKED | VM_POPULATE) : 0) |
83 (((flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE) ?
84 VM_POPULATE : 0);
83} 85}
84#endif /* _LINUX_MMAN_H */ 86#endif /* _LINUX_MMAN_H */
diff --git a/mm/fremap.c b/mm/fremap.c
index 503a72387087..0cd4c11488ed 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -204,8 +204,10 @@ get_write_lock:
204 unsigned long addr; 204 unsigned long addr;
205 struct file *file = get_file(vma->vm_file); 205 struct file *file = get_file(vma->vm_file);
206 206
207 addr = mmap_region(file, start, size, 207 vm_flags = vma->vm_flags;
208 vma->vm_flags, pgoff); 208 if (!(flags & MAP_NONBLOCK))
209 vm_flags |= VM_POPULATE;
210 addr = mmap_region(file, start, size, vm_flags, pgoff);
209 fput(file); 211 fput(file);
210 if (IS_ERR_VALUE(addr)) { 212 if (IS_ERR_VALUE(addr)) {
211 err = addr; 213 err = addr;
@@ -224,6 +226,12 @@ get_write_lock:
224 mutex_unlock(&mapping->i_mmap_mutex); 226 mutex_unlock(&mapping->i_mmap_mutex);
225 } 227 }
226 228
229 if (!(flags & MAP_NONBLOCK) && !(vma->vm_flags & VM_POPULATE)) {
230 if (!has_write_lock)
231 goto get_write_lock;
232 vma->vm_flags |= VM_POPULATE;
233 }
234
227 if (vma->vm_flags & VM_LOCKED) { 235 if (vma->vm_flags & VM_LOCKED) {
228 /* 236 /*
229 * drop PG_Mlocked flag for over-mapped range 237 * drop PG_Mlocked flag for over-mapped range
diff --git a/mm/mlock.c b/mm/mlock.c
index 569400a5d079..d6378feb2950 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -340,9 +340,9 @@ static int do_mlock(unsigned long start, size_t len, int on)
340 340
341 /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ 341 /* Here we know that vma->vm_start <= nstart < vma->vm_end. */
342 342
343 newflags = vma->vm_flags | VM_LOCKED; 343 newflags = vma->vm_flags & ~VM_LOCKED;
344 if (!on) 344 if (on)
345 newflags &= ~VM_LOCKED; 345 newflags |= VM_LOCKED | VM_POPULATE;
346 346
347 tmp = vma->vm_end; 347 tmp = vma->vm_end;
348 if (tmp > end) 348 if (tmp > end)
@@ -402,7 +402,8 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors)
402 * range with the first VMA. Also, skip undesirable VMA types. 402 * range with the first VMA. Also, skip undesirable VMA types.
403 */ 403 */
404 nend = min(end, vma->vm_end); 404 nend = min(end, vma->vm_end);
405 if (vma->vm_flags & (VM_IO | VM_PFNMAP)) 405 if ((vma->vm_flags & (VM_IO | VM_PFNMAP | VM_POPULATE)) !=
406 VM_POPULATE)
406 continue; 407 continue;
407 if (nstart < vma->vm_start) 408 if (nstart < vma->vm_start)
408 nstart = vma->vm_start; 409 nstart = vma->vm_start;
@@ -475,18 +476,18 @@ static int do_mlockall(int flags)
475 struct vm_area_struct * vma, * prev = NULL; 476 struct vm_area_struct * vma, * prev = NULL;
476 477
477 if (flags & MCL_FUTURE) 478 if (flags & MCL_FUTURE)
478 current->mm->def_flags |= VM_LOCKED; 479 current->mm->def_flags |= VM_LOCKED | VM_POPULATE;
479 else 480 else
480 current->mm->def_flags &= ~VM_LOCKED; 481 current->mm->def_flags &= ~(VM_LOCKED | VM_POPULATE);
481 if (flags == MCL_FUTURE) 482 if (flags == MCL_FUTURE)
482 goto out; 483 goto out;
483 484
484 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) { 485 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
485 vm_flags_t newflags; 486 vm_flags_t newflags;
486 487
487 newflags = vma->vm_flags | VM_LOCKED; 488 newflags = vma->vm_flags & ~VM_LOCKED;
488 if (!(flags & MCL_CURRENT)) 489 if (flags & MCL_CURRENT)
489 newflags &= ~VM_LOCKED; 490 newflags |= VM_LOCKED | VM_POPULATE;
490 491
491 /* Ignore errors */ 492 /* Ignore errors */
492 mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags); 493 mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
diff --git a/mm/mmap.c b/mm/mmap.c
index 8826c77513a9..39a3944e1658 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1306,9 +1306,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1306 } 1306 }
1307 1307
1308 addr = mmap_region(file, addr, len, vm_flags, pgoff); 1308 addr = mmap_region(file, addr, len, vm_flags, pgoff);
1309 if (!IS_ERR_VALUE(addr) && 1309 if (!IS_ERR_VALUE(addr) && (vm_flags & VM_POPULATE))
1310 ((vm_flags & VM_LOCKED) ||
1311 (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE))
1312 *populate = true; 1310 *populate = true;
1313 return addr; 1311 return addr;
1314} 1312}