]> www.infradead.org Git - users/willy/xarray.git/commitdiff
XArray: Add extra debugging check to xas_lock and friends main
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 23 Sep 2024 19:16:41 +0000 (15:16 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 23 Sep 2024 19:16:41 +0000 (15:16 -0400)
While tracking down a recent bug, we discovered somewhere that had
forgotten to call xas_reset() before calling xas_lock().  Add a debug
check to be sure that doesn't happen in future.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
include/linux/xarray.h
lib/xarray.c

index 0b618ec04115fc3993bf33a7c358632bef170fc9..9b26bdeb1ac00f2df7cbeaa4b0f296cddb93d2e7 100644 (file)
@@ -1407,16 +1407,44 @@ struct xa_state {
                        order - (order % XA_CHUNK_SHIFT),       \
                        (1U << (order % XA_CHUNK_SHIFT)) - 1)
 
+/**
+ * xas_invalid() - Is the xas in a retry or error state?
+ * @xas: XArray operation state.
+ *
+ * Return: %true if the xas cannot be used for operations.
+ */
+static inline bool xas_invalid(const struct xa_state *xas)
+{
+       return (unsigned long)xas->xa_node & 3;
+}
+
+/**
+ * xas_valid() - Is the xas a valid cursor into the array?
+ * @xas: XArray operation state.
+ *
+ * Return: %true if the xas can be used for operations.
+ */
+static inline bool xas_valid(const struct xa_state *xas)
+{
+       return !xas_invalid(xas);
+}
+
+static inline struct xa_state *XAS_INVALID(struct xa_state *xas)
+{
+       XA_NODE_BUG_ON(xas->xa_node, xas_valid(xas));
+       return xas;
+}
+
 #define xas_marked(xas, mark)  xa_marked((xas)->xa, (mark))
-#define xas_trylock(xas)       xa_trylock((xas)->xa)
-#define xas_lock(xas)          xa_lock((xas)->xa)
+#define xas_trylock(xas)       xa_trylock(XAS_INVALID(xas)->xa)
+#define xas_lock(xas)          xa_lock(XAS_INVALID(xas)->xa)
 #define xas_unlock(xas)                xa_unlock((xas)->xa)
-#define xas_lock_bh(xas)       xa_lock_bh((xas)->xa)
+#define xas_lock_bh(xas)       xa_lock_bh(XAS_INVALID(xas)->xa)
 #define xas_unlock_bh(xas)     xa_unlock_bh((xas)->xa)
-#define xas_lock_irq(xas)      xa_lock_irq((xas)->xa)
+#define xas_lock_irq(xas)      xa_lock_irq(XAS_INVALID(xas)->xa)
 #define xas_unlock_irq(xas)    xa_unlock_irq((xas)->xa)
 #define xas_lock_irqsave(xas, flags) \
-                               xa_lock_irqsave((xas)->xa, flags)
+                               xa_lock_irqsave(XAS_INVALID(xas)->xa, flags)
 #define xas_unlock_irqrestore(xas, flags) \
                                xa_unlock_irqrestore((xas)->xa, flags)
 
@@ -1445,28 +1473,6 @@ static inline void xas_set_err(struct xa_state *xas, long err)
        xas->xa_node = XA_ERROR(err);
 }
 
-/**
- * xas_invalid() - Is the xas in a retry or error state?
- * @xas: XArray operation state.
- *
- * Return: %true if the xas cannot be used for operations.
- */
-static inline bool xas_invalid(const struct xa_state *xas)
-{
-       return (unsigned long)xas->xa_node & 3;
-}
-
-/**
- * xas_valid() - Is the xas a valid cursor into the array?
- * @xas: XArray operation state.
- *
- * Return: %true if the xas can be used for operations.
- */
-static inline bool xas_valid(const struct xa_state *xas)
-{
-       return !xas_invalid(xas);
-}
-
 /**
  * xas_is_node() - Does the xas point to a node?
  * @xas: XArray operation state.
index 2da34b84ac46623153983a889420774c292f49d7..1c612ae20a451da439221aeeebb21680b55eb4ef 100644 (file)
@@ -2243,7 +2243,6 @@ void xa_destroy(struct xarray *xa)
        unsigned long flags;
        void *entry;
 
-       xas.xa_node = NULL;
        xas_lock_irqsave(&xas, flags);
        entry = xa_head_locked(xa);
        RCU_INIT_POINTER(xa->xa_head, NULL);