Skip to content

Commit c485b19

Browse files
committed
RDMA/uverbs: Do not discard the IB_EVENT_DEVICE_FATAL event
The commit below moved all of the destruction to the disassociate step and cleaned up the event channel during destroy_uobj. However, when ib_uverbs_free_hw_resources() pushes IB_EVENT_DEVICE_FATAL and then immediately goes to destroy all uobjects this causes ib_uverbs_free_event_queue() to discard the queued event if userspace hasn't already read() it. Unlike all other event queues async FD needs to defer the ib_uverbs_free_event_queue() until FD release. This still unregisters the handler from the IB device during disassociation. Fixes: 3e032c0 ("RDMA/core: Make ib_uverbs_async_event_file into a uobject") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Yishai Hadas <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent c8b1f34 commit c485b19

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

drivers/infiniband/core/rdma_core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,8 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
459459
struct ib_uobject *uobj;
460460
struct file *filp;
461461

462-
if (WARN_ON(fd_type->fops->release != &uverbs_uobject_fd_release))
462+
if (WARN_ON(fd_type->fops->release != &uverbs_uobject_fd_release &&
463+
fd_type->fops->release != &uverbs_async_event_release))
463464
return ERR_PTR(-EINVAL);
464465

465466
new_fd = get_unused_fd_flags(O_CLOEXEC);

drivers/infiniband/core/uverbs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);
219219
void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file);
220220
void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue);
221221
void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);
222+
int uverbs_async_event_release(struct inode *inode, struct file *filp);
222223

223224
int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs);
224225
int ib_init_ucontext(struct uverbs_attr_bundle *attrs);

drivers/infiniband/core/uverbs_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ const struct file_operations uverbs_async_event_fops = {
346346
.owner = THIS_MODULE,
347347
.read = ib_uverbs_async_event_read,
348348
.poll = ib_uverbs_async_event_poll,
349-
.release = uverbs_uobject_fd_release,
349+
.release = uverbs_async_event_release,
350350
.fasync = ib_uverbs_async_event_fasync,
351351
.llseek = no_llseek,
352352
};

drivers/infiniband/core/uverbs_std_types_async_fd.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,34 @@ static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj,
2626
container_of(uobj, struct ib_uverbs_async_event_file, uobj);
2727

2828
ib_unregister_event_handler(&event_file->event_handler);
29-
ib_uverbs_free_event_queue(&event_file->ev_queue);
3029
return 0;
3130
}
3231

32+
int uverbs_async_event_release(struct inode *inode, struct file *filp)
33+
{
34+
struct ib_uverbs_async_event_file *event_file;
35+
struct ib_uobject *uobj = filp->private_data;
36+
int ret;
37+
38+
if (!uobj)
39+
return uverbs_uobject_fd_release(inode, filp);
40+
41+
event_file =
42+
container_of(uobj, struct ib_uverbs_async_event_file, uobj);
43+
44+
/*
45+
* The async event FD has to deliver IB_EVENT_DEVICE_FATAL even after
46+
* disassociation, so cleaning the event list must only happen after
47+
* release. The user knows it has reached the end of the event stream
48+
* when it sees IB_EVENT_DEVICE_FATAL.
49+
*/
50+
uverbs_uobject_get(uobj);
51+
ret = uverbs_uobject_fd_release(inode, filp);
52+
ib_uverbs_free_event_queue(&event_file->ev_queue);
53+
uverbs_uobject_put(uobj);
54+
return ret;
55+
}
56+
3357
DECLARE_UVERBS_NAMED_METHOD(
3458
UVERBS_METHOD_ASYNC_EVENT_ALLOC,
3559
UVERBS_ATTR_FD(UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE,

0 commit comments

Comments
 (0)