=========================================================================================
@@ -1382,6 +1382,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
struct ib_uobject *uobj;
struct ib_qp *qp;
struct ib_uqp_object *obj;
+ struct ib_xrcd *xrcd;
int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1400,6 +1401,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
return -EBUSY;
}
+ xrcd = qp->xrcd;
ret = ib_destroy_qp(qp);
if (!ret)
uobj->live = 0;
@@ -1409,7 +1411,8 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
if (ret)
return ret;
- atomic_dec(&obj->uxrcd->refcnt);
+ if (xrcd)
+ atomic_dec(&obj->uxrcd->refcnt);
idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
@@ -2294,6 +2297,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
struct ib_uobject *uobj;
struct ib_srq *srq;
struct ib_usrq_object *obj;
+ struct ib_xrcd *xrcd;
int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -2305,6 +2309,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
srq = uobj->object;
obj = container_of(uobj, struct ib_usrq_object, uevent.uobject);
+ xrcd = srq->xrcd;
ret = ib_destroy_srq(srq);
if (!ret)
uobj->live = 0;
@@ -2314,7 +2319,8 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
if (ret)
return ret;
- atomic_dec(&obj->uxrcd->refcnt);
+ if (xrcd)
+ atomic_dec(&obj->uxrcd->refcnt);
idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
@@ -2604,12 +2610,9 @@ ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
live = uobj->live;
- if (inode && ret)
- atomic_inc(&xrcd->usecnt);
-
put_uobj_write(uobj);
- if (ret)
+ if (ret && !inode)
goto out;
if (inode && !live)
@@ -2637,15 +2640,10 @@ void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
int ret = 0;
inode = xrcd->inode;
- if (inode && !atomic_dec_and_test(&xrcd->usecnt))
- return;
+ if (inode)
+ atomic_dec(&xrcd->usecnt);
ret = ib_dealloc_xrcd(xrcd);
-
- if (inode) {
- if (!ret)
- xrcd_table_delete(dev, inode);
- else
- atomic_inc(&xrcd->usecnt);
- }
+ if (!ret && inode)
+ xrcd_table_delete(dev, inode);
}