xfs: refactor locking and unlocking two inodes against userspace IO
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 29 Jun 2020 21:47:20 +0000 (14:47 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 6 Jul 2020 17:46:57 +0000 (10:46 -0700)
Refactor the two functions that we use to lock and unlock two inodes to
block userspace from initiating IO against a file, whether via system
calls or mmap activity.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
fs/xfs/xfs_file.c
fs/xfs/xfs_reflink.c
fs/xfs/xfs_reflink.h

index b375fae..f189bdc 100644 (file)
@@ -1065,7 +1065,7 @@ xfs_file_remap_range(
        if (mp->m_flags & XFS_MOUNT_WSYNC)
                xfs_log_force_inode(dest);
 out_unlock:
-       xfs_reflink_remap_unlock(file_in, file_out);
+       xfs_reflink_remap_unlock(src, dest);
        if (ret)
                trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
        return remapped > 0 ? remapped : ret;
index f07a09d..c1f2222 100644 (file)
@@ -1284,24 +1284,42 @@ retry:
        return 0;
 }
 
-/* Unlock both inodes after they've been prepped for a range clone. */
+/*
+ * Lock two files so that userspace cannot initiate I/O via file syscalls or
+ * mmap activity.
+ */
+static int
+xfs_reflink_remap_lock(
+       struct xfs_inode        *ip1,
+       struct xfs_inode        *ip2)
+{
+       int                     ret;
+
+       ret = xfs_iolock_two_inodes_and_break_layout(VFS_I(ip1), VFS_I(ip2));
+       if (ret)
+               return ret;
+       if (ip1 == ip2)
+               xfs_ilock(ip1, XFS_MMAPLOCK_EXCL);
+       else
+               xfs_lock_two_inodes(ip1, XFS_MMAPLOCK_EXCL,
+                                   ip2, XFS_MMAPLOCK_EXCL);
+       return 0;
+}
+
+/* Unlock both files to allow IO and mmap activity. */
 void
 xfs_reflink_remap_unlock(
-       struct file             *file_in,
-       struct file             *file_out)
+       struct xfs_inode        *ip1,
+       struct xfs_inode        *ip2)
 {
-       struct inode            *inode_in = file_inode(file_in);
-       struct xfs_inode        *src = XFS_I(inode_in);
-       struct inode            *inode_out = file_inode(file_out);
-       struct xfs_inode        *dest = XFS_I(inode_out);
-       bool                    same_inode = (inode_in == inode_out);
+       bool                    same_inode = (ip1 == ip2);
 
-       xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
+       xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
        if (!same_inode)
-               xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
-       inode_unlock(inode_out);
+               xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
+       inode_unlock(VFS_I(ip2));
        if (!same_inode)
-               inode_unlock(inode_in);
+               inode_unlock(VFS_I(ip1));
 }
 
 /*
@@ -1366,18 +1384,12 @@ xfs_reflink_remap_prep(
        struct xfs_inode        *src = XFS_I(inode_in);
        struct inode            *inode_out = file_inode(file_out);
        struct xfs_inode        *dest = XFS_I(inode_out);
-       bool                    same_inode = (inode_in == inode_out);
        int                     ret;
 
        /* Lock both files against IO */
-       ret = xfs_iolock_two_inodes_and_break_layout(inode_in, inode_out);
+       ret = xfs_reflink_remap_lock(src, dest);
        if (ret)
                return ret;
-       if (same_inode)
-               xfs_ilock(src, XFS_MMAPLOCK_EXCL);
-       else
-               xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest,
-                               XFS_MMAPLOCK_EXCL);
 
        /* Check file eligibility and prepare for block sharing. */
        ret = -EINVAL;
@@ -1428,7 +1440,7 @@ xfs_reflink_remap_prep(
 
        return 0;
 out_unlock:
-       xfs_reflink_remap_unlock(file_in, file_out);
+       xfs_reflink_remap_unlock(src, dest);
        return ret;
 }
 
index 3e4fd46..ceeb59b 100644 (file)
@@ -56,7 +56,6 @@ extern int xfs_reflink_remap_blocks(struct xfs_inode *src, loff_t pos_in,
                loff_t *remapped);
 extern int xfs_reflink_update_dest(struct xfs_inode *dest, xfs_off_t newlen,
                xfs_extlen_t cowextsize, unsigned int remap_flags);
-extern void xfs_reflink_remap_unlock(struct file *file_in,
-               struct file *file_out);
+extern void xfs_reflink_remap_unlock(struct xfs_inode *ip1, struct xfs_inode *ip2);
 
 #endif /* __XFS_REFLINK_H */