Skip to content

Commit 32ed5c0

Browse files
committed
IB/uverbs: Make the write path destroy methods use the same flow as ioctl
The ridiculous dance with uobj_remove_commit() is not needed, the write path can follow the same flow as ioctl - lock and destroy the HW object then use the data left over in the uobject to form the response to userspace. Two helpers are introduced to make this flow straightforward for the caller. Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent aa72c9a commit 32ed5c0

File tree

4 files changed

+55
-92
lines changed

4 files changed

+55
-92
lines changed

drivers/infiniband/core/rdma_core.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,44 @@ static int uverbs_try_lock_object(struct ib_uobject *uobj, bool exclusive)
130130
}
131131

132132
/*
133-
* Does both rdma_lookup_get_uobject() and rdma_remove_commit_uobject(), then
134-
* returns success_res on success (negative errno on failure). For use by
135-
* callers that do not need the uobj.
133+
* uobj_get_destroy destroys the HW object and returns a handle to the uobj
134+
* with a NULL object pointer. The caller must pair this with
135+
* uverbs_put_destroy.
136136
*/
137-
int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
138-
struct ib_uverbs_file *ufile, int success_res)
137+
struct ib_uobject *__uobj_get_destroy(const struct uverbs_obj_type *type,
138+
u32 id, struct ib_uverbs_file *ufile)
139139
{
140140
struct ib_uobject *uobj;
141141
int ret;
142142

143143
uobj = rdma_lookup_get_uobject(type, ufile, id, true);
144144
if (IS_ERR(uobj))
145-
return PTR_ERR(uobj);
145+
return uobj;
146146

147-
ret = rdma_remove_commit_uobject(uobj);
148-
if (ret)
149-
return ret;
147+
ret = rdma_explicit_destroy(uobj);
148+
if (ret) {
149+
rdma_lookup_put_uobject(uobj, true);
150+
return ERR_PTR(ret);
151+
}
152+
153+
return uobj;
154+
}
150155

156+
/*
157+
* Does both uobj_get_destroy() and uobj_put_destroy(). Returns success_res
158+
* on success (negative errno on failure). For use by callers that do not need
159+
* the uobj.
160+
*/
161+
int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
162+
struct ib_uverbs_file *ufile, int success_res)
163+
{
164+
struct ib_uobject *uobj;
165+
166+
uobj = __uobj_get_destroy(type, id, ufile);
167+
if (IS_ERR(uobj))
168+
return PTR_ERR(uobj);
169+
170+
rdma_lookup_put_uobject(uobj, true);
151171
return success_res;
152172
}
153173

@@ -449,21 +469,6 @@ static int __must_check _rdma_remove_commit_uobject(struct ib_uobject *uobj,
449469
return ret;
450470
}
451471

452-
/* This is called only for user requested DESTROY reasons
453-
* rdma_lookup_get_uobject(exclusive=true) must have been called to get uobj,
454-
* and after this returns the corresponding put has been done, and the kref
455-
* for uobj has been consumed.
456-
*/
457-
int __must_check rdma_remove_commit_uobject(struct ib_uobject *uobj)
458-
{
459-
int ret;
460-
461-
ret = rdma_explicit_destroy(uobj);
462-
/* Pairs with the lookup_get done by the caller */
463-
rdma_lookup_put_uobject(uobj, true);
464-
return ret;
465-
}
466-
467472
int rdma_explicit_destroy(struct ib_uobject *uobject)
468473
{
469474
int ret;

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 15 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,37 +1304,22 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
13041304
struct ib_uverbs_destroy_cq cmd;
13051305
struct ib_uverbs_destroy_cq_resp resp;
13061306
struct ib_uobject *uobj;
1307-
struct ib_cq *cq;
13081307
struct ib_ucq_object *obj;
1309-
int ret = -EINVAL;
13101308

13111309
if (copy_from_user(&cmd, buf, sizeof cmd))
13121310
return -EFAULT;
13131311

1314-
uobj = uobj_get_write(UVERBS_OBJECT_CQ, cmd.cq_handle, file);
1312+
uobj = uobj_get_destroy(UVERBS_OBJECT_CQ, cmd.cq_handle, file);
13151313
if (IS_ERR(uobj))
13161314
return PTR_ERR(uobj);
13171315

1318-
/*
1319-
* Make sure we don't free the memory in remove_commit as we still
1320-
* needs the uobject memory to create the response.
1321-
*/
1322-
uverbs_uobject_get(uobj);
1323-
cq = uobj->object;
1324-
obj = container_of(cq->uobject, struct ib_ucq_object, uobject);
1325-
1316+
obj = container_of(uobj, struct ib_ucq_object, uobject);
13261317
memset(&resp, 0, sizeof(resp));
1327-
1328-
ret = uobj_remove_commit(uobj);
1329-
if (ret) {
1330-
uverbs_uobject_put(uobj);
1331-
return ret;
1332-
}
1333-
13341318
resp.comp_events_reported = obj->comp_events_reported;
13351319
resp.async_events_reported = obj->async_events_reported;
13361320

1337-
uverbs_uobject_put(uobj);
1321+
uobj_put_destroy(uobj);
1322+
13381323
if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp))
13391324
return -EFAULT;
13401325

@@ -2104,32 +2089,19 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
21042089
struct ib_uverbs_destroy_qp_resp resp;
21052090
struct ib_uobject *uobj;
21062091
struct ib_uqp_object *obj;
2107-
int ret = -EINVAL;
21082092

21092093
if (copy_from_user(&cmd, buf, sizeof cmd))
21102094
return -EFAULT;
21112095

2112-
memset(&resp, 0, sizeof resp);
2113-
2114-
uobj = uobj_get_write(UVERBS_OBJECT_QP, cmd.qp_handle, file);
2096+
uobj = uobj_get_destroy(UVERBS_OBJECT_QP, cmd.qp_handle, file);
21152097
if (IS_ERR(uobj))
21162098
return PTR_ERR(uobj);
21172099

21182100
obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
2119-
/*
2120-
* Make sure we don't free the memory in remove_commit as we still
2121-
* needs the uobject memory to create the response.
2122-
*/
2123-
uverbs_uobject_get(uobj);
2124-
2125-
ret = uobj_remove_commit(uobj);
2126-
if (ret) {
2127-
uverbs_uobject_put(uobj);
2128-
return ret;
2129-
}
2130-
2101+
memset(&resp, 0, sizeof(resp));
21312102
resp.events_reported = obj->uevent.events_reported;
2132-
uverbs_uobject_put(uobj);
2103+
2104+
uobj_put_destroy(uobj);
21332105

21342106
if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof resp))
21352107
return -EFAULT;
@@ -3198,22 +3170,14 @@ int ib_uverbs_ex_destroy_wq(struct ib_uverbs_file *file,
31983170
return -EOPNOTSUPP;
31993171

32003172
resp.response_length = required_resp_len;
3201-
uobj = uobj_get_write(UVERBS_OBJECT_WQ, cmd.wq_handle, file);
3173+
uobj = uobj_get_destroy(UVERBS_OBJECT_WQ, cmd.wq_handle, file);
32023174
if (IS_ERR(uobj))
32033175
return PTR_ERR(uobj);
32043176

32053177
obj = container_of(uobj, struct ib_uwq_object, uevent.uobject);
3206-
/*
3207-
* Make sure we don't free the memory in remove_commit as we still
3208-
* needs the uobject memory to create the response.
3209-
*/
3210-
uverbs_uobject_get(uobj);
3211-
3212-
ret = uobj_remove_commit(uobj);
32133178
resp.events_reported = obj->uevent.events_reported;
3214-
uverbs_uobject_put(uobj);
3215-
if (ret)
3216-
return ret;
3179+
3180+
uobj_put_destroy(uobj);
32173181

32183182
return ib_copy_to_udata(ucore, &resp, resp.response_length);
32193183
}
@@ -3920,31 +3884,20 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
39203884
struct ib_uverbs_destroy_srq_resp resp;
39213885
struct ib_uobject *uobj;
39223886
struct ib_uevent_object *obj;
3923-
int ret = -EINVAL;
39243887

39253888
if (copy_from_user(&cmd, buf, sizeof cmd))
39263889
return -EFAULT;
39273890

3928-
uobj = uobj_get_write(UVERBS_OBJECT_SRQ, cmd.srq_handle, file);
3891+
uobj = uobj_get_destroy(UVERBS_OBJECT_SRQ, cmd.srq_handle, file);
39293892
if (IS_ERR(uobj))
39303893
return PTR_ERR(uobj);
39313894

39323895
obj = container_of(uobj, struct ib_uevent_object, uobject);
3933-
/*
3934-
* Make sure we don't free the memory in remove_commit as we still
3935-
* needs the uobject memory to create the response.
3936-
*/
3937-
uverbs_uobject_get(uobj);
3938-
39393896
memset(&resp, 0, sizeof(resp));
3940-
3941-
ret = uobj_remove_commit(uobj);
3942-
if (ret) {
3943-
uverbs_uobject_put(uobj);
3944-
return ret;
3945-
}
39463897
resp.events_reported = obj->events_reported;
3947-
uverbs_uobject_put(uobj);
3898+
3899+
uobj_put_destroy(uobj);
3900+
39483901
if (copy_to_user(u64_to_user_ptr(cmd.response), &resp, sizeof(resp)))
39493902
return -EFAULT;
39503903

include/rdma/uverbs_std_types.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
8484
__uobj_perform_destroy(uobj_get_type(_type), _uobj_check_id(_id), \
8585
_ufile, _success_res)
8686

87+
struct ib_uobject *__uobj_get_destroy(const struct uverbs_obj_type *type,
88+
u32 id, struct ib_uverbs_file *ufile);
89+
90+
#define uobj_get_destroy(_type, _id, _ufile) \
91+
__uobj_get_destroy(uobj_get_type(_type), _uobj_check_id(_id), _ufile)
92+
93+
static inline void uobj_put_destroy(struct ib_uobject *uobj)
94+
{
95+
rdma_lookup_put_uobject(uobj, true);
96+
}
97+
8798
static inline void uobj_put_read(struct ib_uobject *uobj)
8899
{
89100
rdma_lookup_put_uobject(uobj, false);
@@ -97,11 +108,6 @@ static inline void uobj_put_write(struct ib_uobject *uobj)
97108
rdma_lookup_put_uobject(uobj, true);
98109
}
99110

100-
static inline int __must_check uobj_remove_commit(struct ib_uobject *uobj)
101-
{
102-
return rdma_remove_commit_uobject(uobj);
103-
}
104-
105111
static inline int __must_check uobj_alloc_commit(struct ib_uobject *uobj,
106112
int success_res)
107113
{

include/rdma/uverbs_types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj, bool exclusive);
126126
struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_obj_type *type,
127127
struct ib_uverbs_file *ufile);
128128
void rdma_alloc_abort_uobject(struct ib_uobject *uobj);
129-
int __must_check rdma_remove_commit_uobject(struct ib_uobject *uobj);
130129
int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj);
131130
int rdma_explicit_destroy(struct ib_uobject *uobject);
132131

0 commit comments

Comments
 (0)