diff options
Diffstat (limited to 'mm/madvise.c')
| -rw-r--r-- | mm/madvise.c | 18 | 
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 @@  #include <linux/sched.h>  #include <linux/ksm.h>  #include <linux/fs.h> +#include <linux/file.h>  /*   * 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,  {  	loff_t offset;  	int error; +	struct file *f;  	*prev = NULL;	/* tell sys_madvise we drop mmap_sem */  	if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))  		return -EINVAL; -	if (!vma->vm_file || !vma->vm_file->f_mapping -		|| !vma->vm_file->f_mapping->host) { +	f = vma->vm_file; + +	if (!f || !f->f_mapping || !f->f_mapping->host) {  			return -EINVAL;  	} @@ -221,11 +224,18 @@ static long madvise_remove(struct vm_area_struct *vma,  	offset = (loff_t)(start - vma->vm_start)  			+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT); -	/* filesystem's fallocate may need to take i_mutex */ +	/* +	 * Filesystem's fallocate may need to take i_mutex.  We need to +	 * explicitly grab a reference because the vma (and hence the +	 * vma's reference to the file) can go away as soon as we drop +	 * mmap_sem. +	 */ +	get_file(f);  	up_read(¤t->mm->mmap_sem); -	error = do_fallocate(vma->vm_file, +	error = do_fallocate(f,  				FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,  				offset, end - start); +	fput(f);  	down_read(¤t->mm->mmap_sem);  	return error;  }  | 
