Commit def4cd43 authored by Shay Drory's avatar Shay Drory Committed by Jason Gunthorpe
Browse files

IB/umad: Return EPOLLERR in case of when device disassociated

Currently, polling a umad device will always works, even if the device was
disassociated. A disassociated device should immediately return EPOLLERR
from poll(). Otherwise userspace is endlessly hung on poll() with no idea
that the device has been removed from the system.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Link: https://lore.kernel.org/r/20210125121339.837518-3-leon@kernel.org


Signed-off-by: default avatarShay Drory <shayd@nvidia.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 4fc54618
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -397,6 +397,11 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
		mutex_lock(&file->mutex);
	}

	if (file->agents_dead) {
		mutex_unlock(&file->mutex);
		return -EIO;
	}

	packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
	list_del(&packet->list);

@@ -658,10 +663,14 @@ static __poll_t ib_umad_poll(struct file *filp, struct poll_table_struct *wait)
	/* we will always be able to post a MAD send */
	__poll_t mask = EPOLLOUT | EPOLLWRNORM;

	mutex_lock(&file->mutex);
	poll_wait(filp, &file->recv_wait, wait);

	if (!list_empty(&file->recv_list))
		mask |= EPOLLIN | EPOLLRDNORM;
	if (file->agents_dead)
		mask = EPOLLERR;
	mutex_unlock(&file->mutex);

	return mask;
}
@@ -1341,6 +1350,7 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
	list_for_each_entry(file, &port->file_list, port_list) {
		mutex_lock(&file->mutex);
		file->agents_dead = 1;
		wake_up_interruptible(&file->recv_wait);
		mutex_unlock(&file->mutex);

		for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)