Fixes to IB_EVENT_DEVICE_FATAL logic
cover Fixes to IB_EVENT_DEVICE_FATAL logic
From: Leon Romanovsky <[email protected]>
Hi,
Two changes, pretty straightforward.
Thanks
Jason Gunthorpe (2):
RDMA/uverbs: Do not discard the IB_EVENT_DEVICE_FATAL event RDMA/uverbs: Move IB_EVENT_DEVICE_FATAL to destroy_uobj
drivers/infiniband/core/rdma_core.c | 3 +- drivers/infiniband/core/uverbs.h | 4 +++ drivers/infiniband/core/uverbs_main.c | 12 +++----- .../core/uverbs_std_types_async_fd.c | 30 ++++++++++++++++++- 4 files changed, 39 insertions(+), 10 deletions(-)
--
2.26.2
PATCH 1/2 RDMA/uverbs: Do not discard the IB_EVENT_DEVICE_FATAL event
From: Jason Gunthorpe <[email protected]>
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.
--- drivers/infiniband/core/rdma_core.c | 3 ++- drivers/infiniband/core/uverbs.h | 1 + drivers/infiniband/core/uverbs_main.c | 2 +- .../core/uverbs_std_types_async_fd.c | 26 ++++++++++++++++++- 4 files changed, 29 insertions(+), 3 deletions(-)
drivers/infiniband/core/rdma_core.c +2 -1
@@ -459,7 +459,8 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,struct ib_uobject *uobj;struct file *filp; -if (WARN_ON (fd_type->fops->release != &uverbs_uobject_fd_release)) +if (WARN_ON (fd_type->fops->release != &uverbs_uobject_fd_release && + fd_type->fops->release != &uverbs_async_event_release))return ERR_PTR (-EINVAL ); new_fd =get_unused_fd_flags (O_CLOEXEC );
drivers/infiniband/core/uverbs.h +1 -0
@@ -219,6 +219,7 @@ void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);void ib_uverbs_init_async_event_file (struct ib_uverbs_async_event_file *ev_file);void ib_uverbs_free_event_queue (struct ib_uverbs_event_queue *event_queue);void ib_uverbs_flow_resources_free (struct ib_uflow_resources *uflow_res); +int uverbs_async_event_release (struct inode *inode,struct file *filp);int ib_alloc_ucontext (struct uverbs_attr_bundle *attrs);int ib_init_ucontext (struct uverbs_attr_bundle *attrs);
drivers/infiniband/core/uverbs_main.c +1 -1
@@ -346,7 +346,7 @@ const struct file_operations uverbs_async_event_fops = { .owner = THIS_MODULE, .read = ib_uverbs_async_event_read, .poll = ib_uverbs_async_event_poll, - .release = uverbs_uobject_fd_release, + .release = uverbs_async_event_release, .fasync = ib_uverbs_async_event_fasync, .llseek = no_llseek, };
drivers/infiniband/core/uverbs_std_types_async_fd.c +25 -1
@@ -26,10 +26,34 @@ static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, container_of(uobj, struct ib_uverbs_async_event_file, uobj);ib_unregister_event_handler (&event_file->event_handler); -ib_uverbs_free_event_queue (&event_file->ev_queue);return 0 ; } +int uverbs_async_event_release (struct inode *inode,struct file *filp) +{ +struct ib_uverbs_async_event_file *event_file; +struct ib_uobject *uobj = filp->private_data; +int ret; + +if (!uobj) +return uverbs_uobject_fd_release (inode, filp); + + event_file = + container_of(uobj, struct ib_uverbs_async_event_file, uobj); + +/* +* The async event FD has to deliver IB_EVENT_DEVICE_FATAL even after +* disassociation, so cleaning the event list must only happen after +* release. The user knows it has reached the end of the event stream +* when it sees IB_EVENT_DEVICE_FATAL. +*/ +uverbs_uobject_get (uobj); + ret =uverbs_uobject_fd_release (inode, filp); +ib_uverbs_free_event_queue (&event_file->ev_queue); +uverbs_uobject_put (uobj); +return ret; +} + DECLARE_UVERBS_NAMED_METHOD( UVERBS_METHOD_ASYNC_EVENT_ALLOC, UVERBS_ATTR_FD(UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE,
Signature · 1 line
2.26.2
PATCH 2/2 RDMA/uverbs: Move IB_EVENT_DEVICE_FATAL to destroy_uobj
In reply to Leon RomanovskyFrom: Jason Gunthorpe <[email protected]>
When multiple async FDs were allowed to exist the idea what for all broadcast events to be delivered to all async FDs, however IB_EVENT_DEVICE_FATAL was missed.
Instead of having ib_uverbs_free_hw_resources() special case the global async_fd, have it cause the event during the uobject destruction. Every async fd is now a uobject so simply generate the IB_EVENT_DEVICE_FATAL while destroying the async fd uobject. This ensures every async FD gets a copy of the event.
--- drivers/infiniband/core/uverbs.h | 3 +++ drivers/infiniband/core/uverbs_main.c | 10 +++------- drivers/infiniband/core/uverbs_std_types_async_fd.c | 4 ++++ 3 files changed, 10 insertions(+), 7 deletions(-)
drivers/infiniband/core/uverbs.h +3 -0
@@ -228,6 +228,9 @@ void ib_uverbs_release_ucq(struct ib_uverbs_completion_event_file *ev_file, struct ib_ucq_object *uobj);void ib_uverbs_release_uevent (struct ib_uevent_object *uobj);void ib_uverbs_release_file (struct kref *ref); +void ib_uverbs_async_handler (struct ib_uverbs_async_event_file *async_file, +__u64 element,__u64 event, +struct list_head *obj_list,u32 *counter);void ib_uverbs_comp_handler (struct ib_cq *cq,void *cq_context);void ib_uverbs_cq_event_handler (struct ib_event *event,void *context_ptr);
drivers/infiniband/core/uverbs_main.c +3 -7
@@ -386,10 +386,9 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)kill_fasync (&ev_queue->async_queue,SIGIO ,POLL_IN ); } -static void -ib_uverbs_async_handler (struct ib_uverbs_async_event_file *async_file, -__u64 element,__u64 event,struct list_head *obj_list, -u32 *counter) +void ib_uverbs_async_handler (struct ib_uverbs_async_event_file *async_file, +__u64 element,__u64 event, +struct list_head *obj_list,u32 *counter) {struct ib_uverbs_event *entry;unsigned long flags;
@@ -1187,9 +1186,6 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,*/ mutex_unlock (&uverbs_dev->lists_mutex); -ib_uverbs_async_handler (READ_ONCE (file->async_file),0 , -IB_EVENT_DEVICE_FATAL ,NULL ,NULL ); -uverbs_destroy_ufile_hw (file,RDMA_REMOVE_DRIVER_REMOVE );kref_put (&file->ref, ib_uverbs_release_file);
drivers/infiniband/core/uverbs_std_types_async_fd.c +4 -0
@@ -26,6 +26,10 @@ static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, container_of(uobj, struct ib_uverbs_async_event_file, uobj);ib_unregister_event_handler (&event_file->event_handler); + +if (why ==RDMA_REMOVE_DRIVER_REMOVE ) +ib_uverbs_async_handler (event_file,0 ,IB_EVENT_DEVICE_FATAL , +NULL ,NULL );return 0 ; }
Signature · 1 line
2.26.2
Jason Gunthorpe
AppliedQuoted 11 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
Hi,
Two changes, pretty straightforward.
Thanks
Jason Gunthorpe (2):
RDMA/uverbs: Do not discard theIB_EVENT_DEVICE_FATALevent RDMA/uverbs: MoveIB_EVENT_DEVICE_FATALtodestroy_uobj
Applied to for-rc
Jason