RDMA/irdma: Add a refcount to track user ring MR associations

User QP/CQ/SRQ rings are registered with the normal reg_mr
mechanism prior to creating the actual QP/CQ/SRQ object. In
order to prevent userspace from deregistering these special MRs
while the child object still exists, a refcount will be used.

This commit adds the refcount and logic to reject a dereg_mr
with active references. Subsequent commits will add logic to
bump this refcount when the user QP/CQ/SRQ objects are created.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
Link: https://patch.msgid.link/20260618201458.875740-3-jmoroni@google.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
Jacob Moroni 2026-06-18 20:14:56 +00:00 committed by Leon Romanovsky
parent 097f50384e
commit a7d0a6b582
2 changed files with 18 additions and 4 deletions

View File

@ -3363,6 +3363,7 @@ static struct irdma_mr *irdma_alloc_iwmr(struct ib_umem *region,
if (!iwmr)
return ERR_PTR(-ENOMEM);
refcount_set(&iwmr->user_ring_refs, 1);
iwpbl = &iwmr->iwpbl;
iwpbl->iwmr = iwmr;
iwmr->region = region;
@ -3927,13 +3928,16 @@ static struct ib_mr *irdma_get_dma_mr(struct ib_pd *pd, int acc)
* irdma_del_memlist - Deleting pbl list entries for CQ/QP
* @iwmr: iwmr for IB's user page addresses
* @ucontext: ptr to user context
*
* Return: True if the MR is currently in-use by a QP/CQ/SRQ ring.
*/
static void irdma_del_memlist(struct irdma_mr *iwmr,
static bool irdma_del_memlist(struct irdma_mr *iwmr,
struct irdma_ucontext *ucontext)
{
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
unsigned long flags;
spinlock_t *lock;
bool in_use = false;
switch (iwmr->type) {
case IRDMA_MEMREG_TYPE_CQ:
@ -3946,15 +3950,19 @@ static void irdma_del_memlist(struct irdma_mr *iwmr,
lock = &ucontext->srq_reg_mem_list_lock;
break;
default:
return;
return false;
}
spin_lock_irqsave(lock, flags);
if (iwpbl->on_list) {
if (!refcount_dec_if_one(&iwmr->user_ring_refs)) {
in_use = true;
} else if (iwpbl->on_list) {
iwpbl->on_list = false;
list_del(&iwpbl->list);
}
spin_unlock_irqrestore(lock, flags);
return in_use;
}
/**
@ -3977,7 +3985,12 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
ucontext = rdma_udata_to_drv_context(udata,
struct irdma_ucontext,
ibucontext);
irdma_del_memlist(iwmr, ucontext);
/* Do not allow the MR to be unpinned if it is still
* backing a user ring.
*/
if (irdma_del_memlist(iwmr, ucontext))
return -EBUSY;
}
goto done;
}

View File

@ -120,6 +120,7 @@ struct irdma_mr {
u64 len;
u64 pgaddrmem[IRDMA_MAX_SAVED_PHY_PGADDR];
struct irdma_pbl iwpbl;
refcount_t user_ring_refs;
};
struct irdma_srq {