xfs: move helpers that lock and unlock 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)
Move the double-inode locking helpers to xfs_inode.c since they're not
specific to reflink.

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_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_reflink.c
fs/xfs/xfs_reflink.h

index f189bdcbedddd51c39bb233f4f5cc9a85f957bea..97aa74800bd9969eae567d33a22b4fbf3be18258 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(src, dest);
+       xfs_iunlock2_io_mmap(src, dest);
        if (ret)
                trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
        return remapped > 0 ? remapped : ret;
index 9aea7d68d8ab9a99fe726085e041ae5a32c488d5..24edec472a7c53088afc7020dda9d1ddbf0415aa 100644 (file)
@@ -3881,3 +3881,96 @@ xfs_log_force_inode(
                return 0;
        return xfs_log_force_lsn(ip->i_mount, lsn, XFS_LOG_SYNC, NULL);
 }
+
+/*
+ * Grab the exclusive iolock for a data copy from src to dest, making sure to
+ * abide vfs locking order (lowest pointer value goes first) and breaking the
+ * layout leases before proceeding.  The loop is needed because we cannot call
+ * the blocking break_layout() with the iolocks held, and therefore have to
+ * back out both locks.
+ */
+static int
+xfs_iolock_two_inodes_and_break_layout(
+       struct inode            *src,
+       struct inode            *dest)
+{
+       int                     error;
+
+       if (src > dest)
+               swap(src, dest);
+
+retry:
+       /* Wait to break both inodes' layouts before we start locking. */
+       error = break_layout(src, true);
+       if (error)
+               return error;
+       if (src != dest) {
+               error = break_layout(dest, true);
+               if (error)
+                       return error;
+       }
+
+       /* Lock one inode and make sure nobody got in and leased it. */
+       inode_lock(src);
+       error = break_layout(src, false);
+       if (error) {
+               inode_unlock(src);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
+               return error;
+       }
+
+       if (src == dest)
+               return 0;
+
+       /* Lock the other inode and make sure nobody got in and leased it. */
+       inode_lock_nested(dest, I_MUTEX_NONDIR2);
+       error = break_layout(dest, false);
+       if (error) {
+               inode_unlock(src);
+               inode_unlock(dest);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
+               return error;
+       }
+
+       return 0;
+}
+
+/*
+ * Lock two inodes so that userspace cannot initiate I/O via file syscalls or
+ * mmap activity.
+ */
+int
+xfs_ilock2_io_mmap(
+       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 inodes to allow IO and mmap activity. */
+void
+xfs_iunlock2_io_mmap(
+       struct xfs_inode        *ip1,
+       struct xfs_inode        *ip2)
+{
+       bool                    same_inode = (ip1 == ip2);
+
+       xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
+       if (!same_inode)
+               xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
+       inode_unlock(VFS_I(ip2));
+       if (!same_inode)
+               inode_unlock(VFS_I(ip1));
+}
index 47d3b391030d6da4ad89b5e8eaf4e735fbb115f1..1534386b430c611c476c345e603a893b04074162 100644 (file)
@@ -499,4 +499,7 @@ void xfs_iunlink_destroy(struct xfs_perag *pag);
 
 void xfs_end_io(struct work_struct *work);
 
+int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
+void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
+
 #endif /* __XFS_INODE_H__ */
index c1f2222ffece69e81264665087d6c1e55942ac83..aac83f9d61075083b6d86c0948970e9aa897920a 100644 (file)
@@ -1229,99 +1229,6 @@ xfs_reflink_remap_blocks(
        return error;
 }
 
-/*
- * Grab the exclusive iolock for a data copy from src to dest, making sure to
- * abide vfs locking order (lowest pointer value goes first) and breaking the
- * layout leases before proceeding.  The loop is needed because we cannot call
- * the blocking break_layout() with the iolocks held, and therefore have to
- * back out both locks.
- */
-static int
-xfs_iolock_two_inodes_and_break_layout(
-       struct inode            *src,
-       struct inode            *dest)
-{
-       int                     error;
-
-       if (src > dest)
-               swap(src, dest);
-
-retry:
-       /* Wait to break both inodes' layouts before we start locking. */
-       error = break_layout(src, true);
-       if (error)
-               return error;
-       if (src != dest) {
-               error = break_layout(dest, true);
-               if (error)
-                       return error;
-       }
-
-       /* Lock one inode and make sure nobody got in and leased it. */
-       inode_lock(src);
-       error = break_layout(src, false);
-       if (error) {
-               inode_unlock(src);
-               if (error == -EWOULDBLOCK)
-                       goto retry;
-               return error;
-       }
-
-       if (src == dest)
-               return 0;
-
-       /* Lock the other inode and make sure nobody got in and leased it. */
-       inode_lock_nested(dest, I_MUTEX_NONDIR2);
-       error = break_layout(dest, false);
-       if (error) {
-               inode_unlock(src);
-               inode_unlock(dest);
-               if (error == -EWOULDBLOCK)
-                       goto retry;
-               return error;
-       }
-
-       return 0;
-}
-
-/*
- * 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 xfs_inode        *ip1,
-       struct xfs_inode        *ip2)
-{
-       bool                    same_inode = (ip1 == ip2);
-
-       xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
-       if (!same_inode)
-               xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
-       inode_unlock(VFS_I(ip2));
-       if (!same_inode)
-               inode_unlock(VFS_I(ip1));
-}
-
 /*
  * If we're reflinking to a point past the destination file's EOF, we must
  * zero any speculative post-EOF preallocations that sit between the old EOF
@@ -1387,7 +1294,7 @@ xfs_reflink_remap_prep(
        int                     ret;
 
        /* Lock both files against IO */
-       ret = xfs_reflink_remap_lock(src, dest);
+       ret = xfs_ilock2_io_mmap(src, dest);
        if (ret)
                return ret;
 
@@ -1440,7 +1347,7 @@ xfs_reflink_remap_prep(
 
        return 0;
 out_unlock:
-       xfs_reflink_remap_unlock(src, dest);
+       xfs_iunlock2_io_mmap(src, dest);
        return ret;
 }
 
index ceeb59b86b291489f8fcc25223e3c0688b9ec723..487b00434b962b7980d383651c11ba825548a35a 100644 (file)
@@ -56,6 +56,5 @@ 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 xfs_inode *ip1, struct xfs_inode *ip2);
 
 #endif /* __XFS_REFLINK_H */