svn commit: r319501 - head/sys/compat/linuxkpi/common/src
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Jun 2 16:52:19 UTC 2017
Author: hselasky
Date: Fri Jun 2 16:52:18 2017
New Revision: 319501
URL: https://svnweb.freebsd.org/changeset/base/319501
Log:
Improve kqueue() support in the LinuxKPI. Some applications using the
kqueue() does not set non-blocking I/O mode for event driven read of
file descriptors. This means the LinuxKPI internal kqueue read and
write event flags must be updated before the next read and/or write
system call. Else the read and/or write system call may block. This
can happen when there is no more data to read following a previous
read event. Then the application also gets blocked from processing
other events. This situation can also be solved by the applications
setting and using non-blocking I/O mode.
MFC after: 1 week
Sponsored by: Mellanox Technologies
Modified:
head/sys/compat/linuxkpi/common/src/linux_compat.c
Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c Fri Jun 2 16:30:40 2017 (r319500)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c Fri Jun 2 16:52:18 2017 (r319501)
@@ -438,7 +438,7 @@ linux_kq_lock_unowned(void *arg)
}
static void
-linux_dev_kqfilter_poll(struct linux_file *);
+linux_dev_kqfilter_poll(struct linux_file *, int);
struct linux_file *
linux_file_alloc(void)
@@ -856,9 +856,11 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t
current->bsd_ioctl_len = 0;
}
- if (error == EWOULDBLOCK)
- linux_dev_kqfilter_poll(filp);
- else if (error == ERESTARTSYS)
+ if (error == EWOULDBLOCK) {
+ /* update kqfilter status, if any */
+ linux_dev_kqfilter_poll(filp,
+ LINUX_KQ_FLAG_HAS_READ | LINUX_KQ_FLAG_HAS_WRITE);
+ } else if (error == ERESTARTSYS)
error = ERESTART;
return (error);
}
@@ -893,14 +895,15 @@ linux_dev_read(struct cdev *dev, struct uio *uio, int
uio->uio_resid -= bytes;
} else {
error = -bytes;
- if (error == EWOULDBLOCK)
- linux_dev_kqfilter_poll(filp);
- else if (error == ERESTARTSYS)
+ if (error == ERESTARTSYS)
error = ERESTART;
}
} else
error = ENXIO;
+ /* update kqfilter status, if any */
+ linux_dev_kqfilter_poll(filp, LINUX_KQ_FLAG_HAS_READ);
+
return (error);
}
@@ -934,14 +937,15 @@ linux_dev_write(struct cdev *dev, struct uio *uio, int
uio->uio_resid -= bytes;
} else {
error = -bytes;
- if (error == EWOULDBLOCK)
- linux_dev_kqfilter_poll(filp);
- else if (error == ERESTARTSYS)
+ if (error == ERESTARTSYS)
error = ERESTART;
}
} else
error = ENXIO;
+ /* update kqfilter status, if any */
+ linux_dev_kqfilter_poll(filp, LINUX_KQ_FLAG_HAS_WRITE);
+
return (error);
}
@@ -1032,21 +1036,20 @@ static struct filterops linux_dev_kqfiltops_write = {
};
static void
-linux_dev_kqfilter_poll(struct linux_file *filp)
+linux_dev_kqfilter_poll(struct linux_file *filp, int kqflags)
{
int temp;
- spin_lock(&filp->f_kqlock);
- temp = (filp->f_kqflags & (LINUX_KQ_FLAG_HAS_READ | LINUX_KQ_FLAG_HAS_WRITE));
- filp->f_kqflags &= ~(LINUX_KQ_FLAG_NEED_READ | LINUX_KQ_FLAG_NEED_WRITE);
- spin_unlock(&filp->f_kqlock);
-
- if (temp != 0) {
+ if (filp->f_kqflags & kqflags) {
/* get the latest polling state */
temp = filp->f_op->poll(filp, NULL);
+ spin_lock(&filp->f_kqlock);
+ /* clear kqflags */
+ filp->f_kqflags &= ~(LINUX_KQ_FLAG_NEED_READ |
+ LINUX_KQ_FLAG_NEED_WRITE);
+ /* update kqflags */
if (temp & (POLLIN | POLLOUT)) {
- spin_lock(&filp->f_kqlock);
if (temp & POLLIN)
filp->f_kqflags |= LINUX_KQ_FLAG_NEED_READ;
if (temp & POLLOUT)
@@ -1054,8 +1057,8 @@ linux_dev_kqfilter_poll(struct linux_file *filp)
/* make sure the "knote" gets woken up */
KNOTE_LOCKED(&filp->f_selinfo.si_note, 0);
- spin_unlock(&filp->f_kqlock);
}
+ spin_unlock(&filp->f_kqlock);
}
}
@@ -1099,7 +1102,10 @@ linux_dev_kqfilter(struct cdev *dev, struct knote *kn)
if (error == 0) {
linux_set_current(td);
- linux_dev_kqfilter_poll(filp);
+
+ /* update kqfilter status, if any */
+ linux_dev_kqfilter_poll(filp,
+ LINUX_KQ_FLAG_HAS_READ | LINUX_KQ_FLAG_HAS_WRITE);
}
return (error);
}
More information about the svn-src-head
mailing list