If the callback on the error path returns non-zero after a concurrent ib_sa_free_multicast() already dropped the initial member reference, dropping our temporary reference completes the waiter, which then frees the member before ib_sa_free_multicast() dereferences it again. Only free the multicast member when our reference decrement was not the last one; otherwise the concurrent free is already in flight. Fixes: faec2f7b96b5 ("IB/sa: Track multicast join/leave requests") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang --- drivers/infiniband/core/multicast.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index bea7df3dd8f3..aa6fdac5fcde 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c @@ -409,8 +409,9 @@ static void process_group_error(struct mcast_group *group) ret = member->multicast.callback(-ENETRESET, &member->multicast); - deref_member(member); - if (ret) + if (refcount_dec_and_test(&member->refcount)) + complete(&member->comp); + else if (ret) ib_sa_free_multicast(&member->multicast); spin_lock_irq(&group->lock); } -- 2.34.1