mirror of
https://github.com/torvalds/linux.git
synced 2026-09-25 17:42:03 +02:00
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:
parent
097f50384e
commit
a7d0a6b582
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user