aboutsummaryrefslogtreecommitdiffstats
path: root/mm/madvise.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/madvise.c')
-rw-r--r--mm/madvise.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/mm/madvise.c b/mm/madvise.c
index deff1b64a08c..14d260fa0d17 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -15,6 +15,7 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/ksm.h> 16#include <linux/ksm.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/file.h>
18 19
19/* 20/*
20 * Any behaviour which results in changes to the vma->vm_flags needs to 21 * Any behaviour which results in changes to the vma->vm_flags needs to
@@ -204,14 +205,16 @@ static long madvise_remove(struct vm_area_struct *vma,
204{ 205{
205 loff_t offset; 206 loff_t offset;
206 int error; 207 int error;
208 struct file *f;
207 209
208 *prev = NULL; /* tell sys_madvise we drop mmap_sem */ 210 *prev = NULL; /* tell sys_madvise we drop mmap_sem */
209 211
210 if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB)) 212 if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
211 return -EINVAL; 213 return -EINVAL;
212 214
213 if (!vma->vm_file || !vma->vm_file->f_mapping 215 f = vma->vm_file;
214 || !vma->vm_file->f_mapping->host) { 216
217 if (!f || !f->f_mapping || !f->f_mapping->host) {
215 return -EINVAL; 218 return -EINVAL;
216 } 219 }
217 220
@@ -221,11 +224,18 @@ static long madvise_remove(struct vm_area_struct *vma,
221 offset = (loff_t)(start - vma->vm_start) 224 offset = (loff_t)(start - vma->vm_start)
222 + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); 225 + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
223 226
224 /* filesystem's fallocate may need to take i_mutex */ 227 /*
228 * Filesystem's fallocate may need to take i_mutex. We need to
229 * explicitly grab a reference because the vma (and hence the
230 * vma's reference to the file) can go away as soon as we drop
231 * mmap_sem.
232 */
233 get_file(f);
225 up_read(&current->mm->mmap_sem); 234 up_read(&current->mm->mmap_sem);
226 error = do_fallocate(vma->vm_file, 235 error = do_fallocate(f,
227 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 236 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
228 offset, end - start); 237 offset, end - start);
238 fput(f);
229 down_read(&current->mm->mmap_sem); 239 down_read(&current->mm->mmap_sem);
230 return error; 240 return error;
231} 241}