4 * (C) Copyright 1995 Linus Torvalds
5 * (C) Copyright 2002 Christoph Hellwig
8 #include <linux/capability.h>
9 #include <linux/mman.h>
11 #include <linux/mempolicy.h>
12 #include <linux/syscalls.h>
13 #include <linux/sched.h>
14 #include <linux/module.h>
16 int can_do_mlock(void)
18 if (capable(CAP_IPC_LOCK
))
20 if (current
->signal
->rlim
[RLIMIT_MEMLOCK
].rlim_cur
!= 0)
24 EXPORT_SYMBOL(can_do_mlock
);
26 static int mlock_fixup(struct vm_area_struct
*vma
, struct vm_area_struct
**prev
,
27 unsigned long start
, unsigned long end
, unsigned int newflags
)
29 struct mm_struct
* mm
= vma
->vm_mm
;
34 if (newflags
== vma
->vm_flags
) {
39 pgoff
= vma
->vm_pgoff
+ ((start
- vma
->vm_start
) >> PAGE_SHIFT
);
40 *prev
= vma_merge(mm
, *prev
, start
, end
, newflags
, vma
->anon_vma
,
41 vma
->vm_file
, pgoff
, vma_policy(vma
));
49 if (start
!= vma
->vm_start
) {
50 ret
= split_vma(mm
, vma
, start
, 1);
55 if (end
!= vma
->vm_end
) {
56 ret
= split_vma(mm
, vma
, end
, 0);
63 * vm_flags is protected by the mmap_sem held in write mode.
64 * It's okay if try_to_unmap_one unmaps a page just after we
65 * set VM_LOCKED, make_pages_present below will bring it back.
67 vma
->vm_flags
= newflags
;
70 * Keep track of amount of locked VM.
72 pages
= (end
- start
) >> PAGE_SHIFT
;
73 if (newflags
& VM_LOCKED
) {
75 if (!(newflags
& VM_IO
))
76 ret
= make_pages_present(start
, end
);
79 mm
->locked_vm
-= pages
;
84 static int do_mlock(unsigned long start
, size_t len
, int on
)
86 unsigned long nstart
, end
, tmp
;
87 struct vm_area_struct
* vma
, * prev
;
90 len
= PAGE_ALIGN(len
);
96 vma
= find_vma_prev(current
->mm
, start
, &prev
);
97 if (!vma
|| vma
->vm_start
> start
)
100 if (start
> vma
->vm_start
)
103 for (nstart
= start
; ; ) {
104 unsigned int newflags
;
106 /* Here we know that vma->vm_start <= nstart < vma->vm_end. */
108 newflags
= vma
->vm_flags
| VM_LOCKED
;
110 newflags
&= ~VM_LOCKED
;
115 error
= mlock_fixup(vma
, &prev
, nstart
, tmp
, newflags
);
119 if (nstart
< prev
->vm_end
)
120 nstart
= prev
->vm_end
;
125 if (!vma
|| vma
->vm_start
!= nstart
) {
133 asmlinkage
long sys_mlock(unsigned long start
, size_t len
)
135 unsigned long locked
;
136 unsigned long lock_limit
;
142 down_write(¤t
->mm
->mmap_sem
);
143 len
= PAGE_ALIGN(len
+ (start
& ~PAGE_MASK
));
146 locked
= len
>> PAGE_SHIFT
;
147 locked
+= current
->mm
->locked_vm
;
149 lock_limit
= current
->signal
->rlim
[RLIMIT_MEMLOCK
].rlim_cur
;
150 lock_limit
>>= PAGE_SHIFT
;
152 /* check against resource limits */
153 if ((locked
<= lock_limit
) || capable(CAP_IPC_LOCK
))
154 error
= do_mlock(start
, len
, 1);
155 up_write(¤t
->mm
->mmap_sem
);
159 asmlinkage
long sys_munlock(unsigned long start
, size_t len
)
163 down_write(¤t
->mm
->mmap_sem
);
164 len
= PAGE_ALIGN(len
+ (start
& ~PAGE_MASK
));
166 ret
= do_mlock(start
, len
, 0);
167 up_write(¤t
->mm
->mmap_sem
);
171 static int do_mlockall(int flags
)
173 struct vm_area_struct
* vma
, * prev
= NULL
;
174 unsigned int def_flags
= 0;
176 if (flags
& MCL_FUTURE
)
177 def_flags
= VM_LOCKED
;
178 current
->mm
->def_flags
= def_flags
;
179 if (flags
== MCL_FUTURE
)
182 for (vma
= current
->mm
->mmap
; vma
; vma
= prev
->vm_next
) {
183 unsigned int newflags
;
185 newflags
= vma
->vm_flags
| VM_LOCKED
;
186 if (!(flags
& MCL_CURRENT
))
187 newflags
&= ~VM_LOCKED
;
190 mlock_fixup(vma
, &prev
, vma
->vm_start
, vma
->vm_end
, newflags
);
196 asmlinkage
long sys_mlockall(int flags
)
198 unsigned long lock_limit
;
201 if (!flags
|| (flags
& ~(MCL_CURRENT
| MCL_FUTURE
)))
208 down_write(¤t
->mm
->mmap_sem
);
210 lock_limit
= current
->signal
->rlim
[RLIMIT_MEMLOCK
].rlim_cur
;
211 lock_limit
>>= PAGE_SHIFT
;
214 if (!(flags
& MCL_CURRENT
) || (current
->mm
->total_vm
<= lock_limit
) ||
215 capable(CAP_IPC_LOCK
))
216 ret
= do_mlockall(flags
);
217 up_write(¤t
->mm
->mmap_sem
);
222 asmlinkage
long sys_munlockall(void)
226 down_write(¤t
->mm
->mmap_sem
);
227 ret
= do_mlockall(0);
228 up_write(¤t
->mm
->mmap_sem
);
233 * Objects with different lifetime than processes (SHM_LOCK and SHM_HUGETLB
234 * shm segments) get accounted against the user_struct instead.
236 static DEFINE_SPINLOCK(shmlock_user_lock
);
238 int user_shm_lock(size_t size
, struct user_struct
*user
)
240 unsigned long lock_limit
, locked
;
243 locked
= (size
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
244 lock_limit
= current
->signal
->rlim
[RLIMIT_MEMLOCK
].rlim_cur
;
245 if (lock_limit
== RLIM_INFINITY
)
247 lock_limit
>>= PAGE_SHIFT
;
248 spin_lock(&shmlock_user_lock
);
250 locked
+ user
->locked_shm
> lock_limit
&& !capable(CAP_IPC_LOCK
))
253 user
->locked_shm
+= locked
;
256 spin_unlock(&shmlock_user_lock
);
260 void user_shm_unlock(size_t size
, struct user_struct
*user
)
262 spin_lock(&shmlock_user_lock
);
263 user
->locked_shm
-= (size
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
264 spin_unlock(&shmlock_user_lock
);