On Mon, Oct 19, 2015 at 02:27:17PM +1100, Dave Chinner wrote: > From: Dave Chinner <dchinner@xxxxxxxxxx> > > ->pfn_mkwrite support is needed so that when a page with allocated > backing store takes a write fault we can check that the fault has > not raced with a truncate and is pointing to a region beyond the > current end of file. > > This also allows us to update the timestamp on the inode, too, which > fixes a generic/080 failure. > > Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> > --- Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx> > fs/xfs/xfs_file.c | 35 +++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_trace.h | 1 + > 2 files changed, 36 insertions(+) > > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c > index 403151a..e7cf9ec 100644 > --- a/fs/xfs/xfs_file.c > +++ b/fs/xfs/xfs_file.c > @@ -1577,11 +1577,46 @@ xfs_filemap_pmd_fault( > return ret; > } > > +/* > + * pfn_mkwrite was originally inteneded to ensure we capture time stamp > + * updates on write faults. In reality, it's need to serialise against > + * truncate similar to page_mkwrite. Hence we open-code dax_pfn_mkwrite() > + * here and cycle the XFS_MMAPLOCK_SHARED to ensure we serialise the fault > + * barrier in place. > + */ > +static int > +xfs_filemap_pfn_mkwrite( > + struct vm_area_struct *vma, > + struct vm_fault *vmf) > +{ > + > + struct inode *inode = file_inode(vma->vm_file); > + struct xfs_inode *ip = XFS_I(inode); > + int ret = VM_FAULT_NOPAGE; > + loff_t size; > + > + trace_xfs_filemap_pfn_mkwrite(ip); > + > + sb_start_pagefault(inode->i_sb); > + file_update_time(vma->vm_file); > + > + /* check if the faulting page hasn't raced with truncate */ > + xfs_ilock(ip, XFS_MMAPLOCK_SHARED); > + size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT; > + if (vmf->pgoff >= size) > + ret = VM_FAULT_SIGBUS; > + xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); > + sb_end_pagefault(inode->i_sb); > + return ret; > + > +} > + > static const struct vm_operations_struct xfs_file_vm_ops = { > .fault = xfs_filemap_fault, > .pmd_fault = xfs_filemap_pmd_fault, > .map_pages = filemap_map_pages, > .page_mkwrite = xfs_filemap_page_mkwrite, > + .pfn_mkwrite = xfs_filemap_pfn_mkwrite, > }; > > STATIC int > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > index 957f5cc..877079eb 100644 > --- a/fs/xfs/xfs_trace.h > +++ b/fs/xfs/xfs_trace.h > @@ -689,6 +689,7 @@ DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); > DEFINE_INODE_EVENT(xfs_filemap_fault); > DEFINE_INODE_EVENT(xfs_filemap_pmd_fault); > DEFINE_INODE_EVENT(xfs_filemap_page_mkwrite); > +DEFINE_INODE_EVENT(xfs_filemap_pfn_mkwrite); > > DECLARE_EVENT_CLASS(xfs_iref_class, > TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), > -- > 2.5.0 > > _______________________________________________ > xfs mailing list > xfs@xxxxxxxxxxx > http://oss.sgi.com/mailman/listinfo/xfs _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs