Track memory allocation with restrack DB help
Subsystems (2)
cover Track memory allocation with restrack DB help
From: Leon Romanovsky <[email protected]>
Changelog:
v1:
* Fixed rebase error, deleted second assignment of qp_type.
* Rebased code on latests rdma-next, the changes in cma.c caused to change in patch "RDMA/cma: Delete from restrack DB after successful destroy".
* Dropped patch of port assignment, it is already done as part of this series.
* I didn't add @calller description, regular users should not use _named() funciton.
v0: https://lore.kernel.org/lkml/[email protected]
----------------------------------------------------------------------------------
Hi,
The resource tracker has built-in kref counter to synchronize object release. It makes restrack perfect choice to be responsible for the memory lifetime of any object in which restrack entry is embedded.
In order to make it, the restrack was changed to be mandatory and all callers of rdma_restrack_add() started to rely on result returned from that call. Being mandatory means that all objects specific to restrack type must be tracked.
Before this series, the restrack and rdmatool were aid tools in debug session of user space applications, this caused to some of the functionality to be left behind, like support XRC QPs, device memory MRs and QP0/QP1 in multi-port devices.
This series fixes all mentioned above without extending rdmatool at all.
Thanks
Leon Romanovsky (13):
RDMA/cma: Delete from restrack DB after successful destroy RDMA/mlx5: Don't call to restrack recursively RDMA/restrack: Count references to the verbs objects RDMA/restrack: Simplify restrack tracking in kernel flows RDMA/restrack: Improve readability in task name management RDMA/cma: Be strict with attaching to CMA device RDMA/core: Allow drivers to disable restrack DB RDMA/counter: Combine allocation and bind logic RDMA/restrack: Store all special QPs in restrack DB RDMA/restrack: Make restrack DB mandatory for IB objects RDMA/restrack: Support all QP types
RDMA/core: Track device memory MRs
RDMA/restrack: Drop valid restrack field as source of ambiguity
drivers/infiniband/core/cma.c | 225 +++++++++++------- drivers/infiniband/core/core_priv.h | 39 ++- drivers/infiniband/core/counters.c | 178 +++++++------- drivers/infiniband/core/cq.c | 24 +- drivers/infiniband/core/rdma_core.c | 3 +- drivers/infiniband/core/restrack.c | 208 ++++++++-------- drivers/infiniband/core/restrack.h | 10 +- drivers/infiniband/core/uverbs_cmd.c | 50 +++- drivers/infiniband/core/uverbs_std_types_cq.c | 12 +- drivers/infiniband/core/uverbs_std_types_mr.c | 10 + drivers/infiniband/core/uverbs_std_types_qp.c | 4 +- drivers/infiniband/core/verbs.c | 91 +++++-- drivers/infiniband/hw/mlx5/gsi.c | 16 +- drivers/infiniband/hw/mlx5/qp.c | 2 +- include/rdma/ib_verbs.h | 10 +- include/rdma/restrack.h | 46 ++-- 16 files changed, 537 insertions(+), 391 deletions(-)
--
2.26.2
PATCH 1/13 RDMA/cma: Delete from restrack DB after successful destroy
From: Leon Romanovsky <[email protected]>
Update the code to have similar destroy pattern like other IB objects.
This change create asymmetry to the rdma_id_private create flow to make sure that memory is managed by restrack.
--- drivers/infiniband/core/cma.c | 3 +-- drivers/infiniband/core/restrack.c | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-)
drivers/infiniband/core/cma.c +1 -2
@@ -1821,7 +1821,6 @@ static void _destroy_id(struct rdma_id_private *id_priv, {cma_cancel_operation (id_priv, state); -rdma_restrack_del (&id_priv->res);if (id_priv->cma_dev) {if (rdma_cap_ib_cm (id_priv->id.device,1 )) {if (id_priv->cm_id.ib)
@@ -1847,6 +1846,7 @@ static void _destroy_id(struct rdma_id_private *id_priv,rdma_put_gid_attr (id_priv->id.route.addr.dev_addr.sgid_attr);put_net (id_priv->id.route.addr.dev_addr.net); +rdma_restrack_del (&id_priv->res);kfree (id_priv); }
@@ -3728,7 +3728,6 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)return 0 ; err2: -rdma_restrack_del (&id_priv->res);if (id_priv->cma_dev)cma_release_dev (id_priv); err1:
drivers/infiniband/core/restrack.c +3 -0
@@ -330,6 +330,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id); +if (!old && + (res->type ==RDMA_RESTRACK_MR || res->type ==RDMA_RESTRACK_QP )) +return ;WARN_ON (old != res); res->valid = false;
Signature · 1 line
2.26.2
Jason Gunthorpe
maintainerRe: [PATCH rdma-next v1 01/13] RDMA/cma: Delete from restrack DB after successful destroy
drivers/infiniband/core/restrack.c void rdma_restrack_del(struct rdma_restrack_entry *res) · line 337
Quoted 12 lines · Leon Romanovsky
drivers/infiniband/core/restrack.c +4
-0+++ b/drivers/infiniband/core/restrack.c@@ -330,6 +330,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id); +if (!old && + (res->type ==RDMA_RESTRACK_MR || res->type ==RDMA_RESTRACK_QP )) +return ;WARN_ON (old != res); res->valid = false;
What is this for? It doesn't seem to have anything to do with the cm change.
Calling rdma_testrack_del() on a yet to be added ID should early exit from !valid right?
Jason
Re: [PATCH rdma-next v1 01/13] RDMA/cma: Delete from restrack DB after successful destroy
Quoted 7 lines · Jason Gunthorpe
Quoted 6 lines · Leon Romanovsky
drivers/infiniband/core/restrack.c +1
-0+++ b/drivers/infiniband/core/restrack.c@@ -330,6 +330,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) rt = &dev->res[res->type];
Quoted 9 lines
drivers/infiniband/core/restrack.c void rdma_restrack_del(struct rdma_restrack_entry *res) · line 337
Quoted 6 lines
drivers/infiniband/core/restrack.c +3
-0old =xa_erase (&rt->xa, res->id); +if (!old && + (res->type ==RDMA_RESTRACK_MR || res->type ==RDMA_RESTRACK_QP )) +return ;WARN_ON (old != res); res->valid = false;What is this for? It doesn't seem to have anything to do with the cm change.
Yes, it is a mix between two patches, will fix.
Quoted 3 lines
Calling
rdma_testrack_del()on a yet to be added ID should early exit from !valid right?
QP and MR are not converted yet to ib_core allocation, and they don't have wait_for_completion() support yet, this is why we need to ball out early.
Quoted 2 lines
Jason
PATCH 2/13 RDMA/mlx5: Don't call to restrack recursively
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
The restrack is going to manage memory of all IB objects and must be called before object is created. GSI QP in the mlx5_ib separated between creating dummy interface and HW object beneath. This was achieved by double call to ib_create_qp().
In order to skip such reentry call to internal driver create_qp code.
--- drivers/infiniband/hw/mlx5/gsi.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/infiniband/hw/mlx5/gsi.c +14 -2
@@ -182,13 +182,25 @@ struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd, hw_init_attr.cap.max_send_sge =0 ; hw_init_attr.cap.max_inline_data =0 ; } - gsi->rx_qp =ib_create_qp (pd, &hw_init_attr); + + gsi->rx_qp =mlx5_ib_create_qp (pd, &hw_init_attr,NULL );if (IS_ERR (gsi->rx_qp)) {mlx5_ib_warn (dev,"unable to create hardware GSI QP. error %ld\n" ,PTR_ERR (gsi->rx_qp)); ret =PTR_ERR (gsi->rx_qp); goto err_destroy_cq; } + gsi->rx_qp->device = pd->device; + gsi->rx_qp->pd = pd; + gsi->rx_qp->real_qp = gsi->rx_qp; + + gsi->rx_qp->qp_type = hw_init_attr.qp_type; + gsi->rx_qp->send_cq = hw_init_attr.send_cq; + gsi->rx_qp->recv_cq = hw_init_attr.recv_cq; + gsi->rx_qp->event_handler = hw_init_attr.event_handler; +spin_lock_init (&gsi->rx_qp->mr_lock); +INIT_LIST_HEAD (&gsi->rx_qp->rdma_mrs); +INIT_LIST_HEAD (&gsi->rx_qp->sig_mrs); dev->devr.ports[init_attr->port_num -1 ].gsi = gsi;
@@ -219,7 +231,7 @@ int mlx5_ib_gsi_destroy_qp(struct ib_qp *qp)mlx5_ib_dbg (dev,"destroying GSI QP\n" );mutex_lock (&dev->devr.mutex); - ret =ib_destroy_qp (gsi->rx_qp); + ret =mlx5_ib_destroy_qp (gsi->rx_qp,NULL );if (ret) {mlx5_ib_warn (dev,"unable to destroy hardware GSI QP. error %d\n" , ret);
Signature · 1 line
2.26.2
PATCH 3/13 RDMA/restrack: Count references to the verbs objects
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Refactor the restrack code to make sure that kref inside restrack entry properly kref the object in which it is embedded. This slight change is needed for future conversions of MR and QP which are refcounted before the release and kfree.
The ideal flow from ib_core perspective as follows:
* Allocate ib_* structure with rdma_zalloc_*.
* Set everything that is known to ib_core to that newly created object.
* Initialize kref with restrack help
* Call to driver specific allocation functions.
* Insert into restrack DB
....
* Return and release restrack with restrack_put.
--- drivers/infiniband/core/cma.c | 5 ++- drivers/infiniband/core/core_priv.h | 3 +- drivers/infiniband/core/counters.c | 6 ++- drivers/infiniband/core/cq.c | 7 ++-- drivers/infiniband/core/restrack.c | 40 ++++++++++++++----- drivers/infiniband/core/restrack.h | 3 ++ drivers/infiniband/core/uverbs_cmd.c | 13 ++++-- drivers/infiniband/core/uverbs_std_types_cq.c | 4 +- drivers/infiniband/core/verbs.c | 18 +++++---- include/rdma/restrack.h | 7 ---- 10 files changed, 68 insertions(+), 38 deletions(-)
drivers/infiniband/core/cma.c +3 -2
@@ -855,8 +855,6 @@ struct rdma_cm_id *__rdma_create_id(struct net *net,if (!id_priv)return ERR_PTR (-ENOMEM ); -rdma_restrack_set_task (&id_priv->res, caller); - id_priv->res.type =RDMA_RESTRACK_CM_ID ; id_priv->state =RDMA_CM_IDLE ; id_priv->id.context = context; id_priv->id.event_handler = event_handler;
@@ -876,6 +874,9 @@ struct rdma_cm_id *__rdma_create_id(struct net *net, id_priv->id.route.addr.dev_addr.net =get_net (net); id_priv->seq_num &=0x00ffffff ; +rdma_restrack_new (&id_priv->res,RDMA_RESTRACK_CM_ID ); +rdma_restrack_set_task (&id_priv->res, caller); +return &id_priv->id; }EXPORT_SYMBOL (__rdma_create_id);
drivers/infiniband/core/core_priv.h +2 -1
@@ -44,6 +44,7 @@#include <rdma/ib_mad.h> #include <rdma/restrack.h> #include "mad_priv.h" +#include "restrack.h" /* Total number of ports combined across all struct ib_devices's */ #define RDMA_MAX_PORTS 8192
@@ -352,6 +353,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,INIT_LIST_HEAD (&qp->rdma_mrs);INIT_LIST_HEAD (&qp->sig_mrs); +rdma_restrack_new (&qp->res,RDMA_RESTRACK_QP );/* * We don't track XRC QPs for now, because they don't have PD * and more importantly they are created internaly by driver,
@@ -359,7 +361,6 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,*/ is_xrc = qp_type ==IB_QPT_XRC_INI || qp_type ==IB_QPT_XRC_TGT ;if ((qp_type <IB_QPT_MAX && !is_xrc) || qp_type ==IB_QPT_DRIVER ) { - qp->res.type =RDMA_RESTRACK_QP ;if (uobj)rdma_restrack_uadd (&qp->res);else
drivers/infiniband/core/counters.c +4 -2
@@ -80,8 +80,9 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, counter->device = dev; counter->port = port; - counter->res.type =RDMA_RESTRACK_COUNTER ; - counter->stats = dev->ops.counter_alloc_stats (counter); + +rdma_restrack_new (&counter->res,RDMA_RESTRACK_COUNTER ); + counter->stats = dev->ops.counter_alloc_stats (counter);if (!counter->stats) goto err_stats;
@@ -107,6 +108,7 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,mutex_unlock (&port_counter->lock);kfree (counter->stats); err_stats: +rdma_restrack_put (&counter->res);kfree (counter);return NULL ; }
drivers/infiniband/core/cq.c +3 -4
@@ -235,15 +235,13 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe,if (!cq->wc) goto out_free_cq; - cq->res.type =RDMA_RESTRACK_CQ ; +rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ );rdma_restrack_set_task (&cq->res, caller); ret = dev->ops.create_cq (cq, &cq_attr,NULL );if (ret) goto out_free_wc; -rdma_restrack_kadd (&cq->res); -rdma_dim_init (cq);switch (cq->poll_ctx) {
@@ -269,14 +267,15 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe, goto out_destroy_cq; } +rdma_restrack_kadd (&cq->res);trace_cq_alloc (cq, nr_cqe, comp_vector, poll_ctx);return cq; out_destroy_cq:rdma_dim_destroy (cq); -rdma_restrack_del (&cq->res); cq->device->ops.destroy_cq (cq,NULL ); out_free_wc: +rdma_restrack_put (&cq->res);kfree (cq->wc); out_free_cq:kfree (cq);
drivers/infiniband/core/restrack.c +30 -10
@@ -202,6 +202,21 @@ void rdma_restrack_attach_task(struct rdma_restrack_entry *res, res->task = task; } +/** +* rdma_restrack_new() - Initializes new restrack entry to allow _put() interface +* to release memory in fully automatic way. +* @res - Entry to initialize +* @type - REstrack type +*/ +void rdma_restrack_new (struct rdma_restrack_entry *res, +enum rdma_restrack_type type) +{ +kref_init (&res->kref); +init_completion (&res->comp); + res->type = type; +} +EXPORT_SYMBOL (rdma_restrack_new); +static void rdma_restrack_add (struct rdma_restrack_entry *res) {struct ib_device *dev =res_to_dev (res);
@@ -213,8 +228,6 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res) rt = &dev->res[res->type]; -kref_init (&res->kref); -init_completion (&res->comp);if (res->type ==RDMA_RESTRACK_QP ) {/* Special case to ensure that LQPN points to right QP */ struct ib_qp *qp = container_of(res, struct ib_qp, res);
@@ -305,6 +318,10 @@ static void restrack_release(struct kref *kref)struct rdma_restrack_entry *res; res = container_of(kref, struct rdma_restrack_entry, kref); +if (res->task) { +put_task_struct (res->task); + res->task =NULL ; + }complete (&res->comp); }
@@ -314,14 +331,23 @@ int rdma_restrack_put(struct rdma_restrack_entry *res) }EXPORT_SYMBOL (rdma_restrack_put); +/** +* rdma_restrack_del() - delete object from the reource tracking database +* @res: resource entry +*/ void rdma_restrack_del (struct rdma_restrack_entry *res) {struct rdma_restrack_entry *old;struct rdma_restrack_root *rt;struct ib_device *dev; -if (!res->valid) - goto out; +if (!res->valid) { +if (res->task) { +put_task_struct (res->task); + res->task =NULL ; + } +return ; + } dev =res_to_dev (res);if (WARN_ON (!dev))
@@ -338,11 +364,5 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)rdma_restrack_put (res);wait_for_completion (&res->comp); - -out: -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } }EXPORT_SYMBOL (rdma_restrack_del);
drivers/infiniband/core/restrack.h +3 -0
@@ -25,6 +25,9 @@ struct rdma_restrack_root {int rdma_restrack_init (struct ib_device *dev);void rdma_restrack_clean (struct ib_device *dev); +void rdma_restrack_del (struct rdma_restrack_entry *res); +void rdma_restrack_new (struct rdma_restrack_entry *res, +enum rdma_restrack_type type);void rdma_restrack_attach_task (struct rdma_restrack_entry *res,struct task_struct *task);#endif /* _RDMA_CORE_RESTRACK_H_ */
drivers/infiniband/core/uverbs_cmd.c +9 -4
@@ -218,10 +218,11 @@ int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs)if (!ucontext)return -ENOMEM ; - ucontext->res.type =RDMA_RESTRACK_CTX ; ucontext->device = ib_dev; ucontext->ufile = ufile;xa_init_flags (&ucontext->mmap_xa,XA_FLAGS_ALLOC ); + +rdma_restrack_new (&ucontext->res,RDMA_RESTRACK_CTX ); attrs->context = ucontext;return 0 ; }
@@ -313,6 +314,7 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs) err_uobj:rdma_alloc_abort_uobject (uobj, attrs, false); err_ucontext: +rdma_restrack_put (&attrs->context->res);kfree (attrs->context); attrs->context =NULL ;return ret;
@@ -439,8 +441,8 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) pd->device = ib_dev; pd->uobject = uobj;atomic_set (&pd->usecnt,0 ); - pd->res.type =RDMA_RESTRACK_PD ; +rdma_restrack_new (&pd->res,RDMA_RESTRACK_PD ); ret = ib_dev->ops.alloc_pd (pd, &attrs->driver_udata);if (ret) goto err_alloc;
@@ -453,6 +455,7 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)return uverbs_response (attrs, &resp,sizeof (resp)); err_alloc: +rdma_restrack_put (&pd->res);kfree (pd); err:uobj_alloc_abort (uobj, attrs);
@@ -742,8 +745,9 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) mr->sig_attrs =NULL ; mr->uobject = uobj;atomic_inc (&pd->usecnt); - mr->res.type =RDMA_RESTRACK_MR ; mr->iova = cmd.hca_va; + +rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR );rdma_restrack_uadd (&mr->res); uobj->object = mr;
@@ -994,8 +998,8 @@ static int create_cq(struct uverbs_attr_bundle *attrs, cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = ev_file ? &ev_file->ev_queue :NULL ;atomic_set (&cq->usecnt,0 ); - cq->res.type =RDMA_RESTRACK_CQ ; +rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free;
@@ -1013,6 +1017,7 @@ static int create_cq(struct uverbs_attr_bundle *attrs,return uverbs_response (attrs, &resp,sizeof (resp)); err_free: +rdma_restrack_put (&cq->res);kfree (cq); err_file:if (ev_file)
drivers/infiniband/core/uverbs_std_types_cq.c +3 -1
@@ -33,6 +33,7 @@#include <rdma/uverbs_std_types.h> #include "rdma_core.h" #include "uverbs.h" +#include "restrack.h" static int uverbs_free_cq(struct ib_uobject *uobject, enum rdma_remove_reason why,
@@ -123,8 +124,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)( cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = ev_file ? &ev_file->ev_queue :NULL ;atomic_set (&cq->usecnt,0 ); - cq->res.type =RDMA_RESTRACK_CQ ; +rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free;
@@ -139,6 +140,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(return ret; err_free: +rdma_restrack_put (&cq->res);kfree (cq); err_event_file:if (obj->uevent.event_file)
drivers/infiniband/core/verbs.c +11 -7
@@ -272,11 +272,12 @@ struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,atomic_set (&pd->usecnt,0 ); pd->flags = flags; - pd->res.type =RDMA_RESTRACK_PD ; +rdma_restrack_new (&pd->res,RDMA_RESTRACK_PD );rdma_restrack_set_task (&pd->res, caller); ret = device->ops.alloc_pd (pd,NULL );if (ret) { +rdma_restrack_put (&pd->res);kfree (pd);return ERR_PTR (ret); }
@@ -1996,11 +1997,13 @@ struct ib_cq *__ib_create_cq(struct ib_device *device, cq->event_handler = event_handler; cq->cq_context = cq_context;atomic_set (&cq->usecnt,0 ); - cq->res.type =RDMA_RESTRACK_CQ ; + +rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ );rdma_restrack_set_task (&cq->res, caller); ret = device->ops.create_cq (cq, cq_attr,NULL );if (ret) { +rdma_restrack_put (&cq->res);kfree (cq);return ERR_PTR (ret); }
@@ -2076,7 +2079,8 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mr->pd = pd; mr->dm =NULL ;atomic_inc (&pd->usecnt); - mr->res.type =RDMA_RESTRACK_MR ; + +rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR );rdma_restrack_kadd (&mr->res);return mr;
@@ -2156,11 +2160,11 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, mr->uobject =NULL ;atomic_inc (&pd->usecnt); mr->need_inval = false; - mr->res.type =RDMA_RESTRACK_MR ; -rdma_restrack_kadd (&mr->res); mr->type = mr_type; mr->sig_attrs =NULL ; +rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); +rdma_restrack_kadd (&mr->res); out:trace_mr_alloc (pd, mr_type, max_num_sg, mr);return mr;
@@ -2216,11 +2220,11 @@ struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd, mr->uobject =NULL ;atomic_inc (&pd->usecnt); mr->need_inval = false; - mr->res.type =RDMA_RESTRACK_MR ; -rdma_restrack_kadd (&mr->res); mr->type =IB_MR_TYPE_INTEGRITY ; mr->sig_attrs = sig_attrs; +rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); +rdma_restrack_kadd (&mr->res); out:trace_mr_integ_alloc (pd, max_num_data_sg, max_num_meta_sg, mr);return mr;
include/rdma/restrack.h +0 -7
@@ -110,13 +110,6 @@ int rdma_restrack_count(struct ib_device *dev,void rdma_restrack_kadd (struct rdma_restrack_entry *res);void rdma_restrack_uadd (struct rdma_restrack_entry *res); -/** -* rdma_restrack_del() - delete object from the reource tracking database -* @res: resource entry -* @type: actual type of object to operate -*/ -void rdma_restrack_del (struct rdma_restrack_entry *res); -/** * rdma_is_kernel_res() - check the owner of resource * @res: resource entry
Signature · 1 line
2.26.2
PATCH 4/13 RDMA/restrack: Simplify restrack tracking in kernel flows
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
There is no need to do an extra function indirection just to add restrack entry to the DB. This patch prepares the code to the future requirement of making restrack is mandatory for managing ib objects.
--- drivers/infiniband/core/cma.c | 2 +- drivers/infiniband/core/core_priv.h | 6 ++-- drivers/infiniband/core/counters.c | 2 +- drivers/infiniband/core/cq.c | 2 +- drivers/infiniband/core/restrack.c | 46 ++++------------------------- drivers/infiniband/core/restrack.h | 1 + drivers/infiniband/core/verbs.c | 13 ++++---- include/rdma/restrack.h | 1 - 8 files changed, 22 insertions(+), 51 deletions(-)
drivers/infiniband/core/cma.c +1 -1
@@ -468,7 +468,7 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,rdma_node_get_transport (cma_dev->device->node_type);list_add_tail (&id_priv->list, &cma_dev->id_list);if (id_priv->res.kern_name) -rdma_restrack_kadd (&id_priv->res); +rdma_restrack_add (&id_priv->res);else rdma_restrack_uadd (&id_priv->res);trace_cm_id_attach (id_priv, cma_dev->device);
drivers/infiniband/core/core_priv.h +4 -2
@@ -363,8 +363,10 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,if ((qp_type <IB_QPT_MAX && !is_xrc) || qp_type ==IB_QPT_DRIVER ) {if (uobj)rdma_restrack_uadd (&qp->res); -else -rdma_restrack_kadd (&qp->res); +else { +rdma_restrack_set_task (&qp->res, pd->res.kern_name); +rdma_restrack_add (&qp->res); + } }else qp->res.valid = false;
drivers/infiniband/core/counters.c +1 -1
@@ -252,7 +252,7 @@ static void rdma_counter_res_add(struct rdma_counter *counter, {if (rdma_is_kernel_res (&qp->res)) {rdma_restrack_set_task (&counter->res, qp->res.kern_name); -rdma_restrack_kadd (&counter->res); +rdma_restrack_add (&counter->res); }else {rdma_restrack_attach_task (&counter->res, qp->res.task);rdma_restrack_uadd (&counter->res);
drivers/infiniband/core/cq.c +1 -1
@@ -267,7 +267,7 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe, goto out_destroy_cq; } -rdma_restrack_kadd (&cq->res); +rdma_restrack_add (&cq->res);trace_cq_alloc (cq, nr_cqe, comp_vector, poll_ctx);return cq;
drivers/infiniband/core/restrack.c +6 -40
64 lines not on this page · raw message
drivers/infiniband/core/restrack.h +1 -0
@@ -25,6 +25,7 @@ struct rdma_restrack_root {int rdma_restrack_init (struct ib_device *dev);void rdma_restrack_clean (struct ib_device *dev); +void rdma_restrack_add (struct rdma_restrack_entry *res);void rdma_restrack_del (struct rdma_restrack_entry *res);void rdma_restrack_new (struct rdma_restrack_entry *res,enum rdma_restrack_type type);
drivers/infiniband/core/verbs.c +8 -5
@@ -281,7 +281,7 @@ struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,kfree (pd);return ERR_PTR (ret); } -rdma_restrack_kadd (&pd->res); +rdma_restrack_add (&pd->res);if (device->attrs.device_cap_flags &IB_DEVICE_LOCAL_DMA_LKEY ) pd->local_dma_lkey = device->local_dma_lkey;
@@ -2008,7 +2008,7 @@ struct ib_cq *__ib_create_cq(struct ib_device *device,return ERR_PTR (ret); } -rdma_restrack_kadd (&cq->res); +rdma_restrack_add (&cq->res);return cq; }EXPORT_SYMBOL (__ib_create_cq);
@@ -2081,7 +2081,8 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,atomic_inc (&pd->usecnt);rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_kadd (&mr->res); +rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_add (&mr->res);return mr; }
@@ -2164,7 +2165,8 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, mr->sig_attrs =NULL ;rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_kadd (&mr->res); +rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_add (&mr->res); out:trace_mr_alloc (pd, mr_type, max_num_sg, mr);return mr;
@@ -2224,7 +2226,8 @@ struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd, mr->sig_attrs = sig_attrs;rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_kadd (&mr->res); +rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_add (&mr->res); out:trace_mr_integ_alloc (pd, max_num_data_sg, max_num_meta_sg, mr);return mr;
include/rdma/restrack.h +0 -1
@@ -107,7 +107,6 @@ struct rdma_restrack_entry {int rdma_restrack_count (struct ib_device *dev,enum rdma_restrack_type type); -void rdma_restrack_kadd (struct rdma_restrack_entry *res);void rdma_restrack_uadd (struct rdma_restrack_entry *res);/**
Signature · 1 line
2.26.2
PATCH 5/13 RDMA/restrack: Improve readability in task name management
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Reduce ambiguity in interfaces to set resource names and manage struct task reference counters.
--- drivers/infiniband/core/cma.c | 15 ++-- drivers/infiniband/core/core_priv.h | 12 +-- drivers/infiniband/core/counters.c | 9 +-- drivers/infiniband/core/cq.c | 2 +- drivers/infiniband/core/restrack.c | 73 ++++++++++--------- drivers/infiniband/core/restrack.h | 6 +- drivers/infiniband/core/uverbs_cmd.c | 14 +++- drivers/infiniband/core/uverbs_std_types_cq.c | 4 +- drivers/infiniband/core/verbs.c | 10 +-- include/rdma/restrack.h | 11 --- 10 files changed, 75 insertions(+), 81 deletions(-)
drivers/infiniband/core/cma.c +9 -6
@@ -467,10 +467,13 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv, id_priv->id.route.addr.dev_addr.transport =rdma_node_get_transport (cma_dev->device->node_type);list_add_tail (&id_priv->list, &cma_dev->id_list); -if (id_priv->res.kern_name) -rdma_restrack_add (&id_priv->res); -else -rdma_restrack_uadd (&id_priv->res); +/* +* For example UCMA doesn't set kern_name and below function will +* attach to "current" task. +*/ +rdma_restrack_set_name (&id_priv->res, id_priv->res.kern_name); +rdma_restrack_add (&id_priv->res); +trace_cm_id_attach (id_priv, cma_dev->device); }
@@ -875,7 +878,7 @@ struct rdma_cm_id *__rdma_create_id(struct net *net, id_priv->seq_num &=0x00ffffff ;rdma_restrack_new (&id_priv->res,RDMA_RESTRACK_CM_ID ); -rdma_restrack_set_task (&id_priv->res, caller); +rdma_restrack_set_name (&id_priv->res, caller);return &id_priv->id; }
@@ -4160,7 +4163,7 @@ int __rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param,lockdep_assert_held (&id_priv->handler_mutex); -rdma_restrack_set_task (&id_priv->res, caller); +rdma_restrack_set_name (&id_priv->res, caller);if (READ_ONCE (id_priv->state) !=RDMA_CM_CONNECT )return -EINVAL ;
drivers/infiniband/core/core_priv.h +3 -9
@@ -361,15 +361,9 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,*/ is_xrc = qp_type ==IB_QPT_XRC_INI || qp_type ==IB_QPT_XRC_TGT ;if ((qp_type <IB_QPT_MAX && !is_xrc) || qp_type ==IB_QPT_DRIVER ) { -if (uobj) -rdma_restrack_uadd (&qp->res); -else { -rdma_restrack_set_task (&qp->res, pd->res.kern_name); -rdma_restrack_add (&qp->res); - } - }else - qp->res.valid = false; - +rdma_restrack_parent_name (&qp->res, &pd->res); +rdma_restrack_add (&qp->res); + }return qp; }
drivers/infiniband/core/counters.c +2 -7
@@ -250,13 +250,8 @@ static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp,static void rdma_counter_res_add (struct rdma_counter *counter,struct ib_qp *qp) { -if (rdma_is_kernel_res (&qp->res)) { -rdma_restrack_set_task (&counter->res, qp->res.kern_name); -rdma_restrack_add (&counter->res); - }else { -rdma_restrack_attach_task (&counter->res, qp->res.task); -rdma_restrack_uadd (&counter->res); - } +rdma_restrack_parent_name (&counter->res, &qp->res); +rdma_restrack_add (&counter->res); }static void counter_release (struct kref *kref)
drivers/infiniband/core/cq.c +1 -1
@@ -236,7 +236,7 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe, goto out_free_cq;rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); -rdma_restrack_set_task (&cq->res, caller); +rdma_restrack_set_name (&cq->res, caller); ret = dev->ops.create_cq (cq, &cq_attr,NULL );if (ret)
drivers/infiniband/core/restrack.c +38 -35
97 lines not on this page · raw message
drivers/infiniband/core/restrack.h +4 -2
@@ -29,6 +29,8 @@ void rdma_restrack_add(struct rdma_restrack_entry *res);void rdma_restrack_del (struct rdma_restrack_entry *res);void rdma_restrack_new (struct rdma_restrack_entry *res,enum rdma_restrack_type type); -void rdma_restrack_attach_task (struct rdma_restrack_entry *res, -struct task_struct *task); +void rdma_restrack_set_name (struct rdma_restrack_entry *res, +const char *caller); +void rdma_restrack_parent_name (struct rdma_restrack_entry *dst, +struct rdma_restrack_entry *parent);#endif /* _RDMA_CORE_RESTRACK_H_ */
drivers/infiniband/core/uverbs_cmd.c +10 -4
@@ -223,6 +223,7 @@ int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs)xa_init_flags (&ucontext->mmap_xa,XA_FLAGS_ALLOC );rdma_restrack_new (&ucontext->res,RDMA_RESTRACK_CTX ); +rdma_restrack_set_name (&ucontext->res,NULL ); attrs->context = ucontext;return 0 ; }
@@ -251,7 +252,7 @@ int ib_init_ucontext(struct uverbs_attr_bundle *attrs)if (ret) goto err_uncharge; -rdma_restrack_uadd (&ucontext->res); +rdma_restrack_add (&ucontext->res);/* * Make sure that ib_uverbs_get_ucontext() sees the pointer update
@@ -443,10 +444,12 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)atomic_set (&pd->usecnt,0 );rdma_restrack_new (&pd->res,RDMA_RESTRACK_PD ); +rdma_restrack_set_name (&pd->res,NULL ); + ret = ib_dev->ops.alloc_pd (pd, &attrs->driver_udata);if (ret) goto err_alloc; -rdma_restrack_uadd (&pd->res); +rdma_restrack_add (&pd->res); uobj->object = pd;uobj_finalize_uobj_create (uobj, attrs);
@@ -748,7 +751,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) mr->iova = cmd.hca_va;rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_uadd (&mr->res); +rdma_restrack_set_name (&mr->res,NULL ); +rdma_restrack_add (&mr->res); uobj->object = mr;uobj_put_obj_read (pd);
@@ -1000,10 +1004,12 @@ static int create_cq(struct uverbs_attr_bundle *attrs,atomic_set (&cq->usecnt,0 );rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); +rdma_restrack_set_name (&cq->res,NULL ); + ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free; -rdma_restrack_uadd (&cq->res); +rdma_restrack_add (&cq->res); obj->uevent.uobject.object = cq; obj->uevent.event_file =READ_ONCE (attrs->ufile->default_async_file);
drivers/infiniband/core/uverbs_std_types_cq.c +3 -1
@@ -126,13 +126,15 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(atomic_set (&cq->usecnt,0 );rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); +rdma_restrack_set_name (&cq->res,NULL ); + ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free; obj->uevent.uobject.object = cq; obj->uevent.uobject.user_handle = user_handle; -rdma_restrack_uadd (&cq->res); +rdma_restrack_add (&cq->res);uverbs_finalize_uobj_create (attrs,UVERBS_ATTR_CREATE_CQ_HANDLE ); ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
drivers/infiniband/core/verbs.c +5 -5
@@ -273,7 +273,7 @@ struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags, pd->flags = flags;rdma_restrack_new (&pd->res,RDMA_RESTRACK_PD ); -rdma_restrack_set_task (&pd->res, caller); +rdma_restrack_set_name (&pd->res, caller); ret = device->ops.alloc_pd (pd,NULL );if (ret) {
@@ -1999,7 +1999,7 @@ struct ib_cq *__ib_create_cq(struct ib_device *device,atomic_set (&cq->usecnt,0 );rdma_restrack_new (&cq->res,RDMA_RESTRACK_CQ ); -rdma_restrack_set_task (&cq->res, caller); +rdma_restrack_set_name (&cq->res, caller); ret = device->ops.create_cq (cq, cq_attr,NULL );if (ret) {
@@ -2081,7 +2081,7 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,atomic_inc (&pd->usecnt);rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_parent_name (&mr->res, &pd->res);rdma_restrack_add (&mr->res);return mr;
@@ -2165,7 +2165,7 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, mr->sig_attrs =NULL ;rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_parent_name (&mr->res, &pd->res);rdma_restrack_add (&mr->res); out:trace_mr_alloc (pd, mr_type, max_num_sg, mr);
@@ -2226,7 +2226,7 @@ struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd, mr->sig_attrs = sig_attrs;rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); -rdma_restrack_set_task (&mr->res, pd->res.kern_name); +rdma_restrack_parent_name (&mr->res, &pd->res);rdma_restrack_add (&mr->res); out:trace_mr_integ_alloc (pd, max_num_data_sg, max_num_meta_sg, mr);
include/rdma/restrack.h +0 -11
@@ -106,9 +106,6 @@ struct rdma_restrack_entry {int rdma_restrack_count (struct ib_device *dev,enum rdma_restrack_type type); - -void rdma_restrack_uadd (struct rdma_restrack_entry *res); -/** * rdma_is_kernel_res() - check the owner of resource * @res: resource entry
@@ -130,14 +127,6 @@ int __must_check rdma_restrack_get(struct rdma_restrack_entry *res);*/ int rdma_restrack_put (struct rdma_restrack_entry *res); -/** -* rdma_restrack_set_task() - set the task for this resource -* @res: resource entry -* @caller: kernel name, the current task will be used if the caller is NULL. -*/ -void rdma_restrack_set_task (struct rdma_restrack_entry *res, -const char *caller); -/* * Helper functions for rdma drivers when filling out * nldev driver attributes.
Signature · 1 line
2.26.2
PATCH 6/13 RDMA/cma: Be strict with attaching to CMA device
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
The RDMA-CM code wasn't consistent in flows that attached to cma_dev, this caused to situations where failure during attach to listen on such device leave RDMA-CM in non-consistent state.
Update the listen/attach flow to correctly deal with failures.
--- drivers/infiniband/core/cma.c | 197 ++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 83 deletions(-)
drivers/infiniband/core/cma.c +114 -83
@@ -458,8 +458,8 @@ static int cma_igmp_send(struct net_device *ndev, union ib_gid *mgid, bool join)return (in_dev) ?0 : -ENODEV ; } -static void _cma_attach_to_dev (struct rdma_id_private *id_priv, -struct cma_device *cma_dev) +static int _cma_attach_to_dev (struct rdma_id_private *id_priv, +struct cma_device *cma_dev) {cma_dev_get (cma_dev); id_priv->cma_dev = cma_dev;
@@ -475,15 +475,22 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,rdma_restrack_add (&id_priv->res);trace_cm_id_attach (id_priv, cma_dev->device); +return 0 ; } -static void cma_attach_to_dev (struct rdma_id_private *id_priv, -struct cma_device *cma_dev) +static int cma_attach_to_dev (struct rdma_id_private *id_priv, +struct cma_device *cma_dev) { -_cma_attach_to_dev (id_priv, cma_dev); +int ret; + + ret =_cma_attach_to_dev (id_priv, cma_dev); +if (ret) +return ret; + id_priv->gid_type = cma_dev->default_gid_type[id_priv->id.port_num -rdma_start_port (cma_dev->device)]; +return 0 ; }static inline void release_mc (struct kref *kref)
@@ -656,8 +663,7 @@ static int cma_acquire_dev_by_src_ip(struct rdma_id_private *id_priv)if (!IS_ERR (sgid_attr)) { id_priv->id.port_num = port;cma_bind_sgid_attr (id_priv, sgid_attr); -cma_attach_to_dev (id_priv, cma_dev); - ret =0 ; + ret =cma_attach_to_dev (id_priv, cma_dev); goto out; } }
@@ -686,6 +692,7 @@ static int cma_ib_acquire_dev(struct rdma_id_private *id_priv,const struct ib_gid_attr *sgid_attr;enum ib_gid_type gid_type;union ib_gid gid; +int ret;if (dev_addr->dev_type !=ARPHRD_INFINIBAND && id_priv->id.ps ==RDMA_PS_IPOIB )
@@ -711,9 +718,9 @@ static int cma_ib_acquire_dev(struct rdma_id_private *id_priv,* cma_process_remove(). */ mutex_lock (&lock); -cma_attach_to_dev (id_priv, listen_id_priv->cma_dev); + ret =cma_attach_to_dev (id_priv, listen_id_priv->cma_dev);mutex_unlock (&lock); -return 0 ; +return ret; } static int cma_iw_acquire_dev(struct rdma_id_private *id_priv,
@@ -768,7 +775,7 @@ static int cma_iw_acquire_dev(struct rdma_id_private *id_priv, out:if (!ret) -cma_attach_to_dev (id_priv, cma_dev); + ret =cma_attach_to_dev (id_priv, cma_dev);mutex_unlock (&lock);return ret;
@@ -785,7 +792,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)unsigned int p;u16 pkey, index;enum ib_port_state port_state; -int i; +int i, ret; cma_dev =NULL ; addr = (struct sockaddr_ib *)cma_dst_addr (id_priv);
@@ -828,8 +835,10 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)return -ENODEV ; found: -cma_attach_to_dev (id_priv, cma_dev); + ret =cma_attach_to_dev (id_priv, cma_dev);mutex_unlock (&lock); +if (ret) +return ret; addr = (struct sockaddr_ib *)cma_src_addr (id_priv);memcpy (&addr->sib_addr, &sgid,sizeof (sgid));cma_translate_ib (addr, &id_priv->id.route.addr.dev_addr);
@@ -2479,8 +2488,8 @@ static int cma_listen_handler(struct rdma_cm_id *id,return id_priv->id.event_handler (id, event); } -static void cma_listen_on_dev (struct rdma_id_private *id_priv, -struct cma_device *cma_dev) +static int cma_listen_on_dev (struct rdma_id_private *id_priv, +struct cma_device *cma_dev) {struct rdma_id_private *dev_id_priv;struct rdma_cm_id *id;
@@ -2490,12 +2499,12 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,lockdep_assert_held (&lock);if (cma_family (id_priv) ==AF_IB && !rdma_cap_ib_cm (cma_dev->device,1 )) -return ; +return 0 ; id =__rdma_create_id (net, cma_listen_handler, id_priv, id_priv->id.ps, id_priv->id.qp_type, id_priv->res.kern_name);if (IS_ERR (id)) -return ; +return PTR_ERR (id); dev_id_priv = container_of(id, struct rdma_id_private, id);
@@ -2503,7 +2512,9 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,memcpy (cma_src_addr (dev_id_priv),cma_src_addr (id_priv),rdma_addr_size (cma_src_addr (id_priv))); -_cma_attach_to_dev (dev_id_priv, cma_dev); + ret =_cma_attach_to_dev (dev_id_priv, cma_dev); +if (ret) + goto err_attach;list_add_tail (&dev_id_priv->listen_list, &id_priv->listen_list);cma_id_get (id_priv); dev_id_priv->internal_id =1 ;
@@ -2513,8 +2524,14 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, ret =rdma_listen (id, id_priv->backlog);if (ret) -dev_warn (&cma_dev->device->dev, -"RDMA CMA: cma_listen_on_dev, error %d\n" , ret); + goto err_listen; +return 0 ; +err_listen: +list_del (&id_priv->listen_list); +err_attach: +dev_warn (&cma_dev->device->dev,"RDMA CMA: %s, error %d\n" , __func__, ret); +rdma_destroy_id (id); +return ret; }static void cma_listen_on_all (struct rdma_id_private *id_priv)
@@ -3112,7 +3129,9 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv)rdma_addr_set_sgid (&id_priv->id.route.addr.dev_addr, &gid);ib_addr_set_pkey (&id_priv->id.route.addr.dev_addr, pkey); id_priv->id.port_num = p; -cma_attach_to_dev (id_priv, cma_dev); + ret =cma_attach_to_dev (id_priv, cma_dev); +if (ret) + goto out;cma_set_loopback (cma_src_addr (id_priv)); out:mutex_unlock (&lock);
@@ -4728,69 +4747,6 @@ static struct notifier_block cma_nb = { .notifier_call = cma_netdev_callback }; -static int cma_add_one (struct ib_device *device) -{ -struct cma_device *cma_dev; -struct rdma_id_private *id_priv; -unsigned int i; -unsigned long supported_gids =0 ; -int ret; - - cma_dev =kmalloc (sizeof *cma_dev,GFP_KERNEL ); -if (!cma_dev) -return -ENOMEM ; - - cma_dev->device = device; - cma_dev->default_gid_type =kcalloc (device->phys_port_cnt, -sizeof (*cma_dev->default_gid_type), -GFP_KERNEL ); -if (!cma_dev->default_gid_type) { - ret = -ENOMEM ; - goto free_cma_dev; - } - - cma_dev->default_roce_tos =kcalloc (device->phys_port_cnt, -sizeof (*cma_dev->default_roce_tos), -GFP_KERNEL ); -if (!cma_dev->default_roce_tos) { - ret = -ENOMEM ; - goto free_gid_type; - } - - rdma_for_each_port (device, i) { - supported_gids =roce_gid_type_mask_support (device, i); -WARN_ON (!supported_gids); -if (supported_gids & (1 <<CMA_PREFERRED_ROCE_GID_TYPE )) - cma_dev->default_gid_type[i -rdma_start_port (device)] = -CMA_PREFERRED_ROCE_GID_TYPE ; -else - cma_dev->default_gid_type[i -rdma_start_port (device)] = -find_first_bit (&supported_gids,BITS_PER_LONG ); - cma_dev->default_roce_tos[i -rdma_start_port (device)] =0 ; - } - -init_completion (&cma_dev->comp); -refcount_set (&cma_dev->refcount,1 ); -INIT_LIST_HEAD (&cma_dev->id_list); -ib_set_client_data (device, &cma_client, cma_dev); - -mutex_lock (&lock); -list_add_tail (&cma_dev->list, &dev_list); -list_for_each_entry (id_priv, &listen_any_list, list) -cma_listen_on_dev (id_priv, cma_dev); -mutex_unlock (&lock); - -trace_cm_add_one (device); -return 0 ; - -free_gid_type: -kfree (cma_dev->default_gid_type); - -free_cma_dev: -kfree (cma_dev); -return ret; -} -static void cma_send_device_removal_put (struct rdma_id_private *id_priv) {struct rdma_cm_event event = { .event =RDMA_CM_EVENT_DEVICE_REMOVAL };
@@ -4853,6 +4809,81 @@ static void cma_process_remove(struct cma_device *cma_dev)wait_for_completion (&cma_dev->comp); } +static int cma_add_one (struct ib_device *device) +{ +struct cma_device *cma_dev; +struct rdma_id_private *id_priv; +unsigned int i; +unsigned long supported_gids =0 ; +int ret; + + cma_dev =kmalloc (sizeof (*cma_dev),GFP_KERNEL ); +if (!cma_dev) +return -ENOMEM ; + + cma_dev->device = device; + cma_dev->default_gid_type =kcalloc (device->phys_port_cnt, +sizeof (*cma_dev->default_gid_type), +GFP_KERNEL ); +if (!cma_dev->default_gid_type) { + ret = -ENOMEM ; + goto free_cma_dev; + } + + cma_dev->default_roce_tos =kcalloc (device->phys_port_cnt, +sizeof (*cma_dev->default_roce_tos), +GFP_KERNEL ); +if (!cma_dev->default_roce_tos) { + ret = -ENOMEM ; + goto free_gid_type; + } + + rdma_for_each_port (device, i) { + supported_gids =roce_gid_type_mask_support (device, i); +WARN_ON (!supported_gids); +if (supported_gids & (1 <<CMA_PREFERRED_ROCE_GID_TYPE )) + cma_dev->default_gid_type[i -rdma_start_port (device)] = +CMA_PREFERRED_ROCE_GID_TYPE ; +else + cma_dev->default_gid_type[i -rdma_start_port (device)] = +find_first_bit (&supported_gids,BITS_PER_LONG ); + cma_dev->default_roce_tos[i -rdma_start_port (device)] =0 ; + } + +init_completion (&cma_dev->comp); +refcount_set (&cma_dev->refcount,1 ); +INIT_LIST_HEAD (&cma_dev->id_list); +ib_set_client_data (device, &cma_client, cma_dev); + +mutex_lock (&lock); +list_add_tail (&cma_dev->list, &dev_list); +list_for_each_entry (id_priv, &listen_any_list, list) { + ret =cma_listen_on_dev (id_priv, cma_dev); +if (ret) { +mutex_unlock (&lock); + goto free_listen; + } + } +mutex_unlock (&lock); + +trace_cm_add_one (device); +return 0 ; + +free_listen: +mutex_lock (&lock); +list_del (&cma_dev->list); +mutex_unlock (&lock); + +cma_process_remove (cma_dev); +kfree (cma_dev->default_roce_tos); +free_gid_type: +kfree (cma_dev->default_gid_type); + +free_cma_dev: +kfree (cma_dev); +return ret; +} +static void cma_remove_one (struct ib_device *device,void *client_data) {struct cma_device *cma_dev = client_data;
Signature · 1 line
2.26.2
PATCH 7/13 RDMA/core: Allow drivers to disable restrack DB
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Driver QP types are special case with no IBTA restrictions. For example, EFA implemented creation of this QP type as regular one, while mlx5 separated create to two step: create and modify. That separation causes to the situation where DC QP (mlx5) is always added to the same xarray index zero.
This change allows to drivers like mlx5 simply disable restrack DB tracking, but it doesn't disable kref on the memory.
--- drivers/infiniband/core/counters.c | 2 +- drivers/infiniband/core/restrack.c | 12 ++++++++++-- drivers/infiniband/hw/mlx5/qp.c | 2 +- include/rdma/restrack.h | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-)
drivers/infiniband/core/counters.c +1 -1
@@ -275,7 +275,7 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)struct rdma_counter *counter;int ret; -if (!qp->res.valid ||rdma_is_kernel_res (&qp->res)) +if (!rdma_restrack_is_tracked (&qp->res) ||rdma_is_kernel_res (&qp->res))return 0 ;if (!rdma_is_port_valid (dev, port))
drivers/infiniband/core/restrack.c +10 -2
@@ -221,11 +221,14 @@ void rdma_restrack_add(struct rdma_restrack_entry *res) {struct ib_device *dev =res_to_dev (res);struct rdma_restrack_root *rt; -int ret; +int ret =0 ;if (!dev)return ; +if (res->no_track) + goto out; + rt = &dev->res[res->type];if (res->type ==RDMA_RESTRACK_QP ) {
@@ -246,6 +249,7 @@ void rdma_restrack_add(struct rdma_restrack_entry *res) &rt->next_id, GFP_KERNEL); } +out:if (!ret) res->valid = true; }
@@ -318,6 +322,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)return ; } +if (res->no_track) + goto out; + dev =res_to_dev (res);if (WARN_ON (!dev))return ;
@@ -329,8 +336,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) (res->type == RDMA_RESTRACK_MR || res->type == RDMA_RESTRACK_QP)) return;WARN_ON (old != res); - res->valid = false; +out: + res->valid = false;rdma_restrack_put (res);wait_for_completion (&res->comp); }
drivers/infiniband/hw/mlx5/qp.c +1 -1
@@ -2434,7 +2434,7 @@ static int create_dct(struct mlx5_ib_dev *dev, struct ib_pd *pd, } qp->state =IB_QPS_RESET ; - +rdma_restrack_no_track (&qp->ibqp.res);return 0 ; }
include/rdma/restrack.h +24 -0
@@ -68,6 +68,14 @@ struct rdma_restrack_entry {* As an example for that, see mlx5 QPs with type MLX5_IB_QPT_HW_GSI */ bool valid; +/** +* @no_track: don't add this entry to restrack DB +* +* This field is used to mark an entry that doesn't need to be added to +* internal restrack DB and presented later to the users at the nldev +* query stage. +*/ + u8 no_track : 1;/* * @kref: Protect destroy of the resource */
@@ -145,4 +153,20 @@ int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,struct rdma_restrack_entry *rdma_restrack_get_byid (struct ib_device *dev,enum rdma_restrack_type type,u32 id); + +/** +* rdma_restrack_no_track() - don't add resource to the DB +* @res: resource entry +* +* Every user of thie API should be cross examined. +* Probaby you don't need to use this function. +*/ +static inline void rdma_restrack_no_track (struct rdma_restrack_entry *res) +{ + res->no_track = true; +} +static inline bool rdma_restrack_is_tracked (struct rdma_restrack_entry *res) +{ +return !res->no_track; +}#endif /* _RDMA_RESTRACK_H_ */
Signature · 1 line
2.26.2
Jason Gunthorpe
maintainerRe: [PATCH rdma-next v1 07/13] RDMA/core: Allow drivers to disable restrack DB
Quoted 8 lines · Leon Romanovsky
include/rdma/restrack.h +2
-0+++ b/include/rdma/restrack.h@@ -68,6 +68,14 @@ struct rdma_restrack_entry {* As an example for that, see mlx5 QPs with type MLX5_IB_QPT_HW_GSI */ bool valid; +/**
include/rdma/restrack.h struct rdma_restrack_entry { · line 81
Quoted 10 lines
include/rdma/restrack.h +7
-0+* @no_track: don't add this entry to restrack DB +* +* This field is used to mark an entry that doesn't need to be added to +* internal restrack DB and presented later to the users at the nldev +* query stage. +*/ + u8 no_track : 1;/* * @kref: Protect destroy of the resource */
The valid may as well be changed to a bitfield too
Quoted 5 lines
include/rdma/restrack.h +5
-0+/** +* rdma_restrack_no_track() - don't add resource to the DB +* @res: resource entry +* +* Every user of thie API should be cross examined.
include/rdma/restrack.h int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name, · line 171
Quoted 10 lines
include/rdma/restrack.h +10
-0+* Probaby you don't need to use this function. +*/ +static inline void rdma_restrack_no_track (struct rdma_restrack_entry *res) +{ + res->no_track = true; +} +static inline bool rdma_restrack_is_tracked (struct rdma_restrack_entry *res) +{ +return !res->no_track; +}
Are these wrappers really necessary?
Jason
Re: [PATCH rdma-next v1 07/13] RDMA/core: Allow drivers to disable restrack DB
Quoted 13 lines · Jason Gunthorpe
Quoted 12 lines · Leon Romanovsky
include/rdma/restrack.h +6
-0+++ b/include/rdma/restrack.h@@ -68,6 +68,14 @@ struct rdma_restrack_entry {* As an example for that, see mlx5 QPs with type MLX5_IB_QPT_HW_GSI */ bool valid; +/** +* @no_track: don't add this entry to restrack DB +* +* This field is used to mark an entry that doesn't need to be added to +* internal restrack DB and presented later to the users at the nldev
Quoted 8 lines
include/rdma/restrack.h struct rdma_restrack_entry { · line 81
Quoted 6 lines
include/rdma/restrack.h +3
-0+* query stage. +*/ + u8 no_track : 1;/* * @kref: Protect destroy of the resource */ The valid may as well be changed to a bitfield too
I will delete "valid" later in this series.
Quoted 11 lines
Quoted 11 lines
include/rdma/restrack.h +9
-0+/** +* rdma_restrack_no_track() - don't add resource to the DB +* @res: resource entry +* +* Every user of thie API should be cross examined. +* Probaby you don't need to use this function. +*/ +static inline void rdma_restrack_no_track (struct rdma_restrack_entry *res) +{
Quoted 8 lines
include/rdma/restrack.h int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name, · line 171
Quoted 6 lines
include/rdma/restrack.h +6
-0+ res->no_track = true; +} +static inline bool rdma_restrack_is_tracked (struct rdma_restrack_entry *res) +{ +return !res->no_track; +}Are these wrappers really necessary?
I don't like them either, added them to make same interface for all restrack operations.
Quoted 2 lines
Jason
PATCH 8/13 RDMA/counter: Combine allocation and bind logic
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
RDMA counters are allocated and bounded to QP immediately after that. Only after this two step process they are really usable. By combining the logic, we are ensuring that once counter is returned to the caller, it will have everything set.
--- drivers/infiniband/core/counters.c | 130 +++++++++++++---------------- 1 file changed, 58 insertions(+), 72 deletions(-)
drivers/infiniband/core/counters.c +58 -72
@@ -64,8 +64,40 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,return ret; } -static struct rdma_counter *rdma_counter_alloc (struct ib_device *dev,u8 port, -enum rdma_nl_counter_mode mode) +static void auto_mode_init_counter (struct rdma_counter *counter, +const struct ib_qp *qp, +enum rdma_nl_counter_mask new_mask) +{ +struct auto_mode_param *param = &counter->mode.param; + + counter->mode.mode =RDMA_COUNTER_MODE_AUTO ; + counter->mode.mask = new_mask; + +if (new_mask &RDMA_COUNTER_MASK_QP_TYPE ) + param->qp_type = qp->qp_type; +} + +static int __rdma_counter_bind_qp (struct rdma_counter *counter, +struct ib_qp *qp) +{ +int ret; + +if (qp->counter) +return -EINVAL ; + +if (!qp->device->ops.counter_bind_qp) +return -EOPNOTSUPP ; + +mutex_lock (&counter->lock); + ret = qp->device->ops.counter_bind_qp (counter, qp); +mutex_unlock (&counter->lock); + +return ret; +} + +static struct rdma_counter *alloc_and_bind (struct ib_device *dev,u8 port, +struct ib_qp *qp, +enum rdma_nl_counter_mode mode) {struct rdma_port_counter *port_counter;struct rdma_counter *counter;
@@ -88,11 +120,19 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, port_counter = &dev->port_data[port].port_counter;mutex_lock (&port_counter->lock); -if (mode ==RDMA_COUNTER_MODE_MANUAL ) { +switch (mode) { +case RDMA_COUNTER_MODE_MANUAL : ret =__counter_set_mode (&port_counter->mode,RDMA_COUNTER_MODE_MANUAL ,0 );if (ret) goto err_mode; +break ; +case RDMA_COUNTER_MODE_AUTO : +auto_mode_init_counter (counter, qp, port_counter->mode.mask); +break ; +default : + ret = -EOPNOTSUPP ; + goto err_mode; } port_counter->num_counters++;
@@ -102,6 +142,12 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,kref_init (&counter->kref);mutex_init (&counter->lock); + ret =__rdma_counter_bind_qp (counter, qp); +if (ret) + goto err_mode; + +rdma_restrack_parent_name (&counter->res, &qp->res); +rdma_restrack_add (&counter->res);return counter; err_mode:
@@ -132,19 +178,6 @@ static void rdma_counter_free(struct rdma_counter *counter)kfree (counter); } -static void auto_mode_init_counter (struct rdma_counter *counter, -const struct ib_qp *qp, -enum rdma_nl_counter_mask new_mask) -{ -struct auto_mode_param *param = &counter->mode.param; - - counter->mode.mode =RDMA_COUNTER_MODE_AUTO ; - counter->mode.mask = new_mask; - -if (new_mask &RDMA_COUNTER_MASK_QP_TYPE ) - param->qp_type = qp->qp_type; -} -static bool auto_mode_match (struct ib_qp *qp,struct rdma_counter *counter,enum rdma_nl_counter_mask auto_mask) {
@@ -161,24 +194,6 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,return match; } -static int __rdma_counter_bind_qp (struct rdma_counter *counter, -struct ib_qp *qp) -{ -int ret; - -if (qp->counter) -return -EINVAL ; - -if (!qp->device->ops.counter_bind_qp) -return -EOPNOTSUPP ; - -mutex_lock (&counter->lock); - ret = qp->device->ops.counter_bind_qp (counter, qp); -mutex_unlock (&counter->lock); - -return ret; -} -static int __rdma_counter_unbind_qp (struct ib_qp *qp) {struct rdma_counter *counter = qp->counter;
@@ -247,13 +262,6 @@ static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp,return counter; } -static void rdma_counter_res_add (struct rdma_counter *counter, -struct ib_qp *qp) -{ -rdma_restrack_parent_name (&counter->res, &qp->res); -rdma_restrack_add (&counter->res); -} -static void counter_release (struct kref *kref) {struct rdma_counter *counter;
@@ -293,19 +301,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)return ret; } }else { - counter =rdma_counter_alloc (dev, port,RDMA_COUNTER_MODE_AUTO ); + counter =alloc_and_bind (dev, port, qp,RDMA_COUNTER_MODE_AUTO );if (!counter)return -ENOMEM ; - -auto_mode_init_counter (counter, qp, port_counter->mode.mask); - - ret =__rdma_counter_bind_qp (counter, qp); -if (ret) { -rdma_counter_free (counter); -return ret; - } - -rdma_counter_res_add (counter, qp); }return 0 ;
@@ -419,15 +417,6 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)return NULL ; } -static int rdma_counter_bind_qp_manual (struct rdma_counter *counter, -struct ib_qp *qp) -{ -if ((counter->device != qp->device) || (counter->port != qp->port)) -return -EINVAL ; - -return __rdma_counter_bind_qp (counter, qp); -} -static struct rdma_counter *rdma_get_counter_by_id (struct ib_device *dev,u32 counter_id) {
@@ -475,7 +464,12 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port, goto err_task; } - ret =rdma_counter_bind_qp_manual (counter, qp); +if ((counter->device != qp->device) || (counter->port != qp->port)) { + ret = -EINVAL ; + goto err_task; + } + + ret =__rdma_counter_bind_qp (counter, qp);if (ret) goto err_task;
@@ -520,26 +514,18 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port, goto err; } - counter =rdma_counter_alloc (dev, port,RDMA_COUNTER_MODE_MANUAL ); + counter =alloc_and_bind (dev, port, qp,RDMA_COUNTER_MODE_MANUAL );if (!counter) { ret = -ENOMEM ; goto err; } - ret =rdma_counter_bind_qp_manual (counter, qp); -if (ret) - goto err_bind; -if (counter_id) *counter_id = counter->id; -rdma_counter_res_add (counter, qp); -rdma_restrack_put (&qp->res); -return ret; +return 0 ; -err_bind: -rdma_counter_free (counter); err:rdma_restrack_put (&qp->res);return ret;
Signature · 1 line
2.26.2
PATCH 9/13 RDMA/restrack: Store all special QPs in restrack DB
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Special QPs (SMI and GSI) have different rules in regards of their QP numbers. While all other QP numbers are unique per-device, the QP0 and QP1 are created per-port as requested by IBTA.
In multiple port devices, the number of SMI and GSI QPs with be equal to the number ports.
[leonro@vm ~]$ rdma dev
0: ibp0s9: node_type ca fw 4.4.9999 node_guid 5254:00c0:fe12:3455 sys_image_guid 5254:00c0:fe12:3455 [leonro@vm ~]$ rdma link
0/1: ibp0s9/1: subnet_prefix fe80:0000:0000:0000 lid 13397 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP 0/2: ibp0s9/2: subnet_prefix fe80:0000:0000:0000 lid 13397 sm_lid 49151 lmc 0 state UNKNOWN physical_state UNKNOWN
Before:
[leonro@mtl-leonro-l-vm ~]$ rdma res show qp type SMI,GSI link ibp0s9/1 lqpn 0 type SMI state RTS sq-psn 0 comm [ib_core] link ibp0s9/1 lqpn 1 type GSI state RTS sq-psn 0 comm [ib_core]
After:
[leonro@vm ~]$ rdma res show qp type SMI,GSI
link ibp0s9/1 lqpn 0 type SMI state RTS sq-psn 0 comm [ib_core] link ibp0s9/1 lqpn 1 type GSI state RTS sq-psn 0 comm [ib_core] link ibp0s9/2 lqpn 0 type SMI state RTS sq-psn 0 comm [ib_core] link ibp0s9/2 lqpn 1 type GSI state RTS sq-psn 0 comm [ib_core]
--- drivers/infiniband/core/core_priv.h | 2 ++ drivers/infiniband/core/restrack.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-)
drivers/infiniband/core/core_priv.h +2 -0
@@ -347,6 +347,8 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, qp->srq = attr->srq; qp->rwq_ind_tbl = attr->rwq_ind_tbl; qp->event_handler = attr->event_handler; + qp->qp_type = attr->qp_type; + qp->port = attr->port_num;atomic_set (&qp->usecnt,0 );spin_lock_init (&qp->mr_lock);
drivers/infiniband/core/restrack.c +9 -2
@@ -235,8 +235,15 @@ void rdma_restrack_add(struct rdma_restrack_entry *res)/* Special case to ensure that LQPN points to right QP */ struct ib_qp *qp = container_of(res, struct ib_qp, res); - ret =xa_insert (&rt->xa, qp->qp_num, res,GFP_KERNEL ); - res->id = ret ?0 : qp->qp_num; +WARN_ONCE (qp->qp_num >>24 || qp->port >>8 , +"QP number 0x%0X and port 0x%0X" , qp->qp_num, + qp->port); + res->id = qp->qp_num; +if (qp->qp_type ==IB_QPT_SMI || qp->qp_type ==IB_QPT_GSI ) + res->id |= qp->port <<24 ; + ret =xa_insert (&rt->xa, res->id, res,GFP_KERNEL ); +if (ret) + res->id =0 ; }else if (res->type ==RDMA_RESTRACK_COUNTER ) {/* Special case to ensure that cntn points to right counter */ struct rdma_counter *counter;
Signature · 1 line
2.26.2
PATCH 10/13 RDMA/restrack: Make restrack DB mandatory for IB objects
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Restrack stores the IB objects in the internal xarray and insertion where can fail. As long as restrack was helper tool for the debuggability, such failure were ignored.
In the following patches, the ib_core will be changed to manage allocated IB objects in restrack DB for the proper memory lifetime. It requires to ensure that insertion errors are not ignored.
--- drivers/infiniband/core/cma.c | 9 ++- drivers/infiniband/core/core_priv.h | 9 ++- drivers/infiniband/core/counters.c | 37 ++++++----- drivers/infiniband/core/cq.c | 17 ++++- drivers/infiniband/core/rdma_core.c | 3 +- drivers/infiniband/core/restrack.c | 26 +++++--- drivers/infiniband/core/restrack.h | 2 +- drivers/infiniband/core/uverbs_cmd.c | 27 ++++++-- drivers/infiniband/core/uverbs_std_types_cq.c | 6 +- drivers/infiniband/core/verbs.c | 63 ++++++++++++++----- 10 files changed, 147 insertions(+), 52 deletions(-)
drivers/infiniband/core/cma.c +8 -1
@@ -461,6 +461,8 @@ static int cma_igmp_send(struct net_device *ndev, union ib_gid *mgid, bool join)static int _cma_attach_to_dev (struct rdma_id_private *id_priv,struct cma_device *cma_dev) { +int ret; +cma_dev_get (cma_dev); id_priv->cma_dev = cma_dev; id_priv->id.device = cma_dev->device;
@@ -472,7 +474,12 @@ static int _cma_attach_to_dev(struct rdma_id_private *id_priv,* attach to "current" task. */ rdma_restrack_set_name (&id_priv->res, id_priv->res.kern_name); -rdma_restrack_add (&id_priv->res); + ret =rdma_restrack_add (&id_priv->res); +if (ret) { +list_del (&cma_dev->id_list); +cma_dev_put (cma_dev); +return ret; + }trace_cm_id_attach (id_priv, cma_dev->device);return 0 ;
drivers/infiniband/core/core_priv.h +8 -1
@@ -327,6 +327,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,enum ib_qp_type qp_type = attr->qp_type;struct ib_qp *qp;bool is_xrc; +int ret;if (!dev->ops.create_qp)return ERR_PTR (-EOPNOTSUPP );
@@ -364,9 +365,15 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, is_xrc = qp_type ==IB_QPT_XRC_INI || qp_type ==IB_QPT_XRC_TGT ;if ((qp_type <IB_QPT_MAX && !is_xrc) || qp_type ==IB_QPT_DRIVER ) {rdma_restrack_parent_name (&qp->res, &pd->res); -rdma_restrack_add (&qp->res); + ret =rdma_restrack_add (&qp->res); +if (ret) + goto err; }return qp; +err: +rdma_restrack_put (&qp->res); + dev->ops.destroy_qp (qp, udata); +return ERR_PTR (ret); }struct rdma_dev_addr ;
drivers/infiniband/core/counters.c +21 -16
@@ -95,6 +95,21 @@ static int __rdma_counter_bind_qp(struct rdma_counter *counter,return ret; } +static int __rdma_counter_unbind_qp (struct ib_qp *qp) +{ +struct rdma_counter *counter = qp->counter; +int ret; + +if (!qp->device->ops.counter_unbind_qp) +return -EOPNOTSUPP ; + +mutex_lock (&counter->lock); + ret = qp->device->ops.counter_unbind_qp (qp); +mutex_unlock (&counter->lock); + +return ret; +} +static struct rdma_counter *alloc_and_bind (struct ib_device *dev,u8 port,struct ib_qp *qp,enum rdma_nl_counter_mode mode)
@@ -147,9 +162,14 @@ static struct rdma_counter *alloc_and_bind(struct ib_device *dev, u8 port, goto err_mode;rdma_restrack_parent_name (&counter->res, &qp->res); -rdma_restrack_add (&counter->res); + ret =rdma_restrack_add (&counter->res); +if (ret) + goto err_restrack; +return counter; +err_restrack: +__rdma_counter_unbind_qp (qp); err_mode:mutex_unlock (&port_counter->lock);kfree (counter->stats);
@@ -194,21 +214,6 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,return match; } -static int __rdma_counter_unbind_qp (struct ib_qp *qp) -{ -struct rdma_counter *counter = qp->counter; -int ret; - -if (!qp->device->ops.counter_unbind_qp) -return -EOPNOTSUPP ; - -mutex_lock (&counter->lock); - ret = qp->device->ops.counter_unbind_qp (qp); -mutex_unlock (&counter->lock); - -return ret; -} -static void counter_history_stat_update (struct rdma_counter *counter) {struct ib_device *dev = counter->device;
drivers/infiniband/core/cq.c +16 -1
@@ -267,10 +267,25 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe, goto out_destroy_cq; } -rdma_restrack_add (&cq->res); + ret =rdma_restrack_add (&cq->res); +if (ret) + goto out_poll_cq; +trace_cq_alloc (cq, nr_cqe, comp_vector, poll_ctx);return cq; +out_poll_cq: +switch (cq->poll_ctx) { +case IB_POLL_SOFTIRQ : +irq_poll_disable (&cq->iop); +break ; +case IB_POLL_WORKQUEUE : +case IB_POLL_UNBOUND_WORKQUEUE : +cancel_work_sync (&cq->work); +break ; +default : +break ; + } out_destroy_cq:rdma_dim_destroy (cq); cq->device->ops.destroy_cq (cq,NULL );
drivers/infiniband/core/rdma_core.c +1 -2
@@ -831,10 +831,9 @@ static void ufile_destroy_ucontext(struct ib_uverbs_file *ufile,ib_rdmacg_uncharge (&ucontext->cg_obj, ib_dev,RDMACG_RESOURCE_HCA_HANDLE ); -rdma_restrack_del (&ucontext->res); - ib_dev->ops.dealloc_ucontext (ucontext);WARN_ON (!xa_empty (&ucontext->mmap_xa)); +rdma_restrack_del (&ucontext->res);kfree (ucontext); ufile->ucontext =NULL ;
drivers/infiniband/core/restrack.c +16 -10
@@ -217,21 +217,22 @@ EXPORT_SYMBOL(rdma_restrack_new);* rdma_restrack_add() - add object to the reource tracking database * @res: resource entry */ -void rdma_restrack_add (struct rdma_restrack_entry *res) +int __must_check rdma_restrack_add (struct rdma_restrack_entry *res) {struct ib_device *dev =res_to_dev (res);struct rdma_restrack_root *rt;int ret =0 ;if (!dev) -return ; +return -ENODEV ;if (res->no_track) goto out; rt = &dev->res[res->type]; -if (res->type ==RDMA_RESTRACK_QP ) { +switch (res->type) { +case RDMA_RESTRACK_QP : {/* Special case to ensure that LQPN points to right QP */ struct ib_qp *qp = container_of(res, struct ib_qp, res);
@@ -244,21 +245,26 @@ void rdma_restrack_add(struct rdma_restrack_entry *res) ret =xa_insert (&rt->xa, res->id, res,GFP_KERNEL );if (ret) res->id =0 ; - }else if (res->type ==RDMA_RESTRACK_COUNTER ) { + }break ; +case RDMA_RESTRACK_COUNTER : {/* Special case to ensure that cntn points to right counter */ -struct rdma_counter *counter; + struct rdma_counter *counter = container_of(res, struct rdma_counter, res); - counter = container_of(res, struct rdma_counter, res); ret =xa_insert (&rt->xa, counter->id, res,GFP_KERNEL ); - res->id = ret ?0 : counter->id; - }else { +if (ret) +break ; + res->id = counter->id; + }break ; +default : ret =xa_alloc_cyclic (&rt->xa, &res->id, res, xa_limit_32b, &rt->next_id,GFP_KERNEL ); } out: -if (!ret) - res->valid = true; +if (ret) +return ret; + res->valid = true; +return 0 ; }EXPORT_SYMBOL (rdma_restrack_add);
drivers/infiniband/core/restrack.h +1 -1
@@ -25,7 +25,7 @@ struct rdma_restrack_root {int rdma_restrack_init (struct ib_device *dev);void rdma_restrack_clean (struct ib_device *dev); -void rdma_restrack_add (struct rdma_restrack_entry *res); +int __must_check rdma_restrack_add (struct rdma_restrack_entry *res);void rdma_restrack_del (struct rdma_restrack_entry *res);void rdma_restrack_new (struct rdma_restrack_entry *res,enum rdma_restrack_type type);
drivers/infiniband/core/uverbs_cmd.c +23 -4
@@ -252,7 +252,9 @@ int ib_init_ucontext(struct uverbs_attr_bundle *attrs)if (ret) goto err_uncharge; -rdma_restrack_add (&ucontext->res); + ret =rdma_restrack_add (&ucontext->res); +if (ret) + goto err_restrack;/* * Make sure that ib_uverbs_get_ucontext() sees the pointer update
@@ -264,6 +266,8 @@ int ib_init_ucontext(struct uverbs_attr_bundle *attrs)up_read (&file->hw_destroy_rwsem);return 0 ; +err_restrack: + ucontext->device->ops.dealloc_ucontext (ucontext); err_uncharge:ib_rdmacg_uncharge (&ucontext->cg_obj, ucontext->device,RDMACG_RESOURCE_HCA_HANDLE );
@@ -449,7 +453,10 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) ret = ib_dev->ops.alloc_pd (pd, &attrs->driver_udata);if (ret) goto err_alloc; -rdma_restrack_add (&pd->res); + + ret =rdma_restrack_add (&pd->res); +if (ret) + goto err_restrack; uobj->object = pd;uobj_finalize_uobj_create (uobj, attrs);
@@ -457,6 +464,9 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs) resp.pd_handle = uobj->id;return uverbs_response (attrs, &resp,sizeof (resp)); +err_restrack: + ib_dev->ops.dealloc_pd (pd, &attrs->driver_udata); + err_alloc:rdma_restrack_put (&pd->res);kfree (pd);
@@ -752,7 +762,9 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR );rdma_restrack_set_name (&mr->res,NULL ); -rdma_restrack_add (&mr->res); + ret =rdma_restrack_add (&mr->res); +if (ret) + goto err_restrack; uobj->object = mr;uobj_put_obj_read (pd);
@@ -763,6 +775,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) resp.mr_handle = uobj->id;return uverbs_response (attrs, &resp,sizeof (resp)); +err_restrack: + pd->device->ops.dereg_mr (mr, &attrs->driver_udata); err_put:uobj_put_obj_read (pd); err_free:
@@ -1009,7 +1023,10 @@ static int create_cq(struct uverbs_attr_bundle *attrs, ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free; -rdma_restrack_add (&cq->res); + + ret =rdma_restrack_add (&cq->res); +if (ret) + goto err_restrack; obj->uevent.uobject.object = cq; obj->uevent.event_file =READ_ONCE (attrs->ufile->default_async_file);
@@ -1022,6 +1039,8 @@ static int create_cq(struct uverbs_attr_bundle *attrs, resp.response_length =uverbs_response_length (attrs,sizeof (resp));return uverbs_response (attrs, &resp,sizeof (resp)); +err_restrack: + ib_dev->ops.destroy_cq (cq, &attrs->driver_udata); err_free:rdma_restrack_put (&cq->res);kfree (cq);
drivers/infiniband/core/uverbs_std_types_cq.c +5 -1
@@ -131,16 +131,20 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)( ret = ib_dev->ops.create_cq (cq, &attr, &attrs->driver_udata);if (ret) goto err_free; + ret =rdma_restrack_add (&cq->res); +if (ret) + goto err_restrack; obj->uevent.uobject.object = cq; obj->uevent.uobject.user_handle = user_handle; -rdma_restrack_add (&cq->res);uverbs_finalize_uobj_create (attrs,UVERBS_ATTR_CREATE_CQ_HANDLE ); ret =uverbs_copy_to (attrs,UVERBS_ATTR_CREATE_CQ_RESP_CQE , &cq->cqe,sizeof (cq->cqe));return ret; +err_restrack: + ib_dev->ops.destroy_cq (cq, &attrs->driver_udata); err_free:rdma_restrack_put (&cq->res);kfree (cq);
drivers/infiniband/core/verbs.c +48 -15
119 lines not on this page · raw message
Signature · 1 line
2.26.2
PATCH 11/13 RDMA/restrack: Support all QP types
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
The latest changes in restrack name handling allowed to simplify the QP creation code to support all types of QPs.
For example XRC QP are presented with inbox rdmatool.
[leonro@vm ~]$ ibv_xsrq_pingpong &
[leonro@vm ~]$ rdma res show qp
link ibp0s9/1 lqpn 0 type SMI state RTS sq-psn 0 comm [ib_core]
link ibp0s9/1 lqpn 1 type GSI state RTS sq-psn 0 comm [ib_core]
link ibp0s9/1 lqpn 7 type UD state RTS sq-psn 0 comm [mlx5_ib]
link ibp0s9/1 lqpn 42 type XRC_TGT state INIT sq-psn 0 path-mig-state MIGRATED comm [ib_uverbs] link ibp0s9/1 lqpn 43 type XRC_INI state INIT sq-psn 0 path-mig-state MIGRATED pdn 197 pid 419 comm ibv_xsrq_pingpong
--- drivers/infiniband/core/core_priv.h | 29 ++++++------------- drivers/infiniband/core/uverbs_cmd.c | 4 +-- drivers/infiniband/core/uverbs_std_types_qp.c | 4 +-- drivers/infiniband/core/verbs.c | 11 +++---- include/rdma/ib_verbs.h | 10 +++++-- 5 files changed, 27 insertions(+), 31 deletions(-)
drivers/infiniband/core/core_priv.h +9 -20
@@ -318,15 +318,12 @@ struct ib_device *ib_device_get_by_index(const struct net *net, u32 index);void nldev_init (void );void nldev_exit (void ); -static inline struct ib_qp *_ib_create_qp (struct ib_device *dev, -struct ib_pd *pd, -struct ib_qp_init_attr *attr, -struct ib_udata *udata, -struct ib_uqp_object *uobj) +static inline struct ib_qp * +_ib_create_qp (struct ib_device *dev,struct ib_pd *pd, +struct ib_qp_init_attr *attr,struct ib_udata *udata, +struct ib_uqp_object *uobj,const char *caller) { -enum ib_qp_type qp_type = attr->qp_type;struct ib_qp *qp; -bool is_xrc;int ret;if (!dev->ops.create_qp)
@@ -348,7 +345,6 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, qp->srq = attr->srq; qp->rwq_ind_tbl = attr->rwq_ind_tbl; qp->event_handler = attr->event_handler; - qp->qp_type = attr->qp_type; qp->port = attr->port_num;atomic_set (&qp->usecnt,0 );
@@ -357,18 +353,11 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,INIT_LIST_HEAD (&qp->sig_mrs);rdma_restrack_new (&qp->res,RDMA_RESTRACK_QP ); -/* -* We don't track XRC QPs for now, because they don't have PD -* and more importantly they are created internaly by driver, -* see mlx5 create_dev_resources() as an example. -*/ - is_xrc = qp_type ==IB_QPT_XRC_INI || qp_type ==IB_QPT_XRC_TGT ; -if ((qp_type <IB_QPT_MAX && !is_xrc) || qp_type ==IB_QPT_DRIVER ) { -rdma_restrack_parent_name (&qp->res, &pd->res); - ret =rdma_restrack_add (&qp->res); -if (ret) - goto err; - } +WARN_ONCE (!udata && !caller,"Missing kernel QP owner" ); +rdma_restrack_set_name (&qp->res, udata ?NULL : caller); + ret =rdma_restrack_add (&qp->res); +if (ret) + goto err;return qp; err:rdma_restrack_put (&qp->res);
drivers/infiniband/core/uverbs_cmd.c +2 -2
@@ -1399,8 +1399,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs,if (cmd->qp_type ==IB_QPT_XRC_TGT ) qp =ib_create_qp (pd, &attr);else - qp =_ib_create_qp (device, pd, &attr, &attrs->driver_udata, - obj); + qp =_ib_create_qp (device, pd, &attr, &attrs->driver_udata, obj, +NULL );if (IS_ERR (qp)) { ret =PTR_ERR (qp);
drivers/infiniband/core/uverbs_std_types_qp.c +2 -2
@@ -251,8 +251,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(if (attr.qp_type ==IB_QPT_XRC_TGT ) qp =ib_create_qp (pd, &attr);else - qp =_ib_create_qp (device, pd, &attr, &attrs->driver_udata, - obj); + qp =_ib_create_qp (device, pd, &attr, &attrs->driver_udata, obj, +NULL );if (IS_ERR (qp)) { ret =PTR_ERR (qp);
drivers/infiniband/core/verbs.c +6 -5
@@ -1195,7 +1195,7 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp, }/** -* ib_create_qp - Creates a kernel QP associated with the specified protection +* ib_create_named_qp - Creates a kernel QP associated with the specified protection * domain. * @pd: The protection domain associated with the QP. * @qp_init_attr: A list of initial attributes required to create the
@@ -1204,8 +1204,9 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,* * NOTE: for user qp use ib_create_qp_user with valid udata! */ -struct ib_qp *ib_create_qp (struct ib_pd *pd, -struct ib_qp_init_attr *qp_init_attr) +struct ib_qp *ib_create_named_qp (struct ib_pd *pd, +struct ib_qp_init_attr *qp_init_attr, +const char *caller) {struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;struct ib_qp *qp;
@@ -1230,7 +1231,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,if (qp_init_attr->cap.max_rdma_ctxs)rdma_rw_init_qp (device, qp_init_attr); - qp =_ib_create_qp (device, pd, qp_init_attr,NULL ,NULL ); + qp =_ib_create_qp (device, pd, qp_init_attr,NULL ,NULL , caller);if (IS_ERR (qp))return qp;
@@ -1296,7 +1297,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,return ERR_PTR (ret); } -EXPORT_SYMBOL (ib_create_qp); +EXPORT_SYMBOL (ib_create_named_qp); static const struct { int valid;
include/rdma/ib_verbs.h +8 -2
@@ -3684,8 +3684,14 @@ static inline int ib_post_srq_recv(struct ib_srq *srq, bad_recv_wr ? : &dummy); } -struct ib_qp *ib_create_qp (struct ib_pd *pd, -struct ib_qp_init_attr *qp_init_attr); +struct ib_qp *ib_create_named_qp (struct ib_pd *pd, +struct ib_qp_init_attr *qp_init_attr, +const char *caller); +static inline struct ib_qp *ib_create_qp (struct ib_pd *pd, +struct ib_qp_init_attr *init_attr) +{ +return ib_create_named_qp (pd, init_attr,KBUILD_MODNAME ); +}/** * ib_modify_qp_with_udata - Modifies the attributes for the specified QP.
Signature · 1 line
2.26.2
PATCH 12/13 RDMA/core: Track device memory MRs
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Device memory (DM) are registered to MR during initialization flow, these MRs were not tracked by resource tracker and had res->valid set as a false. Update the code to manage them too.
Before this change:
[leonro@vm ~]$ ibv_rc_pingpong -j &
[leonro@vm ~]$ rdma res show mr <-- shows nothing
After this change:
[leonro@mtl-leonro-l-vm ~]$ ibv_rc_pingpong -j & [leonro@mtl-leonro-l-vm ~]$ rdma res show mr
dev ibp0s9 mrn 0 mrlen 4096 pdn 3 pid 734 comm ibv_rc_pingpong
--- drivers/infiniband/core/uverbs_std_types_mr.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/infiniband/core/uverbs_std_types_mr.c +10 -0
@@ -31,6 +31,7 @@*/ #include "rdma_core.h" +#include "restrack.h" #include "uverbs.h" #include <rdma/uverbs_std_types.h>
@@ -134,6 +135,15 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(atomic_inc (&pd->usecnt);atomic_inc (&dm->usecnt); +rdma_restrack_new (&mr->res,RDMA_RESTRACK_MR ); +rdma_restrack_set_name (&mr->res,NULL ); + ret =rdma_restrack_add (&mr->res); +if (ret) { +rdma_restrack_put (&mr->res); + pd->device->ops.dereg_mr (mr, &attrs->driver_udata); +return ret; + } + uobj->object = mr;uverbs_finalize_uobj_create (attrs,UVERBS_ATTR_REG_DM_MR_HANDLE );
Signature · 1 line
2.26.2
PATCH 13/13 RDMA/restrack: Drop valid restrack field as source of ambiguity
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
The valid field was needed to distinguish between supported/not supported QPs, after the create_qp was changed to support all types, that field can be dropped and the code simplified a little bit.
--- drivers/infiniband/core/restrack.c | 29 ++++++++--------------------- include/rdma/restrack.h | 9 --------- 2 files changed, 8 insertions(+), 30 deletions(-)
drivers/infiniband/core/restrack.c +8 -21
@@ -143,7 +143,7 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) return container_of(res, struct rdma_counter, res)->device;default :WARN_ONCE (true,"Wrong resource tracking type %u\n" , res->type); -return NULL ; +return ERR_PTR (-EINVAL ); } }
@@ -223,7 +223,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res)struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) +if (IS_ERR_OR_NULL (dev))return -ENODEV ;if (res->no_track)
@@ -261,10 +261,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res) } out: -if (ret) -return ret; - res->valid = true; -return 0 ; +return ret; }EXPORT_SYMBOL (rdma_restrack_add);
@@ -323,25 +320,16 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_del (struct rdma_restrack_entry *res) { +struct ib_device *dev =res_to_dev (res);struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev; -if (!res->valid) { -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } -return ; - } - -if (res->no_track) +WARN_ONCE (!dev && res->type !=RDMA_RESTRACK_CM_ID , +"IB device should be set for restrack type %s" , +type2str (res->type)); +if (res->no_track ||IS_ERR_OR_NULL (dev)) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) -return ; - rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id);
@@ -351,7 +339,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)WARN_ON (old != res); out: - res->valid = false;rdma_restrack_put (res);wait_for_completion (&res->comp); }
include/rdma/restrack.h +0 -9
@@ -59,15 +59,6 @@ enum rdma_restrack_type {* struct rdma_restrack_entry - metadata per-entry */ struct rdma_restrack_entry { -/** -* @valid: validity indicator -* -* The entries are filled during rdma_restrack_add, -* can be attempted to be free during rdma_restrack_del. -* -* As an example for that, see mlx5 QPs with type MLX5_IB_QPT_HW_GSI -*/ -bool valid;/** * @no_track: don't add this entry to restrack DB *
Signature · 1 line
2.26.2
Jason Gunthorpe
maintainerRe: [PATCH rdma-next v1 13/13] RDMA/restrack: Drop valid restrack field as source of ambiguity
Quoted 64 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
The valid field was needed to distinguish between supported/not supported QPs, after the
create_qpwas changed to support all types, that field can be dropped and the code simplified a little bit.Signed-off-by Leon Romanovsky <[email protected]>drivers/infiniband/core/restrack.c | 29 ++++++++--------------------- include/rdma/restrack.h | 9 --------- 2 files changed, 8 insertions(+), 30 deletions(-)drivers/infiniband/core/restrack.c +7
-16+++ b/drivers/infiniband/core/restrack.c@@ -143,7 +143,7 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) return container_of(res, struct rdma_counter, res)->device;default :WARN_ONCE (true,"Wrong resource tracking type %u\n" , res->type); -return NULL ; +return ERR_PTR (-EINVAL ); } }@@ -223,7 +223,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res)struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) +if (IS_ERR_OR_NULL (dev))return -ENODEV ;if (res->no_track)@@ -261,10 +261,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res) } out: -if (ret) -return ret; - res->valid = true; -return 0 ; +return ret; }EXPORT_SYMBOL (rdma_restrack_add);@@ -323,25 +320,16 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_del (struct rdma_restrack_entry *res) { +struct ib_device *dev =res_to_dev (res);struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev; -if (!res->valid) { -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } -return ; - } - -if (res->no_track) + WARN_ONCE(!dev && res->type != RDMA_RESTRACK_CM_ID, + "IB device should be set for restrack type %s",
drivers/infiniband/core/restrack.c EXPORT_SYMBOL(rdma_restrack_put); · line 334
Quoted 10 lines
drivers/infiniband/core/restrack.c +2
-4+ type2str(res->type)); +if (res->no_track ||IS_ERR_OR_NULL (dev)) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) -return ; - rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id);
How does this work without valid?
xa_alloc is called in rdma_restrack_add() and previously it was safe to call res_track_del() on unadded things.
Now there are problems, like __ib_alloc_cq_user() does calls restrack_del without doing restrack_ad()
drivers/infiniband/core/restrack.c void rdma_restrack_del(struct rdma_restrack_entry *res) · line 339
Quoted 2 lines
drivers/infiniband/core/restrack.c +0
-0@@ -351,7 +339,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)WARN_ON (old != res);
So this WARN_ON should trigger?
I don't think this can escape a bit that says that id is in the xarray.
I'd say no_track is a flag to add to rdma_restrack_add(), not a bit in the struct. The bit in the struct is 'valid' aka 'added_to_xarray'. The no_track flag simply doesn't set valid.
Jason
Re: [PATCH rdma-next v1 13/13] RDMA/restrack: Drop valid restrack field as source of ambiguity
Quoted 78 lines · Jason Gunthorpe
Quoted 64 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
The valid field was needed to distinguish between supported/not supported QPs, after the
create_qpwas changed to support all types, that field can be dropped and the code simplified a little bit.Signed-off-by Leon Romanovsky <[email protected]>drivers/infiniband/core/restrack.c | 29 ++++++++--------------------- include/rdma/restrack.h | 9 --------- 2 files changed, 8 insertions(+), 30 deletions(-)drivers/infiniband/core/restrack.c +7
-16+++ b/drivers/infiniband/core/restrack.c@@ -143,7 +143,7 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) return container_of(res, struct rdma_counter, res)->device;default :WARN_ONCE (true,"Wrong resource tracking type %u\n" , res->type); -return NULL ; +return ERR_PTR (-EINVAL ); } }@@ -223,7 +223,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res)struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) +if (IS_ERR_OR_NULL (dev))return -ENODEV ;if (res->no_track)@@ -261,10 +261,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res) } out: -if (ret) -return ret; - res->valid = true; -return 0 ; +return ret; }EXPORT_SYMBOL (rdma_restrack_add);@@ -323,25 +320,16 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_del (struct rdma_restrack_entry *res) { +struct ib_device *dev =res_to_dev (res);struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev; -if (!res->valid) { -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } -return ; - } - -if (res->no_track) + WARN_ONCE(!dev && res->type != RDMA_RESTRACK_CM_ID, + "IB device should be set for restrack type %s",drivers/infiniband/core/restrack.c EXPORT_SYMBOL(rdma_restrack_put); · line 334
Quoted 10 lines
drivers/infiniband/core/restrack.c +2
-4+ type2str(res->type)); +if (res->no_track ||IS_ERR_OR_NULL (dev)) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) -return ; - rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id);How does this work without valid?
Quoted 5 lines
xa_allocis called inrdma_restrack_add()and previously it was safe to callres_track_del()on unadded things.Now there are problems, like
__ib_alloc_cq_user()does callsrestrack_delwithout doingrestrack_ad()
Maybe I missed it, but I don't see it in the code.
After this series is applied, the rdma_restrack_del() can be called only on rdma_restrack_add(). This ensure that ->valid is not needed any more. Everything that is not added to DB uses rdma_restrack_new() call, which will be released by rdma_restrack_put().
Quoted 5 lines
drivers/infiniband/core/restrack.c void rdma_restrack_del(struct rdma_restrack_entry *res) · line 339
Quoted 3 lines
drivers/infiniband/core/restrack.c +0
-0@@ -351,7 +339,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)WARN_ON (old != res);So this
WARN_ONshould trigger?
It helps to find the places with calls to rdma_restrack_del() without rdma_restrack_add() before.
Quoted 3 lines
I don't think this can escape a bit that says that id is in the xarray.
Not needed, because of separation between _add() and _new().
Quoted 6 lines
I'd say
no_trackis a flag to add tordma_restrack_add(), not a bit in the struct. The bit in the struct is 'valid' aka 'added_to_xarray'. Theno_trackflag simply doesn't set valid.Jason
Jason Gunthorpe
maintainerRe: [PATCH rdma-next v1 13/13] RDMA/restrack: Drop valid restrack field as source of ambiguity
Quoted 79 lines · Leon Romanovsky
Quoted 78 lines · Jason Gunthorpe
Quoted 64 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
The valid field was needed to distinguish between supported/not supported QPs, after the
create_qpwas changed to support all types, that field can be dropped and the code simplified a little bit.Signed-off-by Leon Romanovsky <[email protected]>drivers/infiniband/core/restrack.c | 29 ++++++++--------------------- include/rdma/restrack.h | 9 --------- 2 files changed, 8 insertions(+), 30 deletions(-)drivers/infiniband/core/restrack.c +7
-16+++ b/drivers/infiniband/core/restrack.c@@ -143,7 +143,7 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) return container_of(res, struct rdma_counter, res)->device;default :WARN_ONCE (true,"Wrong resource tracking type %u\n" , res->type); -return NULL ; +return ERR_PTR (-EINVAL ); } }@@ -223,7 +223,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res)struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) +if (IS_ERR_OR_NULL (dev))return -ENODEV ;if (res->no_track)@@ -261,10 +261,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res) } out: -if (ret) -return ret; - res->valid = true; -return 0 ; +return ret; }EXPORT_SYMBOL (rdma_restrack_add);@@ -323,25 +320,16 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_del (struct rdma_restrack_entry *res) { +struct ib_device *dev =res_to_dev (res);struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev; -if (!res->valid) { -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } -return ; - } - -if (res->no_track) + WARN_ONCE(!dev && res->type != RDMA_RESTRACK_CM_ID, + "IB device should be set for restrack type %s",drivers/infiniband/core/restrack.c EXPORT_SYMBOL(rdma_restrack_put); · line 334
Quoted 10 lines
drivers/infiniband/core/restrack.c +2
-4+ type2str(res->type)); +if (res->no_track ||IS_ERR_OR_NULL (dev)) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) -return ; - rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id);How does this work without valid?
Quoted 7 lines
Quoted 5 lines
xa_allocis called inrdma_restrack_add()and previously it was safe to callres_track_del()on unadded things.Now there are problems, like
__ib_alloc_cq_user()does callsrestrack_delwithout doingrestrack_ad()Maybe I missed it, but I don't see it in the code.
Look at the error unwinding
Jason
Re: [PATCH rdma-next v1 13/13] RDMA/restrack: Drop valid restrack field as source of ambiguity
Quoted 83 lines · Jason Gunthorpe
Quoted 82 lines · Leon Romanovsky
Quoted 81 lines · Jason Gunthorpe
Quoted 64 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
The valid field was needed to distinguish between supported/not supported QPs, after the
create_qpwas changed to support all types, that field can be dropped and the code simplified a little bit.Signed-off-by Leon Romanovsky <[email protected]>drivers/infiniband/core/restrack.c | 29 ++++++++--------------------- include/rdma/restrack.h | 9 --------- 2 files changed, 8 insertions(+), 30 deletions(-)drivers/infiniband/core/restrack.c +7
-16+++ b/drivers/infiniband/core/restrack.c@@ -143,7 +143,7 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) return container_of(res, struct rdma_counter, res)->device;default :WARN_ONCE (true,"Wrong resource tracking type %u\n" , res->type); -return NULL ; +return ERR_PTR (-EINVAL ); } }@@ -223,7 +223,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res)struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) +if (IS_ERR_OR_NULL (dev))return -ENODEV ;if (res->no_track)@@ -261,10 +261,7 @@ int __must_check rdma_restrack_add(struct rdma_restrack_entry *res) } out: -if (ret) -return ret; - res->valid = true; -return 0 ; +return ret; }EXPORT_SYMBOL (rdma_restrack_add);@@ -323,25 +320,16 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_del (struct rdma_restrack_entry *res) { +struct ib_device *dev =res_to_dev (res);struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev; -if (!res->valid) { -if (res->task) { -put_task_struct (res->task); - res->task =NULL ; - } -return ; - } - -if (res->no_track) + WARN_ONCE(!dev && res->type != RDMA_RESTRACK_CM_ID, + "IB device should be set for restrack type %s",drivers/infiniband/core/restrack.c EXPORT_SYMBOL(rdma_restrack_put); · line 334
Quoted 10 lines
drivers/infiniband/core/restrack.c +2
-4+ type2str(res->type)); +if (res->no_track ||IS_ERR_OR_NULL (dev)) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) -return ; - rt = &dev->res[res->type]; old =xa_erase (&rt->xa, res->id);How does this work without valid?
xa_allocis called inrdma_restrack_add()and previously it was safe to callres_track_del()on unadded things.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
Now there are problems, like
__ib_alloc_cq_user()does callsrestrack_delwithout doingrestrack_ad()Maybe I missed it, but I don't see it in the code.
Look at the error unwinding
After this series I will call to rdma_restrack_put() and not to rdma_restrack_del(). in error unwind.
Thanks
Quoted 2 lines
Jason