forked from mirrors/linux
		
	mm: create the new vm_fault_t type
Page fault handlers are supposed to return VM_FAULT codes, but some drivers/file systems mistakenly return error numbers. Now that all drivers/file systems have been converted to use the vm_fault_t return type, change the type definition to no longer be compatible with 'int'. By making it an unsigned int, the function prototype becomes incompatible with a function which returns int. Sparse will detect any attempts to return a value which is not a VM_FAULT code. VM_FAULT_SET_HINDEX and VM_FAULT_GET_HINDEX values are changed to avoid conflict with other VM_FAULT codes. [jrdr.linux@gmail.com: fix warnings] Link: http://lkml.kernel.org/r/20190109183742.GA24326@jordon-HP-15-Notebook-PC Link: http://lkml.kernel.org/r/20190108183041.GA12137@jordon-HP-15-Notebook-PC Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com> Reviewed-by: William Kucharski <william.kucharski@oracle.com> Reviewed-by: Mike Rapoport <rppt@linux.ibm.com> Reviewed-by: Matthew Wilcox <willy@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Rik van Riel <riel@redhat.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
							
								
									c2938eeb88
								
							
						
					
					
						commit
						3d3539018d
					
				
					 3 changed files with 73 additions and 48 deletions
				
			
		|  | @ -1031,7 +1031,7 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code, | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | ||||||
