forked from mirrors/linux
		
	orangefs: implement vm_ops->fault
Must retrieve size before running filemap_fault so the kernel has an up-to-date size. This should have been caught by xfstests generic/246, but it was masked by orangefs_new_inode, which set i_size to PAGE_SIZE. When nothing caused a getattr prior to a pagefault, i_size was still PAGE_SIZE. Since xfstests only read 10 bytes, it did not catch this bug. When orangefs_new_inode was modified to perform a getattr instead, i_size was set to zero, as it was a newly created file. Then orangefs_file_write_iter did NOT set i_size. Instead it invalidated the attribute cache, which should have caused the next caller to retrieve i_size. But the fault handler did not know it was supposed to retrieve i_size. So during xfstests, i_size was still zero, and filemap_fault returned VM_FAULT_SIGBUS. Fixes xfstests generic/452. Signed-off-by: Martin Brandenburg <martin@omnibond.com> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
This commit is contained in:
		
							parent
							
								
									dbcb5e7fc4
								
							
						
					
					
						commit
						a5135eeab2
					
				
					 1 changed files with 28 additions and 2 deletions
				
			
		|  | @ -528,6 +528,28 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int orangefs_fault(struct vm_fault *vmf) | ||||
| { | ||||
| 	struct file *file = vmf->vma->vm_file; | ||||
| 	int rc; | ||||
| 	rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1, | ||||
| 	    STATX_SIZE); | ||||
| 	if (rc == -ESTALE) | ||||
| 		rc = -EIO; | ||||
| 	if (rc) { | ||||
| 		gossip_err("%s: orangefs_inode_getattr failed, " | ||||
| 		    "rc:%d:.\n", __func__, rc); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	return filemap_fault(vmf); | ||||
| } | ||||
| 
 | ||||
| const struct vm_operations_struct orangefs_file_vm_ops = { | ||||
| 	.fault = orangefs_fault, | ||||
| 	.map_pages = filemap_map_pages, | ||||
| 	.page_mkwrite = filemap_page_mkwrite, | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Memory map a region of a file. | ||||
|  */ | ||||
|  | @ -539,12 +561,16 @@ static int orangefs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 			(char *)file->f_path.dentry->d_name.name : | ||||
| 			(char *)"Unknown")); | ||||
| 
 | ||||
| 	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* set the sequential readahead hint */ | ||||
| 	vma->vm_flags |= VM_SEQ_READ; | ||||
| 	vma->vm_flags &= ~VM_RAND_READ; | ||||
| 
 | ||||
| 	/* Use readonly mmap since we cannot support writable maps. */ | ||||
| 	return generic_file_readonly_mmap(file, vma); | ||||
| 	file_accessed(file); | ||||
| 	vma->vm_ops = &orangefs_file_vm_ops; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define mapping_nrpages(idata) ((idata)->nrpages) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Martin Brandenburg
						Martin Brandenburg