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 |
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 --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.
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(-)