diff mbox series

[for-next,v14,09/10] RDMA/rxe: Convert read side locking to rcu

Message ID 20220421014042.26985-10-rpearsonhpe@gmail.com (mailing list archive)
State Superseded
Headers show
Series Fix race conditions in rxe_pool | expand

Commit Message

Bob Pearson April 21, 2022, 1:40 a.m. UTC
Use rcu_read_lock() for protecting read side operations in rxe_pool.c.
Convert write side locking to use plain spin_lock().

Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
---
 drivers/infiniband/sw/rxe/rxe_pool.c | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

Comments

Jason Gunthorpe May 9, 2022, 11:58 a.m. UTC | #1
On Wed, Apr 20, 2022 at 08:40:42PM -0500, Bob Pearson wrote:

> @@ -217,16 +216,15 @@ int __rxe_cleanup(struct rxe_pool_elem *elem)
>  	struct rxe_pool *pool = elem->pool;
>  	struct xarray *xa = &pool->xa;
>  	static int timeout = RXE_POOL_TIMEOUT;
> -	unsigned long flags;
>  	int ret, err = 0;
>  	void *xa_ret;
>  
> +	WARN_ON(!in_task());

This should be might_sleep() which will show up any held spinlock that
Zhu was talking about.

There is definately some possible cases like that in the AH mess,
RDMA_DESTROY_AH_SLEEPABLE for instance is not handled, and the error
unwind during AH ceration, for example.

But that is just more of that AH mess that needs fixing, and isn't
related to RCU. It needs an atomic version of rxe_cleanup() too.

Jason
diff mbox series

Patch

diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
index f5380b6bdea2..661e0af522a9 100644
--- a/drivers/infiniband/sw/rxe/rxe_pool.c
+++ b/drivers/infiniband/sw/rxe/rxe_pool.c
@@ -191,16 +191,15 @@  void *rxe_pool_get_index(struct rxe_pool *pool, u32 index)
 {
 	struct rxe_pool_elem *elem;
 	struct xarray *xa = &pool->xa;
-	unsigned long flags;
 	void *obj;
 
-	xa_lock_irqsave(xa, flags);
+	rcu_read_lock();
 	elem = xa_load(xa, index);
 	if (elem && kref_get_unless_zero(&elem->ref_cnt))
 		obj = elem->obj;
 	else
 		obj = NULL;
-	xa_unlock_irqrestore(xa, flags);
+	rcu_read_unlock();
 
 	return obj;
 }
@@ -217,16 +216,15 @@  int __rxe_cleanup(struct rxe_pool_elem *elem)
 	struct rxe_pool *pool = elem->pool;
 	struct xarray *xa = &pool->xa;
 	static int timeout = RXE_POOL_TIMEOUT;
-	unsigned long flags;
 	int ret, err = 0;
 	void *xa_ret;
 
+	WARN_ON(!in_task());
+
 	/* erase xarray entry to prevent looking up
 	 * the pool elem from its index
 	 */
-	xa_lock_irqsave(xa, flags);
-	xa_ret = __xa_erase(xa, elem->index);
-	xa_unlock_irqrestore(xa, flags);
+	xa_ret = xa_erase(xa, elem->index);
 	WARN_ON(xa_err(xa_ret));
 
 	/* if this is the last call to rxe_put complete the
@@ -251,7 +249,7 @@  int __rxe_cleanup(struct rxe_pool_elem *elem)
 		pool->cleanup(elem);
 
 	if (pool->flags & RXE_POOL_ALLOC)
-		kfree(elem->obj);
+		kfree_rcu(elem->obj);
 
 	atomic_dec(&pool->num_elem);
 
@@ -270,12 +268,8 @@  int __rxe_put(struct rxe_pool_elem *elem)
 
 void __rxe_finalize(struct rxe_pool_elem *elem)
 {
-	struct xarray *xa = &elem->pool->xa;
-	unsigned long flags;
-	void *ret;
-
-	xa_lock_irqsave(xa, flags);
-	ret = __xa_store(&elem->pool->xa, elem->index, elem, GFP_KERNEL);
-	xa_unlock_irqrestore(xa, flags);
-	WARN_ON(xa_err(ret));
+	void *xa_ret;
+
+	xa_ret = xa_store(&elem->pool->xa, elem->index, elem, GFP_KERNEL);
+	WARN_ON(xa_err(xa_ret));
 }