RDMA/core: Prevent destroying in-use completion counters

Reject comp_cntr destroy while it is attached to any QP. Track
attachments using an xarray in ib_qp keyed by the attach op_mask.
Use op bitmask to reject overlapping attaches early.

Reviewed-by: Yonatan Nachum <ynachum@amazon.com>
Signed-off-by: Michael Margolin <mrgolin@amazon.com>
Link: https://patch.msgid.link/20260722083603.30334-3-mrgolin@amazon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
Michael Margolin 2026-07-22 08:35:59 +00:00 committed by Leon Romanovsky
parent b3818ea4ad
commit 45e537bf58
4 changed files with 31 additions and 1 deletions

View File

@ -13,6 +13,9 @@ static int uverbs_free_comp_cntr(struct ib_uobject *uobject, enum rdma_remove_re
struct ib_comp_cntr *cc = uobject->object;
int ret;
if (atomic_read(&cc->usecnt))
return -EBUSY;
ret = cc->device->ops.destroy_comp_cntr(cc);
if (ret)
return ret;

View File

@ -403,7 +403,23 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_ATTACH_COMP_CNTR)(
if (!attr.op_mask)
return -EINVAL;
return qp->device->ops.qp_attach_comp_cntr(qp, cc, &attr);
if (attr.op_mask & qp->comp_cntr_op_mask)
return -EBUSY;
ret = xa_err(xa_store(&qp->comp_cntrs, attr.op_mask, cc, GFP_KERNEL));
if (ret)
return ret;
ret = qp->device->ops.qp_attach_comp_cntr(qp, cc, &attr);
if (ret) {
xa_erase(&qp->comp_cntrs, attr.op_mask);
return ret;
}
atomic_inc(&cc->usecnt);
qp->comp_cntr_op_mask |= attr.op_mask;
return 0;
}
DECLARE_UVERBS_NAMED_METHOD(

View File

@ -1300,6 +1300,7 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
qp->qp_context = attr->qp_context;
spin_lock_init(&qp->mr_lock);
xa_init(&qp->comp_cntrs);
INIT_LIST_HEAD(&qp->rdma_mrs);
INIT_LIST_HEAD(&qp->sig_mrs);
init_completion(&qp->srq_completion);
@ -1334,6 +1335,7 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
qp, uattrs ? uverbs_get_cleared_udata(uattrs) : NULL);
err_create:
rdma_restrack_put(&qp->res);
xa_destroy(&qp->comp_cntrs);
kfree(qp);
return ERR_PTR(ret);
@ -2151,6 +2153,8 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
struct ib_qp_security *sec;
struct ib_comp_cntr *cc;
unsigned long index;
int ret;
WARN_ON_ONCE(qp->mrs_used > 0);
@ -2184,6 +2188,10 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
if (av_sgid_attr)
rdma_put_gid_attr(av_sgid_attr);
xa_for_each(&qp->comp_cntrs, index, cc)
atomic_dec(&cc->usecnt);
xa_destroy(&qp->comp_cntrs);
ib_qp_usecnt_dec(qp);
if (sec)
ib_destroy_qp_security_end(sec);

View File

@ -1758,6 +1758,7 @@ enum ib_qp_attach_comp_cntr_op {
struct ib_comp_cntr {
struct ib_device *device;
struct ib_uobject *uobject;
atomic_t usecnt;
};
enum ib_comp_cntr_entry {
@ -1944,6 +1945,8 @@ struct ib_qp {
struct completion srq_completion;
struct ib_xrcd *xrcd; /* XRC TGT QPs only */
struct list_head xrcd_list;
struct xarray comp_cntrs; /* op_mask -> comp_cntr */
u32 comp_cntr_op_mask;
/* count times opened, mcast attaches, flow attaches */
atomic_t usecnt;