| 	  unsigned int fault) | 	  vm_fault_t fault) | ||||||
| { | { | ||||||
| 	struct task_struct *tsk = current; | 	struct task_struct *tsk = current; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1322,52 +1322,6 @@ static inline void clear_page_pfmemalloc(struct page *page) | ||||||
| 	page->index = 0; | 	page->index = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Different kinds of faults, as returned by handle_mm_fault(). |  | ||||||
|  * Used to decide whether a process gets delivered SIGBUS or |  | ||||||
|  * just gets major/minor fault counters bumped up. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #define VM_FAULT_OOM	0x0001 |  | ||||||
| #define VM_FAULT_SIGBUS	0x0002 |  | ||||||
| #define VM_FAULT_MAJOR	0x0004 |  | ||||||
| #define VM_FAULT_WRITE	0x0008	/* Special case for get_user_pages */ |  | ||||||
| #define VM_FAULT_HWPOISON 0x0010	/* Hit poisoned small page */ |  | ||||||
| #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */ |  | ||||||
| #define VM_FAULT_SIGSEGV 0x0040 |  | ||||||
| 
 |  | ||||||
| #define VM_FAULT_NOPAGE	0x0100	/* ->fault installed the pte, not return page */ |  | ||||||
| #define VM_FAULT_LOCKED	0x0200	/* ->fault locked the returned page */ |  | ||||||
| #define VM_FAULT_RETRY	0x0400	/* ->fault blocked, must retry */ |  | ||||||
| #define VM_FAULT_FALLBACK 0x0800	/* huge page fault failed, fall back to small */ |  | ||||||
| #define VM_FAULT_DONE_COW   0x1000	/* ->fault has fully handled COW */ |  | ||||||
| #define VM_FAULT_NEEDDSYNC  0x2000	/* ->fault did not modify page tables |  | ||||||
| 					 * and needs fsync() to complete (for |  | ||||||
| 					 * synchronous page faults in DAX) */ |  | ||||||
| 
 |  | ||||||
| #define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ |  | ||||||
| 			 VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ |  | ||||||
| 			 VM_FAULT_FALLBACK) |  | ||||||
| 
 |  | ||||||
| #define VM_FAULT_RESULT_TRACE \ |  | ||||||
| 	{ VM_FAULT_OOM,			"OOM" }, \ |  | ||||||
| 	{ VM_FAULT_SIGBUS,		"SIGBUS" }, \ |  | ||||||
| 	{ VM_FAULT_MAJOR,		"MAJOR" }, \ |  | ||||||
| 	{ VM_FAULT_WRITE,		"WRITE" }, \ |  | ||||||
| 	{ VM_FAULT_HWPOISON,		"HWPOISON" }, \ |  | ||||||
| 	{ VM_FAULT_HWPOISON_LARGE,	"HWPOISON_LARGE" }, \ |  | ||||||
| 	{ VM_FAULT_SIGSEGV,		"SIGSEGV" }, \ |  | ||||||
| 	{ VM_FAULT_NOPAGE,		"NOPAGE" }, \ |  | ||||||
| 	{ VM_FAULT_LOCKED,		"LOCKED" }, \ |  | ||||||
| 	{ VM_FAULT_RETRY,		"RETRY" }, \ |  | ||||||
| 	{ VM_FAULT_FALLBACK,		"FALLBACK" }, \ |  | ||||||
| 	{ VM_FAULT_DONE_COW,		"DONE_COW" }, \ |  | ||||||
| 	{ VM_FAULT_NEEDDSYNC,		"NEEDDSYNC" } |  | ||||||
| 
 |  | ||||||
| /* Encode hstate index for a hwpoisoned large page */ |  | ||||||
| #define VM_FAULT_SET_HINDEX(x) ((x) << 12) |  | ||||||
| #define VM_FAULT_GET_HINDEX(x) (((x) >> 12) & 0xf) |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Can be called by the pagefault handler when it gets a VM_FAULT_OOM. |  * Can be called by the pagefault handler when it gets a VM_FAULT_OOM. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -22,7 +22,6 @@ | ||||||
| #endif | #endif | ||||||
| #define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1)) | #define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1)) | ||||||
| 
 | 
 | ||||||
| typedef int vm_fault_t; |  | ||||||
| 
 | 
 | ||||||
| struct address_space; | struct address_space; | ||||||
| struct mem_cgroup; | struct mem_cgroup; | ||||||
|  | @ -621,6 +620,78 @@ static inline bool mm_tlb_flush_nested(struct mm_struct *mm) | ||||||
| 
 | 
 | ||||||
| struct vm_fault; | struct vm_fault; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * typedef vm_fault_t - Return type for page fault handlers. | ||||||
|  |  * | ||||||
|  |  * Page fault handlers return a bitmask of %VM_FAULT values. | ||||||
|  |  */ | ||||||
|  | typedef __bitwise unsigned int vm_fault_t; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * enum vm_fault_reason - Page fault handlers return a bitmask of | ||||||
|  |  * these values to tell the core VM what happened when handling the | ||||||
|  |  * fault. Used to decide whether a process gets delivered SIGBUS or | ||||||
|  |  * just gets major/minor fault counters bumped up. | ||||||
|  |  * | ||||||
|  |  * @VM_FAULT_OOM:		Out Of Memory | ||||||
|  |  * @VM_FAULT_SIGBUS:		Bad access | ||||||
|  |  * @VM_FAULT_MAJOR:		Page read from storage | ||||||
|  |  * @VM_FAULT_WRITE:		Special case for get_user_pages | ||||||
|  |  * @VM_FAULT_HWPOISON:		Hit poisoned small page | ||||||
|  |  * @VM_FAULT_HWPOISON_LARGE:	Hit poisoned large page. Index encoded | ||||||
|  |  *				in upper bits | ||||||
|  |  * @VM_FAULT_SIGSEGV:		segmentation fault | ||||||
|  |  * @VM_FAULT_NOPAGE:		->fault installed the pte, not return page | ||||||
|  |  * @VM_FAULT_LOCKED:		->fault locked the returned page | ||||||
|  |  * @VM_FAULT_RETRY:		->fault blocked, must retry | ||||||
|  |  * @VM_FAULT_FALLBACK:		huge page fault failed, fall back to small | ||||||
|  |  * @VM_FAULT_DONE_COW:		->fault has fully handled COW | ||||||
|  |  * @VM_FAULT_NEEDDSYNC:		->fault did not modify page tables and needs | ||||||
|  |  *				fsync() to complete (for synchronous page faults | ||||||
|  |  *				in DAX) | ||||||
|  |  * @VM_FAULT_HINDEX_MASK:	mask HINDEX value | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | enum vm_fault_reason { | ||||||
|  | 	VM_FAULT_OOM            = (__force vm_fault_t)0x000001, | ||||||
|  | 	VM_FAULT_SIGBUS         = (__force vm_fault_t)0x000002, | ||||||
|  | 	VM_FAULT_MAJOR          = (__force vm_fault_t)0x000004, | ||||||
|  | 	VM_FAULT_WRITE          = (__force vm_fault_t)0x000008, | ||||||
|  | 	VM_FAULT_HWPOISON       = (__force vm_fault_t)0x000010, | ||||||
|  | 	VM_FAULT_HWPOISON_LARGE = (__force vm_fault_t)0x000020, | ||||||
|  | 	VM_FAULT_SIGSEGV        = (__force vm_fault_t)0x000040, | ||||||
|  | 	VM_FAULT_NOPAGE         = (__force vm_fault_t)0x000100, | ||||||
|  | 	VM_FAULT_LOCKED         = (__force vm_fault_t)0x000200, | ||||||
|  | 	VM_FAULT_RETRY          = (__force vm_fault_t)0x000400, | ||||||
|  | 	VM_FAULT_FALLBACK       = (__force vm_fault_t)0x000800, | ||||||
|  | 	VM_FAULT_DONE_COW       = (__force vm_fault_t)0x001000, | ||||||
|  | 	VM_FAULT_NEEDDSYNC      = (__force vm_fault_t)0x002000, | ||||||
|  | 	VM_FAULT_HINDEX_MASK    = (__force vm_fault_t)0x0f0000, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Encode hstate index for a hwpoisoned large page */ | ||||||
|  | #define VM_FAULT_SET_HINDEX(x) ((__force vm_fault_t)((x) << 16)) | ||||||
|  | #define VM_FAULT_GET_HINDEX(x) (((x) >> 16) & 0xf) | ||||||
|  | 
 | ||||||
|  | #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS |	\ | ||||||
|  | 			VM_FAULT_SIGSEGV | VM_FAULT_HWPOISON |	\ | ||||||
|  | 			VM_FAULT_HWPOISON_LARGE | VM_FAULT_FALLBACK) | ||||||
|  | 
 | ||||||
|  | #define VM_FAULT_RESULT_TRACE \ | ||||||
|  | 	{ VM_FAULT_OOM,                 "OOM" },	\ | ||||||
|  | 	{ VM_FAULT_SIGBUS,              "SIGBUS" },	\ | ||||||
|  | 	{ VM_FAULT_MAJOR,               "MAJOR" },	\ | ||||||
|  | 	{ VM_FAULT_WRITE,               "WRITE" },	\ | ||||||
|  | 	{ VM_FAULT_HWPOISON,            "HWPOISON" },	\ | ||||||
|  | 	{ VM_FAULT_HWPOISON_LARGE,      "HWPOISON_LARGE" },	\ | ||||||
|  | 	{ VM_FAULT_SIGSEGV,             "SIGSEGV" },	\ | ||||||
|  | 	{ VM_FAULT_NOPAGE,              "NOPAGE" },	\ | ||||||
|  | 	{ VM_FAULT_LOCKED,              "LOCKED" },	\ | ||||||
|  | 	{ VM_FAULT_RETRY,               "RETRY" },	\ | ||||||
|  | 	{ VM_FAULT_FALLBACK,            "FALLBACK" },	\ | ||||||
|  | 	{ VM_FAULT_DONE_COW,            "DONE_COW" },	\ | ||||||
|  | 	{ VM_FAULT_NEEDDSYNC,           "NEEDDSYNC" } | ||||||
|  | 
 | ||||||
| struct vm_special_mapping { | struct vm_special_mapping { | ||||||
| 	const char *name;	/* The name, e.g. "[vdso]". */ | 	const char *name;	/* The name, e.g. "[vdso]". */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Souptick Joarder
						Souptick Joarder