mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	userfaultfd: hugetlbfs: add userfaultfd hugetlb hook
When processing a hugetlb fault for no page present, check the vma to determine if faults are to be handled via userfaultfd. If so, drop the hugetlb_fault_mutex and call handle_userfault(). Link: http://lkml.kernel.org/r/20161216144821.5183-21-aarcange@redhat.com Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com> Cc: Michael Rapoport <RAPOPORT@il.ibm.com> Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> Cc: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									810a56b943
								
							
						
					
					
						commit
						1a1aad8a9b
					
				
					 1 changed files with 33 additions and 0 deletions
				
			
		
							
								
								
									
										33
									
								
								mm/hugetlb.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								mm/hugetlb.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -32,6 +32,7 @@
 | 
			
		|||
#include <linux/hugetlb.h>
 | 
			
		||||
#include <linux/hugetlb_cgroup.h>
 | 
			
		||||
#include <linux/node.h>
 | 
			
		||||
#include <linux/userfaultfd_k.h>
 | 
			
		||||
#include "internal.h"
 | 
			
		||||
 | 
			
		||||
int hugepages_treat_as_movable;
 | 
			
		||||
| 
						 | 
				
			
			@ -3680,6 +3681,38 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 | 
			
		|||
		size = i_size_read(mapping->host) >> huge_page_shift(h);
 | 
			
		||||
		if (idx >= size)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Check for page in userfault range
 | 
			
		||||
		 */
 | 
			
		||||
		if (userfaultfd_missing(vma)) {
 | 
			
		||||
			u32 hash;
 | 
			
		||||
			struct vm_fault vmf = {
 | 
			
		||||
				.vma = vma,
 | 
			
		||||
				.address = address,
 | 
			
		||||
				.flags = flags,
 | 
			
		||||
				/*
 | 
			
		||||
				 * Hard to debug if it ends up being
 | 
			
		||||
				 * used by a callee that assumes
 | 
			
		||||
				 * something about the other
 | 
			
		||||
				 * uninitialized fields... same as in
 | 
			
		||||
				 * memory.c
 | 
			
		||||
				 */
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			 * hugetlb_fault_mutex must be dropped before
 | 
			
		||||
			 * handling userfault.  Reacquire after handling
 | 
			
		||||
			 * fault to make calling code simpler.
 | 
			
		||||
			 */
 | 
			
		||||
			hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
 | 
			
		||||
							idx, address);
 | 
			
		||||
			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
 | 
			
		||||
			ret = handle_userfault(&vmf, VM_UFFD_MISSING);
 | 
			
		||||
			mutex_lock(&hugetlb_fault_mutex_table[hash]);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		page = alloc_huge_page(vma, address, 0);
 | 
			
		||||
		if (IS_ERR(page)) {
 | 
			
		||||
			ret = PTR_ERR(page);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue