Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/uverbs: Fix to consider event queue closing also upon non-blocking mode

Fix ib_uverbs_event_read() to consider event queue closing also upon
non-blocking mode.

Once the queue is closed (e.g. hot-plug flow) all the existing events
are cleaned-up as part of ib_uverbs_free_event_queue().

An application that uses the non-blocking FD mode should get -EIO in
that case to let it knows that the device was removed already.

Otherwise, it can loose the indication that the device was removed and
won't recover.

As part of that, refactor the code to have a single flow with regards to
'is_closed' for both blocking and non-blocking modes.

Fixes: 14e23bd6d221 ("RDMA/core: Fix locking in ib_uverbs_event_read")
Reviewed-by: Maor Gottlieb <maorg@nvidia.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Link: https://lore.kernel.org/r/97b00116a1e1e13f8dc4ec38a5ea81cf8c030210.1685960567.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Yishai Hadas and committed by
Leon Romanovsky
62fab312 0cadb4db

+5 -7
+5 -7
drivers/infiniband/core/uverbs_main.c
··· 222 222 spin_lock_irq(&ev_queue->lock); 223 223 224 224 while (list_empty(&ev_queue->event_list)) { 225 - spin_unlock_irq(&ev_queue->lock); 225 + if (ev_queue->is_closed) { 226 + spin_unlock_irq(&ev_queue->lock); 227 + return -EIO; 228 + } 226 229 230 + spin_unlock_irq(&ev_queue->lock); 227 231 if (filp->f_flags & O_NONBLOCK) 228 232 return -EAGAIN; 229 233 ··· 237 233 return -ERESTARTSYS; 238 234 239 235 spin_lock_irq(&ev_queue->lock); 240 - 241 - /* If device was disassociated and no event exists set an error */ 242 - if (list_empty(&ev_queue->event_list) && ev_queue->is_closed) { 243 - spin_unlock_irq(&ev_queue->lock); 244 - return -EIO; 245 - } 246 236 } 247 237 248 238 event = list_entry(ev_queue->event_list.next, struct ib_uverbs_event, list);