Skip to content

Commit

Permalink
orangefs: implement vm_ops->fault
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin Brandenburg authored and hubcapsc committed Apr 4, 2018
1 parent dbcb5e7 commit a5135ee
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions fs/orangefs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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)
Expand Down

0 comments on commit a5135ee

Please sign in to comment.