]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: don't create one lockdep class per RTG xfs-per-rtg-inodes
authorChristoph Hellwig <hch@lst.de>
Tue, 16 Jul 2024 14:16:52 +0000 (16:16 +0200)
committerChristoph Hellwig <hch@lst.de>
Wed, 17 Jul 2024 07:30:51 +0000 (09:30 +0200)
lockdep_unregister_key is rather expensive because it does a
synchronize_rcu.  To avoid slowdowns with lots of RTGs try to avoid
using it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_rtgroup.c
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/xfs_inode.h
fs/xfs/xfs_iops.c
fs/xfs/xfs_iops.h
fs/xfs/xfs_rtalloc.c

index e48f8ffd18a5043f63bf1f733a7272af121ce955..fababe13a8c7b59af7f6569da1c702455fc7610f 100644 (file)
@@ -166,8 +166,6 @@ xfs_initialize_rtgroups(
                /* Place kernel structure only init below this point. */
                spin_lock_init(&rtg->rtg_state_lock);
                init_waitqueue_head(&rtg->rtg_active_wq);
-               memset(&rtg->lock_class, 0, sizeof(rtg->lock_class));
-               lockdep_register_key(&rtg->lock_class);
                xfs_defer_drain_init(&rtg->rtg_intents_drain);
                xfs_hooks_init(&rtg->rtg_rmap_update_hooks);
 #endif /* __KERNEL__ */
@@ -210,7 +208,6 @@ xfs_free_unused_rtgroup_range(
                if (!rtg)
                        break;
 #ifdef __KERNEL__
-               lockdep_unregister_key(&rtg->lock_class);
                xfs_defer_drain_free(&rtg->rtg_intents_drain);
 #endif
                kfree(rtg);
@@ -247,7 +244,6 @@ xfs_free_rtgroups(
                ASSERT(rtg);
                XFS_IS_CORRUPT(mp, atomic_read(&rtg->rtg_ref) != 0);
 #ifdef __KERNEL__
-               lockdep_unregister_key(&rtg->lock_class);
                xfs_defer_drain_free(&rtg->rtg_intents_drain);
 #endif
 
@@ -525,6 +521,46 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[] = {
        },
 };
 
+#ifdef CONFIG_PROVE_LOCKING
+static struct lock_class_key xfs_rtg_lock_class;
+
+static int
+xfs_rtg_ilock_cmp_fn(
+       const struct lockdep_map        *m1,
+       const struct lockdep_map        *m2)
+{
+       const struct xfs_inode *ip1 =
+               container_of(m1, struct xfs_inode, i_lock.dep_map);
+       const struct xfs_inode *ip2 =
+               container_of(m2, struct xfs_inode, i_lock.dep_map);
+
+       if (ip1->i_rgno < ip2->i_rgno)
+               return -1;
+       if (ip1->i_rgno > ip2->i_rgno)
+               return 1;
+       return 0;
+}
+
+/*
+ * Most of the time each of the RTG inode locks is only taken one at a time.
+ * But when committing deferred ops more than one of a kind can be taken.
+ * As the RTG will be committed in rgno order there is not potential for
+ * deadlocks, and the code here is needed to tell lockdep about this order.
+ */
+static inline void
+xfs_rtg_ilock_lockdep_setup(
+       struct xfs_inode        *ip,
+       xfs_rgnumber_t          rgno,
+       enum xfs_rtg_inodes     type)
+{
+       ip->i_rgno = rgno;
+       lockdep_set_class_and_subclass(&ip->i_lock, &xfs_rtg_lock_class, type);
+       lock_set_cmp_fn(&ip->i_lock, xfs_rtg_ilock_cmp_fn, NULL);
+}
+#else
+#define xfs_rtg_ilock_lockdep_setup(ip, rgno, type)    do { } while (0)
+#endif /* CONFIG_PROVE_LOCKING */
+
 const char *
 xfs_rtginode_name(
        enum xfs_rtg_inodes     type)
@@ -576,11 +612,7 @@ xfs_rtginode_load(
                return -EFSCORRUPTED;
        }
 
-       /*
-        * Each realtime allocation group has a lockdep class key for the metadata
-        * inodes.  Each metadata inode in a group gets its own subclass.
-        */
-       lockdep_set_class_and_subclass(&ip->i_lock, &rtg->lock_class, type);
+       xfs_rtg_ilock_lockdep_setup(ip, rtg->rtg_rgno, type);
        rtg->rtg_inodes[type] = ip;
        return 0;
 }
@@ -613,7 +645,7 @@ xfs_rtginode_create(
        if (error)
                return error;
 
-       lockdep_set_class_and_subclass(&upd.ip->i_lock, &rtg->lock_class, type);
+       xfs_rtg_ilock_lockdep_setup(upd.ip, rtg->rtg_rgno, type);
 
        error = ops->create(rtg, upd.ip, upd.tp, init);
        if (error)
index e8d76a818e07db3b3cdb2e4a0b1032c7f123a957..ab44b9ccf1d812e28d7d4d09279245d55aed21bc 100644 (file)
@@ -50,8 +50,6 @@ struct xfs_rtgroup {
        /* -- kernel only structures below this line -- */
        spinlock_t              rtg_state_lock;
 
-       struct lock_class_key   lock_class;
-
        /*
         * We use xfs_drain to track the number of deferred log intent items
         * that have been queued (but not yet processed) so that waiters (e.g.
index 67073dc7b712c59370194de2f3384cb69db33ccc..655f99f4ff7ca39550b45fef480d8d748c790792 100644 (file)
@@ -57,7 +57,9 @@ typedef struct xfs_inode {
        uint64_t                i_delayed_blks; /* count of delay alloc blks */
        /* Space that has been set aside to root a btree in this file. */
        uint64_t                i_meta_resv_asked;
-
+#ifdef CONFIG_PROVE_LOCKING
+       xfs_rgnumber_t          i_rgno;
+#endif
        xfs_fsize_t             i_disk_size;    /* number of bytes in file */
        xfs_rfsblock_t          i_nblocks;      /* # of direct & btree blocks */
        prid_t                  i_projid;       /* owner's project id */
index b1e8b1eb75b6615cd2e9d41a1da0d2500a39bd71..9c8c23beec61d8f919fd066b84a6d8c44f8d79c9 100644 (file)
@@ -1272,7 +1272,7 @@ xfs_diflags_to_iflags(
        inode->i_flags |= flags;
 }
 
-void
+static void
 xfs_setup_metadata_inode_lock_class(
        struct xfs_inode        *ip)
 {
index 1325112347611364a5f4fdb33a6d8b604eb3efaf..3c1a2605ffd2b8778ad25eb0b36819adea8673ca 100644 (file)
@@ -20,6 +20,4 @@ extern void xfs_setup_inode(struct xfs_inode *ip);
 extern void xfs_setup_iops(struct xfs_inode *ip);
 extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init);
 
-void xfs_setup_metadata_inode_lock_class(struct xfs_inode *ip);
-
 #endif /* __XFS_IOPS_H__ */
index 628e632a5266bc5389b30df4353346b05400d482..92adc7df47e537fa445ab20a5af472212a569eae 100644 (file)
@@ -944,17 +944,8 @@ static inline void
 xfs_rtgroup_irele(
        struct xfs_inode        **ipp)
 {
-       struct xfs_inode        *ip = *ipp;
-
-       if (!ip)
-               return;
-
-       /*
-        * Detach from the rtgroup's dynamic lockdep class key before we lose
-        * access to the inode entirely.
-        */
-       xfs_setup_metadata_inode_lock_class(ip);
-       xfs_irele(ip);
+       if (*ipp)
+               xfs_irele(*ipp);
        *ipp = NULL;
 }