xfs: Hold inode locks in xfs_trans_alloc_dir
authorAllison Henderson <allison.henderson@oracle.com>
Mon, 15 Apr 2024 21:55:13 +0000 (14:55 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 21:59:02 +0000 (14:59 -0700)
Modify xfs_trans_alloc_dir to hold locks after return.  Caller will be
responsible for manual unlock.  We will need this later to hold locks
across parent pointer operations

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Catherine Hoang <catherine.hoang@oracle.com>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_inode.c
fs/xfs/xfs_trans.c

index 2ec005e6c1dab3d6f5a3272f63a22dc70be7e356..36e1012e156a1c46c311c31f598a17a557d711d4 100644 (file)
@@ -1368,10 +1368,15 @@ xfs_link(
        if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
                xfs_trans_set_sync(tp);
 
-       return xfs_trans_commit(tp);
+       error = xfs_trans_commit(tp);
+       xfs_iunlock(tdp, XFS_ILOCK_EXCL);
+       xfs_iunlock(sip, XFS_ILOCK_EXCL);
+       return error;
 
  error_return:
        xfs_trans_cancel(tp);
+       xfs_iunlock(tdp, XFS_ILOCK_EXCL);
+       xfs_iunlock(sip, XFS_ILOCK_EXCL);
  std_return:
        if (error == -ENOSPC && nospace_error)
                error = nospace_error;
@@ -2781,15 +2786,20 @@ xfs_remove(
 
        error = xfs_trans_commit(tp);
        if (error)
-               goto std_return;
+               goto out_unlock;
 
        if (is_dir && xfs_inode_is_filestream(ip))
                xfs_filestream_deassociate(ip);
 
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       xfs_iunlock(dp, XFS_ILOCK_EXCL);
        return 0;
 
  out_trans_cancel:
        xfs_trans_cancel(tp);
+ out_unlock:
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       xfs_iunlock(dp, XFS_ILOCK_EXCL);
  std_return:
        return error;
 }
index 7350640059cc60dc093d69e23646089cb7a17f98..50d878d78a5e112abeec2d8fcb8eda24f092dcff 100644 (file)
@@ -1430,6 +1430,8 @@ out_cancel:
  * The caller must ensure that the on-disk dquots attached to this inode have
  * already been allocated and initialized.  The ILOCKs will be dropped when the
  * transaction is committed or cancelled.
+ *
+ * Caller is responsible for unlocking the inodes manually upon return
  */
 int
 xfs_trans_alloc_dir(
@@ -1460,8 +1462,8 @@ retry:
 
        xfs_lock_two_inodes(dp, XFS_ILOCK_EXCL, ip, XFS_ILOCK_EXCL);
 
-       xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, dp, 0);
+       xfs_trans_ijoin(tp, ip, 0);
 
        error = xfs_qm_dqattach_locked(dp, false);
        if (error) {
@@ -1484,6 +1486,9 @@ retry:
        if (error == -EDQUOT || error == -ENOSPC) {
                if (!retried) {
                        xfs_trans_cancel(tp);
+                       xfs_iunlock(dp, XFS_ILOCK_EXCL);
+                       if (dp != ip)
+                               xfs_iunlock(ip, XFS_ILOCK_EXCL);
                        xfs_blockgc_free_quota(dp, 0);
                        retried = true;
                        goto retry;