Don't use POLLNVAL as a return value from the client side poll

function. Many existing clients don't understand POLLNVAL and instead
relies on an error code from the read(), write() or ioctl() system
call. Also make sure we wakeup any client pollers before the cuse
server is closing, so they don't wait forever for an event.
This commit is contained in:
Hans Petter Selasky 2015-01-13 13:32:18 +00:00
parent 43d5c9f65a
commit 9570004318
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=277127

View File

@ -142,6 +142,7 @@ static struct cuse_server *cuse_alloc_unit[CUSE_DEVICES_MAX];
static int cuse_alloc_unit_id[CUSE_DEVICES_MAX];
static struct cuse_memory cuse_mem[CUSE_ALLOC_UNIT_MAX];
static void cuse_server_wakeup_all_client_locked(struct cuse_server *pcs);
static void cuse_client_kqfilter_read_detach(struct knote *kn);
static void cuse_client_kqfilter_write_detach(struct knote *kn);
static int cuse_client_kqfilter_read_event(struct knote *kn, long hint);
@ -648,6 +649,8 @@ cuse_server_free(void *arg)
return;
}
cuse_server_is_closing(pcs);
/* final client wakeup, if any */
cuse_server_wakeup_all_client_locked(pcs);
TAILQ_REMOVE(&cuse_server_head, pcs, entry);
@ -716,6 +719,9 @@ cuse_server_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
cuse_lock();
cuse_server_is_closing(pcs);
/* final client wakeup, if any */
cuse_server_wakeup_all_client_locked(pcs);
knlist_clear(&pcs->selinfo.si_note, 1);
cuse_unlock();
@ -920,6 +926,18 @@ cuse_server_wakeup_locked(struct cuse_server *pcs)
KNOTE_LOCKED(&pcs->selinfo.si_note, 0);
}
static void
cuse_server_wakeup_all_client_locked(struct cuse_server *pcs)
{
struct cuse_client *pcc;
TAILQ_FOREACH(pcc, &pcs->hcli, entry) {
pcc->cflags |= (CUSE_CLI_KNOTE_NEED_READ |
CUSE_CLI_KNOTE_NEED_WRITE);
}
cuse_server_wakeup_locked(pcs);
}
static int
cuse_free_unit_by_id_locked(struct cuse_server *pcs, int id)
{
@ -1226,11 +1244,7 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
* We don't know which direction caused the event.
* Wakeup both!
*/
TAILQ_FOREACH(pcc, &pcs->hcli, entry) {
pcc->cflags |= (CUSE_CLI_KNOTE_NEED_READ |
CUSE_CLI_KNOTE_NEED_WRITE);
}
cuse_server_wakeup_locked(pcs);
cuse_server_wakeup_all_client_locked(pcs);
cuse_unlock();
break;
@ -1677,7 +1691,7 @@ cuse_client_poll(struct cdev *dev, int events, struct thread *td)
error = cuse_client_get(&pcc);
if (error != 0)
return (POLLNVAL);
goto pollnval;
temp = 0;
@ -1705,8 +1719,10 @@ cuse_client_poll(struct cdev *dev, int events, struct thread *td)
error = cuse_client_receive_command_locked(pccmd, 0, 0);
cuse_unlock();
cuse_cmd_unlock(pccmd);
if (error < 0) {
revents = POLLNVAL;
goto pollnval;
} else {
revents = 0;
if (error & CUSE_POLL_READ)
@ -1716,10 +1732,12 @@ cuse_client_poll(struct cdev *dev, int events, struct thread *td)
if (error & CUSE_POLL_ERROR)
revents |= (events & POLLHUP);
}
cuse_cmd_unlock(pccmd);
return (revents);
pollnval:
/* XXX many clients don't understand POLLNVAL */
return (events & (POLLHUP | POLLPRI | POLLIN |
POLLRDNORM | POLLOUT | POLLWRNORM));
}
static int