Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: prepare xfs_break_layouts() to be called with XFS_MMAPLOCK_EXCL

In preparation for adding coordination between extent unmap operations
and busy dax-pages, update xfs_break_layouts() to permit it to be called
with the mmap lock held. This lock scheme will be required for
coordinating the break of 'dax layouts' (non-idle dax (ZONE_DEVICE)
pages mapped into the file's address space). Breaking dax layouts will
be added to xfs_break_layouts() in a future patch, for now this preps
the unmap call sites to take and hold XFS_MMAPLOCK_EXCL over the call to
xfs_break_layouts().

Cc: "Darrick J. Wong" <darrick.wong@oracle.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <darrick.wong@oracle.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+13 -14
+1 -4
fs/xfs/xfs_file.c
··· 734 734 struct xfs_inode *ip = XFS_I(inode); 735 735 long error; 736 736 enum xfs_prealloc_flags flags = 0; 737 - uint iolock = XFS_IOLOCK_EXCL; 737 + uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 738 738 loff_t new_size = 0; 739 739 bool do_file_insert = false; 740 740 ··· 747 747 error = xfs_break_layouts(inode, &iolock); 748 748 if (error) 749 749 goto out_unlock; 750 - 751 - xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 752 - iolock |= XFS_MMAPLOCK_EXCL; 753 750 754 751 if (mode & FALLOC_FL_PUNCH_HOLE) { 755 752 error = xfs_free_file_space(ip, offset, len);
+1 -4
fs/xfs/xfs_ioctl.c
··· 614 614 struct xfs_inode *ip = XFS_I(inode); 615 615 struct iattr iattr; 616 616 enum xfs_prealloc_flags flags = 0; 617 - uint iolock = XFS_IOLOCK_EXCL; 617 + uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 618 618 int error; 619 619 620 620 /* ··· 647 647 error = xfs_break_layouts(inode, &iolock); 648 648 if (error) 649 649 goto out_unlock; 650 - 651 - xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 652 - iolock |= XFS_MMAPLOCK_EXCL; 653 650 654 651 switch (bf->l_whence) { 655 652 case 0: /*SEEK_SET*/
+9 -5
fs/xfs/xfs_iops.c
··· 1031 1031 1032 1032 if (iattr->ia_valid & ATTR_SIZE) { 1033 1033 struct xfs_inode *ip = XFS_I(d_inode(dentry)); 1034 - uint iolock = XFS_IOLOCK_EXCL; 1035 - 1036 - error = xfs_break_layouts(d_inode(dentry), &iolock); 1037 - if (error) 1038 - return error; 1034 + uint iolock; 1039 1035 1040 1036 xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 1037 + iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 1038 + 1039 + error = xfs_break_layouts(d_inode(dentry), &iolock); 1040 + if (error) { 1041 + xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); 1042 + return error; 1043 + } 1044 + 1041 1045 error = xfs_vn_setattr_size(dentry, iattr); 1042 1046 xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); 1043 1047 } else {
+2 -1
fs/xfs/xfs_pnfs.c
··· 43 43 while ((error = break_layout(inode, false) == -EWOULDBLOCK)) { 44 44 xfs_iunlock(ip, *iolock); 45 45 error = break_layout(inode, true); 46 - *iolock = XFS_IOLOCK_EXCL; 46 + *iolock &= ~XFS_IOLOCK_SHARED; 47 + *iolock |= XFS_IOLOCK_EXCL; 47 48 xfs_ilock(ip, *iolock); 48 49 } 49 50