Page MenuHomeFreeBSD

D50826.id156977.diff
No OneTemporary

D50826.id156977.diff

diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -278,15 +278,17 @@
return (events &
(POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
+ if (fdata_get_dead(data))
+ revents |= POLLHUP;
if (events & (POLLIN | POLLRDNORM)) {
fuse_lck_mtx_lock(data->ms_mtx);
- if (fdata_get_dead(data) || STAILQ_FIRST(&data->ms_head))
+ if (STAILQ_FIRST(&data->ms_head))
revents |= events & (POLLIN | POLLRDNORM);
else
selrecord(td, &data->ks_rsel);
fuse_lck_mtx_unlock(data->ms_mtx);
}
- if (events & (POLLOUT | POLLWRNORM)) {
+ if (!fdata_get_dead(data) && (events & (POLLOUT | POLLWRNORM))) {
revents |= events & (POLLOUT | POLLWRNORM);
}
return (revents);
@@ -319,6 +321,10 @@
"we know early on that reader should be kicked so we "
"don't wait for news");
fuse_lck_mtx_unlock(data->ms_mtx);
+ /*
+ * ENXIO would make more sense. But return ENODEV for
+ * compatibility with the Linux implementation.
+ */
return (ENODEV);
}
if (!(tick = fuse_ms_pop(data))) {
diff --git a/tests/sys/fs/fusefs/dev_fuse_poll.cc b/tests/sys/fs/fusefs/dev_fuse_poll.cc
--- a/tests/sys/fs/fusefs/dev_fuse_poll.cc
+++ b/tests/sys/fs/fusefs/dev_fuse_poll.cc
@@ -33,7 +33,10 @@
*/
extern "C" {
+#include <sys/event.h>
+
#include <fcntl.h>
+#include <poll.h>
#include <semaphore.h>
#include <unistd.h>
}
@@ -79,6 +82,13 @@
}
};
+class Poll: public FuseTest {
+ virtual void SetUp() {
+ m_pm = POLL;
+ FuseTest::SetUp();
+ }
+};
+
TEST_P(DevFusePoll, access)
{
expect_access(FUSE_ROOT_ID, X_OK, 0);
@@ -227,3 +237,46 @@
sem_destroy(&sem0);
sem_destroy(&sem1);
}
+
+/* After unmount, kevent(/dev/fuse) should return EV_EOF */
+TEST_F(Kqueue, HUP)
+{
+ struct timespec timeout_ts;
+ struct kevent changes[1];
+ struct kevent events[1];
+ const int timeout_ms = 999;
+ int nready;
+
+ expect_destroy(0);
+
+ m_mock->unmount();
+ timeout_ts.tv_sec = 0;
+ timeout_ts.tv_nsec = timeout_ms * 1'000'000;
+ EV_SET(&changes[0], m_mock->m_fuse_fd, EVFILT_READ, EV_ADD | EV_ONESHOT,
+ 0, 0, 0);
+ nready = kevent(m_mock->m_kq, &changes[0], 1, &events[0], 1,
+ &timeout_ts);
+ ASSERT_LE(0, nready) << strerror(errno);
+ ASSERT_EQ(1, nready);
+ ASSERT_EQ(events[0].ident, (uintptr_t)m_mock->m_fuse_fd);
+ ASSERT_TRUE(events[0].flags & EV_EOF);
+}
+
+/* After unmount, poll(/dev/fuse) should return POLLHUP */
+TEST_F(Poll, HUP)
+{
+ const int timeout_ms = 999;
+ pollfd fds[1];
+ int nready;
+
+ expect_destroy(0);
+
+ m_mock->unmount();
+ fds[0].fd = m_mock->m_fuse_fd;
+ fds[0].events = POLLIN | POLLOUT;
+ nready = poll(fds, 1, timeout_ms);
+ ASSERT_LE(0, nready) << strerror(errno);
+ ASSERT_EQ(1, nready);
+ ASSERT_TRUE(fds[0].revents & POLLHUP);
+ ASSERT_FALSE(fds[0].revents & (POLLIN | POLLOUT));
+}
diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh
--- a/tests/sys/fs/fusefs/mockfs.hh
+++ b/tests/sys/fs/fusefs/mockfs.hh
@@ -286,14 +286,9 @@
*/
pthread_t m_daemon_id;
- /* file descriptor of /dev/fuse control device */
- volatile int m_fuse_fd;
-
/* The minor version of the kernel API that this mock daemon targets */
uint32_t m_kernel_minor_version;
- int m_kq;
-
/*
* If nonzero, the maximum size in bytes of a read that the kernel will
* send to the server.
@@ -348,6 +343,11 @@
/* pid of child process, for two-process test cases */
pid_t m_child_pid;
+ int m_kq;
+
+ /* file descriptor of /dev/fuse control device */
+ volatile int m_fuse_fd;
+
/* Maximum size of a FUSE_WRITE write */
uint32_t m_maxwrite;
diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc
--- a/tests/sys/fs/fusefs/mockfs.cc
+++ b/tests/sys/fs/fusefs/mockfs.cc
@@ -423,7 +423,6 @@
const char *fsname, const char *subtype)
: m_daemon_id(NULL),
m_kernel_minor_version(kernel_minor_version),
- m_kq(pm == KQ ? kqueue() : -1),
m_maxread(max_read),
m_maxreadahead(max_readahead),
m_pid(getpid()),
@@ -431,6 +430,7 @@
m_pm(pm),
m_time_gran(time_gran),
m_child_pid(-1),
+ m_kq(pm == KQ ? kqueue() : -1),
m_maxwrite(MIN(max_write, max_max_write)),
m_nready(-1),
m_quit(false)

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 17, 5:58 AM (2 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27682819
Default Alt Text
D50826.id156977.diff (4 KB)

Event Timeline