]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: add a lockdep class key for rtgroup inodes
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:11:51 +0000 (21:11 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 31 Jul 2024 01:46:54 +0000 (18:46 -0700)
Add a dynamic lockdep class key for rtgroup inodes.  This will enable
lockdep to deduce inconsistencies in the rtgroup metadata ILOCK locking
order.  Each class can have 8 subclasses, and for now we will only have
2 inodes per group.  This enables rtgroup order and inode order checks
when nesting ILOCKs.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/xfs_rtgroup.c

index 0f1b008af89d2357573c5b0db58b67a8b67556b5..c6208acf7421e062bbdca1fc0cc03c01056c1304 100644 (file)
@@ -470,3 +470,55 @@ xfs_rtgroup_get_geometry(
        xfs_rtgroup_geom_health(rtg, rgeo);
        return 0;
 }
+
+#ifdef CONFIG_PROVE_LOCKING
+static struct lock_class_key xfs_rtginode_lock_class;
+
+static int
+xfs_rtginode_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_projid < ip2->i_projid)
+               return -1;
+       if (ip1->i_projid > ip2->i_projid)
+               return 1;
+       return 0;
+}
+
+static inline void
+xfs_rtginode_ilock_print_fn(
+       const struct lockdep_map        *m)
+{
+       const struct xfs_inode *ip =
+               container_of(m, struct xfs_inode, i_lock.dep_map);
+
+       printk(KERN_CONT " rgno=%u", ip->i_projid);
+}
+
+/*
+ * Most of the time each of the RTG inode locks are only taken one at a time.
+ * But when committing deferred ops, more than one of a kind can be taken.
+ * However, deferred rt ops will be committed in rgno order so there is no
+ * potential for deadlocks.  The code here is needed to tell lockdep about this
+ * order.
+ */
+static inline void
+xfs_rtginode_lockdep_setup(
+       struct xfs_inode        *ip,
+       xfs_rgnumber_t          rgno,
+       enum xfs_rtg_inodes     type)
+{
+       lockdep_set_class_and_subclass(&ip->i_lock, &xfs_rtginode_lock_class,
+                       type);
+       lock_set_cmp_fn(&ip->i_lock, xfs_rtginode_ilock_cmp_fn,
+                       xfs_rtginode_ilock_print_fn);
+}
+#else
+#define xfs_rtginode_lockdep_setup(ip, rgno, type)     do { } while (0)
+#endif /* CONFIG_PROVE_LOCKING */