blob: fdde550a4bda3e205c81ed5557d7c262b1124e1a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/mm/madvise.c
3 *
4 * Copyright (C) 1999 Linus Torvalds
5 * Copyright (C) 2002 Christoph Hellwig
6 */
7
8#include <linux/mman.h>
9#include <linux/pagemap.h>
10#include <linux/syscalls.h>
Prasanna Meda05b74382005-06-21 17:14:37 -070011#include <linux/mempolicy.h>
Andi Kleenafcf9382009-12-16 12:20:00 +010012#include <linux/page-isolation.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/hugetlb.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040014#include <linux/sched.h>
Hugh Dickinsf8af4da2009-09-21 17:01:57 -070015#include <linux/ksm.h>
Andy Lutomirski9b924402012-07-05 16:00:11 -070016#include <linux/file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017
18/*
Nick Piggin0a27a142007-05-06 14:49:53 -070019 * Any behaviour which results in changes to the vma->vm_flags needs to
20 * take mmap_sem for writing. Others, which simply traverse vmas, need
21 * to only take it for reading.
22 */
23static int madvise_need_mmap_write(int behavior)
24{
25 switch (behavior) {
26 case MADV_REMOVE:
27 case MADV_WILLNEED:
28 case MADV_DONTNEED:
29 return 0;
30 default:
31 /* be safe, default to 1. list exceptions explicitly */
32 return 1;
33 }
34}
35
36/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 * We can potentially split a vm area into separate
38 * areas, each area with its own behavior.
39 */
Prasanna Meda05b74382005-06-21 17:14:37 -070040static long madvise_behavior(struct vm_area_struct * vma,
41 struct vm_area_struct **prev,
42 unsigned long start, unsigned long end, int behavior)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043{
44 struct mm_struct * mm = vma->vm_mm;
45 int error = 0;
Prasanna Meda05b74382005-06-21 17:14:37 -070046 pgoff_t pgoff;
Hugh Dickins3866ea92009-09-21 17:01:52 -070047 unsigned long new_flags = vma->vm_flags;
Prasanna Medae798c6e2005-06-21 17:14:36 -070048
49 switch (behavior) {
Michael S. Tsirkinf8225662006-02-14 13:53:08 -080050 case MADV_NORMAL:
51 new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ;
52 break;
Prasanna Medae798c6e2005-06-21 17:14:36 -070053 case MADV_SEQUENTIAL:
Michael S. Tsirkinf8225662006-02-14 13:53:08 -080054 new_flags = (new_flags & ~VM_RAND_READ) | VM_SEQ_READ;
Prasanna Medae798c6e2005-06-21 17:14:36 -070055 break;
56 case MADV_RANDOM:
Michael S. Tsirkinf8225662006-02-14 13:53:08 -080057 new_flags = (new_flags & ~VM_SEQ_READ) | VM_RAND_READ;
Prasanna Medae798c6e2005-06-21 17:14:36 -070058 break;
Michael S. Tsirkinf8225662006-02-14 13:53:08 -080059 case MADV_DONTFORK:
60 new_flags |= VM_DONTCOPY;
61 break;
62 case MADV_DOFORK:
Hugh Dickins3866ea92009-09-21 17:01:52 -070063 if (vma->vm_flags & VM_IO) {
64 error = -EINVAL;
65 goto out;
66 }
Michael S. Tsirkinf8225662006-02-14 13:53:08 -080067 new_flags &= ~VM_DONTCOPY;
Prasanna Medae798c6e2005-06-21 17:14:36 -070068 break;
Jason Baronaccb61f2012-03-23 15:02:51 -070069 case MADV_DONTDUMP:
Konstantin Khlebnikovec5bf682012-10-08 16:28:59 -070070 new_flags |= VM_DONTDUMP;
Jason Baronaccb61f2012-03-23 15:02:51 -070071 break;
72 case MADV_DODUMP:
Konstantin Khlebnikovec5bf682012-10-08 16:28:59 -070073 if (new_flags & VM_SPECIAL) {
74 error = -EINVAL;
75 goto out;
76 }
77 new_flags &= ~VM_DONTDUMP;
Jason Baronaccb61f2012-03-23 15:02:51 -070078 break;
Hugh Dickinsf8af4da2009-09-21 17:01:57 -070079 case MADV_MERGEABLE:
80 case MADV_UNMERGEABLE:
81 error = ksm_madvise(vma, start, end, behavior, &new_flags);
82 if (error)
83 goto out;
84 break;
Andrea Arcangeli0af4e982011-01-13 15:46:55 -080085 case MADV_HUGEPAGE:
Andrea Arcangelia664b2d2011-01-13 15:47:17 -080086 case MADV_NOHUGEPAGE:
Andrea Arcangeli60ab3242011-01-13 15:47:18 -080087 error = hugepage_madvise(vma, &new_flags, behavior);
Andrea Arcangeli0af4e982011-01-13 15:46:55 -080088 if (error)
89 goto out;
90 break;
Prasanna Medae798c6e2005-06-21 17:14:36 -070091 }
92
Prasanna Meda05b74382005-06-21 17:14:37 -070093 if (new_flags == vma->vm_flags) {
94 *prev = vma;
Hugh Dickins836d5ff2005-09-03 15:54:53 -070095 goto out;
Prasanna Meda05b74382005-06-21 17:14:37 -070096 }
97
98 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
99 *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
Colin Crossa9e6b182013-06-26 17:26:01 -0700100 vma->vm_file, pgoff, vma_policy(vma),
101 vma_get_anon_name(vma));
Prasanna Meda05b74382005-06-21 17:14:37 -0700102 if (*prev) {
103 vma = *prev;
104 goto success;
105 }
106
107 *prev = vma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 if (start != vma->vm_start) {
110 error = split_vma(mm, vma, start, 1);
111 if (error)
112 goto out;
113 }
114
115 if (end != vma->vm_end) {
116 error = split_vma(mm, vma, end, 0);
117 if (error)
118 goto out;
119 }
120
Hugh Dickins836d5ff2005-09-03 15:54:53 -0700121success:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 /*
123 * vm_flags is protected by the mmap_sem held in write mode.
124 */
Prasanna Medae798c6e2005-06-21 17:14:36 -0700125 vma->vm_flags = new_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127out:
128 if (error == -ENOMEM)
129 error = -EAGAIN;
130 return error;
131}
132
133/*
134 * Schedule all required I/O operations. Do not wait for completion.
135 */
136static long madvise_willneed(struct vm_area_struct * vma,
Prasanna Meda05b74382005-06-21 17:14:37 -0700137 struct vm_area_struct ** prev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 unsigned long start, unsigned long end)
139{
140 struct file *file = vma->vm_file;
141
Suzuki1bef4002005-10-11 08:29:06 -0700142 if (!file)
143 return -EBADF;
144
Nick Piggin70688e42008-04-28 02:13:02 -0700145 if (file->f_mapping->a_ops->get_xip_mem) {
Carsten Ottefe77ba62005-06-23 22:05:29 -0700146 /* no bad return value, but ignore advice */
147 return 0;
148 }
149
Prasanna Meda05b74382005-06-21 17:14:37 -0700150 *prev = vma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
152 if (end > vma->vm_end)
153 end = vma->vm_end;
154 end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
155
Wu Fengguangf7e839d2009-06-16 15:31:20 -0700156 force_page_cache_readahead(file->f_mapping, file, start, end - start);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 return 0;
158}
159
160/*
161 * Application no longer needs these pages. If the pages are dirty,
162 * it's OK to just throw them away. The app will be more careful about
163 * data it wants to keep. Be sure to free swap resources too. The
Fernando Luis Vazquez Cao7e6cbea2008-07-29 22:33:39 -0700164 * zap_page_range call sets things up for shrink_active_list to actually free
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 * these pages later if no one else has touched them in the meantime,
166 * although we could add these pages to a global reuse list for
Fernando Luis Vazquez Cao7e6cbea2008-07-29 22:33:39 -0700167 * shrink_active_list to pick up before reclaiming other pages.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 *
169 * NB: This interface discards data rather than pushes it out to swap,
170 * as some implementations do. This has performance implications for
171 * applications like large transactional databases which want to discard
172 * pages in anonymous maps after committing to backing store the data
173 * that was kept in them. There is no reason to write this data out to
174 * the swap area if the application is discarding it.
175 *
176 * An interface that causes the system to free clean pages and flush
177 * dirty pages is already available as msync(MS_INVALIDATE).
178 */
179static long madvise_dontneed(struct vm_area_struct * vma,
Prasanna Meda05b74382005-06-21 17:14:37 -0700180 struct vm_area_struct ** prev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 unsigned long start, unsigned long end)
182{
Prasanna Meda05b74382005-06-21 17:14:37 -0700183 *prev = vma;
Linus Torvalds6aab3412005-11-28 14:34:23 -0800184 if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 return -EINVAL;
186
187 if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
188 struct zap_details details = {
189 .nonlinear_vma = vma,
190 .last_index = ULONG_MAX,
191 };
192 zap_page_range(vma, start, end - start, &details);
193 } else
194 zap_page_range(vma, start, end - start, NULL);
195 return 0;
196}
197
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800198/*
199 * Application wants to free up the pages and associated backing store.
200 * This is effectively punching a hole into the middle of a file.
201 *
202 * NOTE: Currently, only shmfs/tmpfs is supported for this operation.
203 * Other filesystems return -ENOSYS.
204 */
205static long madvise_remove(struct vm_area_struct *vma,
Nick Piggin00e9fa22007-03-16 13:38:10 -0800206 struct vm_area_struct **prev,
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800207 unsigned long start, unsigned long end)
208{
209 struct address_space *mapping;
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700210 loff_t offset, endoff;
211 int error;
Andy Lutomirski9b924402012-07-05 16:00:11 -0700212 struct file *f;
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800213
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700214 *prev = NULL; /* tell sys_madvise we drop mmap_sem */
Nick Piggin00e9fa22007-03-16 13:38:10 -0800215
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800216 if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
217 return -EINVAL;
218
Andy Lutomirski9b924402012-07-05 16:00:11 -0700219 f = vma->vm_file;
220
221 if (!f || !f->f_mapping || !f->f_mapping->host) {
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800222 return -EINVAL;
223 }
224
Hugh Dickins69cf0fa2006-04-17 22:46:32 +0100225 if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
226 return -EACCES;
227
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800228 mapping = vma->vm_file->f_mapping;
229
230 offset = (loff_t)(start - vma->vm_start)
231 + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
232 endoff = (loff_t)(end - vma->vm_start - 1)
233 + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700234
Andy Lutomirski9b924402012-07-05 16:00:11 -0700235 /*
236 * vmtruncate_range may need to take i_mutex. We need to
237 * explicitly grab a reference because the vma (and hence the
238 * vma's reference to the file) can go away as soon as we drop
239 * mmap_sem.
240 */
241 get_file(f);
Nick Piggin0a27a142007-05-06 14:49:53 -0700242 up_read(&current->mm->mmap_sem);
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700243 error = vmtruncate_range(mapping->host, offset, endoff);
Andy Lutomirski9b924402012-07-05 16:00:11 -0700244 fput(f);
Nick Piggin0a27a142007-05-06 14:49:53 -0700245 down_read(&current->mm->mmap_sem);
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700246 return error;
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800247}
248
Andi Kleen9893e492009-09-16 11:50:17 +0200249#ifdef CONFIG_MEMORY_FAILURE
250/*
251 * Error injection support for memory error handling.
252 */
Andi Kleenafcf9382009-12-16 12:20:00 +0100253static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
Andi Kleen9893e492009-09-16 11:50:17 +0200254{
255 int ret = 0;
256
257 if (!capable(CAP_SYS_ADMIN))
258 return -EPERM;
259 for (; start < end; start += PAGE_SIZE) {
260 struct page *p;
Andi Kleend15f1072009-12-16 12:20:00 +0100261 int ret = get_user_pages_fast(start, 1, 0, &p);
Andi Kleen9893e492009-09-16 11:50:17 +0200262 if (ret != 1)
263 return ret;
Andi Kleenafcf9382009-12-16 12:20:00 +0100264 if (bhv == MADV_SOFT_OFFLINE) {
265 printk(KERN_INFO "Soft offlining page %lx at %lx\n",
266 page_to_pfn(p), start);
267 ret = soft_offline_page(p, MF_COUNT_INCREASED);
268 if (ret)
269 break;
270 continue;
271 }
Andi Kleen9893e492009-09-16 11:50:17 +0200272 printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n",
273 page_to_pfn(p), start);
274 /* Ignore return value for now */
Tony Luckcd42f4a2011-12-15 10:48:12 -0800275 memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
Andi Kleen9893e492009-09-16 11:50:17 +0200276 }
277 return ret;
278}
279#endif
280
suzuki165cd402005-07-27 11:43:59 -0700281static long
282madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
283 unsigned long start, unsigned long end, int behavior)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 switch (behavior) {
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800286 case MADV_REMOVE:
Hugh Dickins3866ea92009-09-21 17:01:52 -0700287 return madvise_remove(vma, prev, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 case MADV_WILLNEED:
Hugh Dickins3866ea92009-09-21 17:01:52 -0700289 return madvise_willneed(vma, prev, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 case MADV_DONTNEED:
Hugh Dickins3866ea92009-09-21 17:01:52 -0700291 return madvise_dontneed(vma, prev, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 default:
Hugh Dickins3866ea92009-09-21 17:01:52 -0700293 return madvise_behavior(vma, prev, start, end, behavior);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295}
296
Nick Piggin75927af2009-06-16 15:32:38 -0700297static int
298madvise_behavior_valid(int behavior)
299{
300 switch (behavior) {
301 case MADV_DOFORK:
302 case MADV_DONTFORK:
303 case MADV_NORMAL:
304 case MADV_SEQUENTIAL:
305 case MADV_RANDOM:
306 case MADV_REMOVE:
307 case MADV_WILLNEED:
308 case MADV_DONTNEED:
Hugh Dickinsf8af4da2009-09-21 17:01:57 -0700309#ifdef CONFIG_KSM
310 case MADV_MERGEABLE:
311 case MADV_UNMERGEABLE:
312#endif
Andrea Arcangeli0af4e982011-01-13 15:46:55 -0800313#ifdef CONFIG_TRANSPARENT_HUGEPAGE
314 case MADV_HUGEPAGE:
Andrea Arcangelia664b2d2011-01-13 15:47:17 -0800315 case MADV_NOHUGEPAGE:
Andrea Arcangeli0af4e982011-01-13 15:46:55 -0800316#endif
Jason Baronaccb61f2012-03-23 15:02:51 -0700317 case MADV_DONTDUMP:
318 case MADV_DODUMP:
Nick Piggin75927af2009-06-16 15:32:38 -0700319 return 1;
320
321 default:
322 return 0;
323 }
324}
Hugh Dickins3866ea92009-09-21 17:01:52 -0700325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326/*
327 * The madvise(2) system call.
328 *
329 * Applications can use madvise() to advise the kernel how it should
330 * handle paging I/O in this VM area. The idea is to help the kernel
331 * use appropriate read-ahead and caching techniques. The information
332 * provided is advisory only, and can be safely disregarded by the
333 * kernel without affecting the correct operation of the application.
334 *
335 * behavior values:
336 * MADV_NORMAL - the default behavior is to read clusters. This
337 * results in some read-ahead and read-behind.
338 * MADV_RANDOM - the system should read the minimum amount of data
339 * on any access, since it is unlikely that the appli-
340 * cation will need more than what it asks for.
341 * MADV_SEQUENTIAL - pages in the given range will probably be accessed
342 * once, so they can be aggressively read ahead, and
343 * can be freed soon after they are accessed.
344 * MADV_WILLNEED - the application is notifying the system to read
345 * some pages ahead.
346 * MADV_DONTNEED - the application is finished with the given range,
347 * so the kernel can free resources associated with it.
Badari Pulavartyf6b3ec22006-01-06 00:10:38 -0800348 * MADV_REMOVE - the application wants to free up the given range of
349 * pages and associated backing store.
Hugh Dickins3866ea92009-09-21 17:01:52 -0700350 * MADV_DONTFORK - omit this area from child's address space when forking:
351 * typically, to avoid COWing pages pinned by get_user_pages().
352 * MADV_DOFORK - cancel MADV_DONTFORK: no longer omit this area when forking.
Hugh Dickinsf8af4da2009-09-21 17:01:57 -0700353 * MADV_MERGEABLE - the application recommends that KSM try to merge pages in
354 * this area with pages of identical content from other such areas.
355 * MADV_UNMERGEABLE- cancel MADV_MERGEABLE: no longer merge pages with others.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 *
357 * return values:
358 * zero - success
359 * -EINVAL - start + len < 0, start is not page-aligned,
360 * "behavior" is not a valid value, or application
361 * is attempting to release locked or shared pages.
362 * -ENOMEM - addresses in the specified range are not currently
363 * mapped, or are outside the AS of the process.
364 * -EIO - an I/O error occurred while paging in data.
365 * -EBADF - map exists, but area maps something that isn't a file.
366 * -EAGAIN - a kernel resource was temporarily unavailable.
367 */
Heiko Carstens3480b252009-01-14 14:14:16 +0100368SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
Prasanna Meda05b74382005-06-21 17:14:37 -0700370 unsigned long end, tmp;
371 struct vm_area_struct * vma, *prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 int unmapped_error = 0;
373 int error = -EINVAL;
Jason Baronf7977792007-07-15 23:38:21 -0700374 int write;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 size_t len;
376
Andi Kleen9893e492009-09-16 11:50:17 +0200377#ifdef CONFIG_MEMORY_FAILURE
Andi Kleenafcf9382009-12-16 12:20:00 +0100378 if (behavior == MADV_HWPOISON || behavior == MADV_SOFT_OFFLINE)
379 return madvise_hwpoison(behavior, start, start+len_in);
Andi Kleen9893e492009-09-16 11:50:17 +0200380#endif
Nick Piggin75927af2009-06-16 15:32:38 -0700381 if (!madvise_behavior_valid(behavior))
382 return error;
383
Jason Baronf7977792007-07-15 23:38:21 -0700384 write = madvise_need_mmap_write(behavior);
385 if (write)
Nick Piggin0a27a142007-05-06 14:49:53 -0700386 down_write(&current->mm->mmap_sem);
387 else
388 down_read(&current->mm->mmap_sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 if (start & ~PAGE_MASK)
391 goto out;
392 len = (len_in + ~PAGE_MASK) & PAGE_MASK;
393
394 /* Check to see whether len was rounded up from small -ve to zero */
395 if (len_in && !len)
396 goto out;
397
398 end = start + len;
399 if (end < start)
400 goto out;
401
402 error = 0;
403 if (end == start)
404 goto out;
405
406 /*
407 * If the interval [start,end) covers some unmapped address
408 * ranges, just ignore them, but return -ENOMEM at the end.
Prasanna Meda05b74382005-06-21 17:14:37 -0700409 * - different from the way of handling in mlock etc.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 */
Prasanna Meda05b74382005-06-21 17:14:37 -0700411 vma = find_vma_prev(current->mm, start, &prev);
Hugh Dickins836d5ff2005-09-03 15:54:53 -0700412 if (vma && start > vma->vm_start)
413 prev = vma;
414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 for (;;) {
416 /* Still start < end. */
417 error = -ENOMEM;
418 if (!vma)
419 goto out;
420
Prasanna Meda05b74382005-06-21 17:14:37 -0700421 /* Here start < (end|vma->vm_end). */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 if (start < vma->vm_start) {
423 unmapped_error = -ENOMEM;
424 start = vma->vm_start;
Prasanna Meda05b74382005-06-21 17:14:37 -0700425 if (start >= end)
426 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 }
428
Prasanna Meda05b74382005-06-21 17:14:37 -0700429 /* Here vma->vm_start <= start < (end|vma->vm_end) */
430 tmp = vma->vm_end;
431 if (end < tmp)
432 tmp = end;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Prasanna Meda05b74382005-06-21 17:14:37 -0700434 /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
435 error = madvise_vma(vma, &prev, start, tmp, behavior);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 if (error)
437 goto out;
Prasanna Meda05b74382005-06-21 17:14:37 -0700438 start = tmp;
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700439 if (prev && start < prev->vm_end)
Prasanna Meda05b74382005-06-21 17:14:37 -0700440 start = prev->vm_end;
441 error = unmapped_error;
442 if (start >= end)
443 goto out;
Hugh Dickins90ed52e2007-03-29 01:20:38 -0700444 if (prev)
445 vma = prev->vm_next;
446 else /* madvise_remove dropped mmap_sem */
447 vma = find_vma(current->mm, start);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449out:
Jason Baronf7977792007-07-15 23:38:21 -0700450 if (write)
Nick Piggin0a27a142007-05-06 14:49:53 -0700451 up_write(&current->mm->mmap_sem);
452 else
453 up_read(&current->mm->mmap_sem);
454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return error;
456}