XArray: Add extra debugging check to xas_lock and friends

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>
This commit is contained in:
Matthew Wilcox (Oracle) 2024-09-23 15:16:41 -04:00
parent c88414f56c
commit 6684aba078
2 changed files with 33 additions and 28 deletions

View 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.

View 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);