Skip to content

Commit a5135ee

Browse files
Martin Brandenburghubcapsc
authored andcommitted
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 <[email protected]> Signed-off-by: Mike Marshall <[email protected]>
1 parent dbcb5e7 commit a5135ee

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

fs/orangefs/file.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,28 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar
528528
return ret;
529529
}
530530

531+
static int orangefs_fault(struct vm_fault *vmf)
532+
{
533+
struct file *file = vmf->vma->vm_file;
534+
int rc;
535+
rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
536+
STATX_SIZE);
537+
if (rc == -ESTALE)
538+
rc = -EIO;
539+
if (rc) {
540+
gossip_err("%s: orangefs_inode_getattr failed, "
541+
"rc:%d:.\n", __func__, rc);
542+
return rc;
543+
}
544+
return filemap_fault(vmf);
545+
}
546+
547+
const struct vm_operations_struct orangefs_file_vm_ops = {
548+
.fault = orangefs_fault,
549+
.map_pages = filemap_map_pages,
550+
.page_mkwrite = filemap_page_mkwrite,
551+
};
552+
531553
/*
532554
* Memory map a region of a file.
533555
*/
@@ -539,12 +561,16 @@ static int orangefs_file_mmap(struct file *file, struct vm_area_struct *vma)
539561
(char *)file->f_path.dentry->d_name.name :
540562
(char *)"Unknown"));
541563

564+
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
565+
return -EINVAL;
566+
542567
/* set the sequential readahead hint */
543568
vma->vm_flags |= VM_SEQ_READ;
544569
vma->vm_flags &= ~VM_RAND_READ;
545570

546-
/* Use readonly mmap since we cannot support writable maps. */
547-
return generic_file_readonly_mmap(file, vma);
571+
file_accessed(file);
572+
vma->vm_ops = &orangefs_file_vm_ops;
573+
return 0;
548574
}
549575

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

0 commit comments

Comments
 (0)