diff options
Diffstat (limited to 'mm/memory.c')
| -rw-r--r-- | mm/memory.c | 17 | 
1 files changed, 17 insertions, 0 deletions
| diff --git a/mm/memory.c b/mm/memory.c index 291cbf54b347..78ab57141731 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1990,6 +1990,20 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo  		copy_user_highpage(dst, src, va, vma);  } +static gfp_t __get_fault_gfp_mask(struct vm_area_struct *vma) +{ +	struct file *vm_file = vma->vm_file; + +	if (vm_file) +		return mapping_gfp_mask(vm_file->f_mapping) | __GFP_FS | __GFP_IO; + +	/* +	 * Special mappings (e.g. VDSO) do not have any file so fake +	 * a default GFP_KERNEL for them. +	 */ +	return GFP_KERNEL; +} +  /*   * Notify the address space that the page is about to become writable so that   * it can prohibit this or wait for the page to get into an appropriate state. @@ -2005,6 +2019,7 @@ static int do_page_mkwrite(struct vm_area_struct *vma, struct page *page,  	vmf.virtual_address = (void __user *)(address & PAGE_MASK);  	vmf.pgoff = page->index;  	vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE; +	vmf.gfp_mask = __get_fault_gfp_mask(vma);  	vmf.page = page;  	vmf.cow_page = NULL; @@ -2771,6 +2786,7 @@ static int __do_fault(struct vm_area_struct *vma, unsigned long address,  	vmf.pgoff = pgoff;  	vmf.flags = flags;  	vmf.page = NULL; +	vmf.gfp_mask = __get_fault_gfp_mask(vma);  	vmf.cow_page = cow_page;  	ret = vma->vm_ops->fault(vma, &vmf); @@ -2937,6 +2953,7 @@ static void do_fault_around(struct vm_area_struct *vma, unsigned long address,  	vmf.pgoff = pgoff;  	vmf.max_pgoff = max_pgoff;  	vmf.flags = flags; +	vmf.gfp_mask = __get_fault_gfp_mask(vma);  	vma->vm_ops->map_pages(vma, &vmf);  } | 
