Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5135eea authored by Martin Brandenburg's avatar Martin Brandenburg Committed by Mike Marshall
Browse files

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: default avatarMartin Brandenburg <martin@omnibond.com>
Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent dbcb5e7f
Loading
Loading
Loading
Loading
+28 −2
Original line number Original line Diff line number Diff line
@@ -528,6 +528,28 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar
	return ret;
	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.
 * 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 *)file->f_path.dentry->d_name.name :
			(char *)"Unknown"));
			(char *)"Unknown"));


	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
		return -EINVAL;

	/* set the sequential readahead hint */
	/* set the sequential readahead hint */
	vma->vm_flags |= VM_SEQ_READ;
	vma->vm_flags |= VM_SEQ_READ;
	vma->vm_flags &= ~VM_RAND_READ;
	vma->vm_flags &= ~VM_RAND_READ;


	/* Use readonly mmap since we cannot support writable maps. */
	file_accessed(file);
	return generic_file_readonly_mmap(file, vma);
	vma->vm_ops = &orangefs_file_vm_ops;
	return 0;
}
}


#define mapping_nrpages(idata) ((idata)->nrpages)
#define mapping_nrpages(idata) ((idata)->nrpages)