]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: Increase XFS_DEFER_OPS_NR_INODES to 5
authorAllison Henderson <allison.henderson@oracle.com>
Mon, 15 Apr 2024 21:55:11 +0000 (14:55 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 21:59:01 +0000 (14:59 -0700)
Renames that generate parent pointer updates can join up to 5
inodes locked in sorted order.  So we need to increase the
number of defer ops inodes and relock them in the same way.

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>
[djwong: have one sorting function]
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_defer.c
fs/xfs/libxfs/xfs_defer.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h

index 061cc01245a9149de5a03247f657914858555fbe..4a078e07e1a0a07246b845e430ccd08ad94ad125 100644 (file)
@@ -1092,7 +1092,11 @@ xfs_defer_ops_continue(
        ASSERT(!(tp->t_flags & XFS_TRANS_DIRTY));
 
        /* Lock the captured resources to the new transaction. */
-       if (dfc->dfc_held.dr_inos == 2)
+       if (dfc->dfc_held.dr_inos > 2) {
+               xfs_sort_inodes(dfc->dfc_held.dr_ip, dfc->dfc_held.dr_inos);
+               xfs_lock_inodes(dfc->dfc_held.dr_ip, dfc->dfc_held.dr_inos,
+                               XFS_ILOCK_EXCL);
+       } else if (dfc->dfc_held.dr_inos == 2)
                xfs_lock_two_inodes(dfc->dfc_held.dr_ip[0], XFS_ILOCK_EXCL,
                                    dfc->dfc_held.dr_ip[1], XFS_ILOCK_EXCL);
        else if (dfc->dfc_held.dr_inos == 1)
index 81cca60d70a3bc13de44864824e952c334e423df..8b338031e487c4b98d127340109e25db34994950 100644 (file)
@@ -77,7 +77,13 @@ extern const struct xfs_defer_op_type xfs_exchmaps_defer_type;
 /*
  * Deferred operation item relogging limits.
  */
-#define XFS_DEFER_OPS_NR_INODES        2       /* join up to two inodes */
+
+/*
+ * Rename w/ parent pointers can require up to 5 inodes with deferred ops to
+ * be joined to the transaction: src_dp, target_dp, src_ip, target_ip, and wip.
+ * These inodes are locked in sorted order by their inode numbers
+ */
+#define XFS_DEFER_OPS_NR_INODES        5
 #define XFS_DEFER_OPS_NR_BUFS  2       /* join up to two buffers */
 
 /* Resources that must be held across a transaction roll. */
index 03dcb4ac04312de2ecf0968cdf54a1cc9154d0de..efd040094753fc5a949ea294e89af07b6c719afb 100644 (file)
@@ -418,7 +418,7 @@ xfs_lock_inumorder(
  * lock more than one at a time, lockdep will report false positives saying we
  * have violated locking orders.
  */
-static void
+void
 xfs_lock_inodes(
        struct xfs_inode        **ips,
        int                     inodes,
@@ -2802,7 +2802,7 @@ xfs_sort_for_rename(
        struct xfs_inode        **i_tab,/* out: sorted array of inodes */
        int                     *num_inodes)  /* in/out: inodes in array */
 {
-       int                     i, j;
+       int                     i;
 
        ASSERT(*num_inodes == __XFS_SORT_INODES);
        memset(i_tab, 0, *num_inodes * sizeof(struct xfs_inode *));
@@ -2824,17 +2824,26 @@ xfs_sort_for_rename(
                i_tab[i++] = wip;
        *num_inodes = i;
 
+       xfs_sort_inodes(i_tab, *num_inodes);
+}
+
+void
+xfs_sort_inodes(
+       struct xfs_inode        **i_tab,
+       unsigned int            num_inodes)
+{
+       int                     i, j;
+
+       ASSERT(num_inodes <= __XFS_SORT_INODES);
+
        /*
         * Sort the elements via bubble sort.  (Remember, there are at
         * most 5 elements to sort, so this is adequate.)
         */
-       for (i = 0; i < *num_inodes; i++) {
-               for (j = 1; j < *num_inodes; j++) {
-                       if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
-                               struct xfs_inode *temp = i_tab[j];
-                               i_tab[j] = i_tab[j-1];
-                               i_tab[j-1] = temp;
-                       }
+       for (i = 0; i < num_inodes; i++) {
+               for (j = 1; j < num_inodes; j++) {
+                       if (i_tab[j]->i_ino < i_tab[j-1]->i_ino)
+                               swap(i_tab[j], i_tab[j - 1]);
                }
        }
 }
index c74c48bc0945331d73bbde961dba2fe50aa512a5..a6da1ab8ab13624a0ffc09d24bf915269eb20990 100644 (file)
@@ -627,6 +627,8 @@ 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);
 void xfs_iunlock2_remapping(struct xfs_inode *ip1, struct xfs_inode *ip2);
 void xfs_bumplink(struct xfs_trans *tp, struct xfs_inode *ip);
+void xfs_lock_inodes(struct xfs_inode **ips, int inodes, uint lock_mode);
+void xfs_sort_inodes(struct xfs_inode **i_tab, unsigned int num_inodes);
 
 static inline bool
 xfs_inode_unlinked_incomplete(