diff mbox series

[for-next,1/2] RDMA/core: Support drivers use of rcu locking

Message ID 20230718175943.16734-2-rpearsonhpe@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Jason Gunthorpe
Headers show
Series Enable rcu locking of verbs objects | expand

Commit Message

Bob Pearson July 18, 2023, 5:59 p.m. UTC
This patch allows drivers to optionally include struct rcu_head
in their private object data structs and have rdma-core use kfree_rcu
to free the objects.

The offsets of the rcu_heads are stored in fields in struct
ib_device_ops and a macro RDMA_KFREE_RCU is introduced which calls
(an open coded) kfree_rcu instead of kfree if the value is non-
zero. Currently the supported object types are AH, QP and MW.

Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
---
 drivers/infiniband/core/uverbs_main.c |  2 +-
 drivers/infiniband/core/verbs.c       |  6 +++---
 include/rdma/ib_verbs.h               | 24 ++++++++++++++++++++++++
 3 files changed, 28 insertions(+), 4 deletions(-)

Comments

Jason Gunthorpe Aug. 9, 2023, 7:10 p.m. UTC | #1
On Tue, Jul 18, 2023 at 12:59:43PM -0500, Bob Pearson wrote:
> This patch allows drivers to optionally include struct rcu_head
> in their private object data structs and have rdma-core use kfree_rcu
> to free the objects.
> 
> The offsets of the rcu_heads are stored in fields in struct
> ib_device_ops and a macro RDMA_KFREE_RCU is introduced which calls
> (an open coded) kfree_rcu instead of kfree if the value is non-
> zero. Currently the supported object types are AH, QP and MW.
> 
> Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
> ---
>  drivers/infiniband/core/uverbs_main.c |  2 +-
>  drivers/infiniband/core/verbs.c       |  6 +++---
>  include/rdma/ib_verbs.h               | 24 ++++++++++++++++++++++++
>  3 files changed, 28 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
> index 7c9c79c13941..50497e550f18 100644
> --- a/drivers/infiniband/core/uverbs_main.c
> +++ b/drivers/infiniband/core/uverbs_main.c
> @@ -112,7 +112,7 @@ int uverbs_dealloc_mw(struct ib_mw *mw)
>  		return ret;
>  
>  	atomic_dec(&pd->usecnt);
> -	kfree(mw);
> +	RDMA_KFREE_RCU(mw);
>  	return ret;
>  }
>  
> diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
> index b99b3cc283b6..a49ae8c52c66 100644
> --- a/drivers/infiniband/core/verbs.c
> +++ b/drivers/infiniband/core/verbs.c
> @@ -982,7 +982,7 @@ int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
>  	if (sgid_attr)
>  		rdma_put_gid_attr(sgid_attr);
>  
> -	kfree(ah);
> +	RDMA_KFREE_RCU(ah);
>  	return ret;
>  }
>  EXPORT_SYMBOL(rdma_destroy_ah_user);
> @@ -1970,7 +1970,7 @@ int ib_close_qp(struct ib_qp *qp)
>  	atomic_dec(&real_qp->usecnt);
>  	if (qp->qp_sec)
>  		ib_close_shared_qp_security(qp->qp_sec);
> -	kfree(qp);
> +	RDMA_KFREE_RCU(qp);
>  
>  	return 0;
>  }
> @@ -2041,7 +2041,7 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
>  		ib_destroy_qp_security_end(sec);
>  
>  	rdma_restrack_del(&qp->res);
> -	kfree(qp);
> +	RDMA_KFREE_RCU(qp);
>  	return ret;
>  }
>  EXPORT_SYMBOL(ib_destroy_qp_user);
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 1e7774ac808f..616e9e54a733 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -2684,8 +2684,32 @@ struct ib_device_ops {
>  	DECLARE_RDMA_OBJ_SIZE(ib_srq);
>  	DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
>  	DECLARE_RDMA_OBJ_SIZE(ib_xrcd);
> +
> +	/* if non-zero holds offset of rcu_head in object */
> +	ssize_t rcu_offset_ah;
> +	ssize_t rcu_offset_qp;
> +	ssize_t rcu_offset_mw;

Just size_t, this isn't negative

> +static inline void __rdma_kfree_rcu(void *obj, ssize_t rcu_offset)

Here too

Jason
diff mbox series

Patch

diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 7c9c79c13941..50497e550f18 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -112,7 +112,7 @@  int uverbs_dealloc_mw(struct ib_mw *mw)
 		return ret;
 
 	atomic_dec(&pd->usecnt);
-	kfree(mw);
+	RDMA_KFREE_RCU(mw);
 	return ret;
 }
 
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index b99b3cc283b6..a49ae8c52c66 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -982,7 +982,7 @@  int rdma_destroy_ah_user(struct ib_ah *ah, u32 flags, struct ib_udata *udata)
 	if (sgid_attr)
 		rdma_put_gid_attr(sgid_attr);
 
-	kfree(ah);
+	RDMA_KFREE_RCU(ah);
 	return ret;
 }
 EXPORT_SYMBOL(rdma_destroy_ah_user);
@@ -1970,7 +1970,7 @@  int ib_close_qp(struct ib_qp *qp)
 	atomic_dec(&real_qp->usecnt);
 	if (qp->qp_sec)
 		ib_close_shared_qp_security(qp->qp_sec);
-	kfree(qp);
+	RDMA_KFREE_RCU(qp);
 
 	return 0;
 }
@@ -2041,7 +2041,7 @@  int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
 		ib_destroy_qp_security_end(sec);
 
 	rdma_restrack_del(&qp->res);
-	kfree(qp);
+	RDMA_KFREE_RCU(qp);
 	return ret;
 }
 EXPORT_SYMBOL(ib_destroy_qp_user);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 1e7774ac808f..616e9e54a733 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2684,8 +2684,32 @@  struct ib_device_ops {
 	DECLARE_RDMA_OBJ_SIZE(ib_srq);
 	DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
 	DECLARE_RDMA_OBJ_SIZE(ib_xrcd);
+
+	/* if non-zero holds offset of rcu_head in object */
+	ssize_t rcu_offset_ah;
+	ssize_t rcu_offset_qp;
+	ssize_t rcu_offset_mw;
+
 };
 
+/* drivers may optionally use rcu locking on verbs objects
+ * by including struct rcu_head in their private data and
+ * setting rcu_offset_xx in the ib_driver_ops struct where
+ * xx is one of ah, qp or mw.
+ */
+static inline void __rdma_kfree_rcu(void *obj, ssize_t rcu_offset)
+{
+	if (rcu_offset)
+		kvfree_call_rcu((struct rcu_head *)((u8 *)obj + rcu_offset),
+				obj);
+	else
+		kfree(obj);
+}
+
+/* obj must be one of ah, qp, or mw */
+#define RDMA_KFREE_RCU(obj) __rdma_kfree_rcu(obj,		\
+				obj->device->ops.rcu_offset_##obj)
+
 struct ib_core_device {
 	/* device must be the first element in structure until,
 	 * union of ib_core_device and device exists in ib_device.