Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Jun 2021 19:34:52 GMT
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 7b8622fa220b - main - fusefs: support EVFILT_WRITE on /dev/fuse
Message-ID:  <202106161934.15GJYqWX062564@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=7b8622fa220b9c08041102f638f848c48e022644

commit 7b8622fa220b9c08041102f638f848c48e022644
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2021-06-15 23:17:28 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2021-06-16 19:34:14 +0000

    fusefs: support EVFILT_WRITE on /dev/fuse
    
    /dev/fuse is always ready for writing, so it's kind of dumb to poll it.
    But some applications do it anyway.  Better to return ready than EINVAL.
    
    MFC after:      2 weeks
    Reviewed by:    emaste, pfg
    Differential Revision: https://reviews.freebsd.org/D30784
---
 sys/fs/fuse/fuse_device.c     | 22 +++++++++++++++++++++-
 tests/sys/fs/fusefs/mockfs.cc | 20 +++++++++++++++++---
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index cab5925c91de..8e000475c0ce 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -119,6 +119,7 @@ static struct cdevsw fuse_device_cdevsw = {
 };
 
 static int fuse_device_filt_read(struct knote *kn, long hint);
+static int fuse_device_filt_write(struct knote *kn, long hint);
 static void fuse_device_filt_detach(struct knote *kn);
 
 struct filterops fuse_device_rfiltops = {
@@ -127,6 +128,11 @@ struct filterops fuse_device_rfiltops = {
 	.f_event = fuse_device_filt_read,
 };
 
+struct filterops fuse_device_wfiltops = {
+	.f_isfd = 1,
+	.f_event = fuse_device_filt_write,
+};
+
 /****************************
  *
  * >>> Fuse device op defs
@@ -180,12 +186,14 @@ fuse_device_filter(struct cdev *dev, struct knote *kn)
 
 	error = devfs_get_cdevpriv((void **)&data);
 
-	/* EVFILT_WRITE is not supported; the device is always ready to write */
 	if (error == 0 && kn->kn_filter == EVFILT_READ) {
 		kn->kn_fop = &fuse_device_rfiltops;
 		kn->kn_hook = data;
 		knlist_add(&data->ks_rsel.si_note, kn, 0);
 		error = 0;
+	} else if (error == 0 && kn->kn_filter == EVFILT_WRITE) {
+		kn->kn_fop = &fuse_device_wfiltops;
+		error = 0;
 	} else if (error == 0) {
 		error = EINVAL;
 		kn->kn_data = error;
@@ -231,6 +239,18 @@ fuse_device_filt_read(struct knote *kn, long hint)
 	return (ready);
 }
 
+static int
+fuse_device_filt_write(struct knote *kn, long hint)
+{
+	int ready;
+
+	/* The device is always ready to write */
+	kn->kn_data = 0;
+	ready = 1;
+
+	return (ready);
+}
+
 /*
  * Resources are set up on a per-open basis
  */
diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc
index 7e4991fb7bb9..7003472ca52b 100644
--- a/tests/sys/fs/fusefs/mockfs.cc
+++ b/tests/sys/fs/fusefs/mockfs.cc
@@ -867,8 +867,8 @@ void MockFS::read_request(mockfs_buf_in &in, ssize_t &res) {
 		timeout_ts.tv_sec = 0;
 		timeout_ts.tv_nsec = timeout_ms * 1'000'000;
 		while (nready == 0) {
-			EV_SET(&changes[0], m_fuse_fd, EVFILT_READ, EV_ADD, 0,
-				0, 0);
+			EV_SET(&changes[0], m_fuse_fd, EVFILT_READ,
+				EV_ADD | EV_ONESHOT, 0, 0, 0);
 			nready = kevent(m_kq, &changes[0], 1, &events[0], 1,
 				&timeout_ts);
 			if (m_quit)
@@ -930,12 +930,26 @@ void MockFS::read_request(mockfs_buf_in &in, ssize_t &res) {
 void MockFS::write_response(const mockfs_buf_out &out) {
 	fd_set writefds;
 	pollfd fds[1];
+	struct kevent changes[1];
+	struct kevent events[1];
 	int nready, nfds;
 	ssize_t r;
 
 	switch (m_pm) {
 	case BLOCKING:
-	case KQ:	/* EVFILT_WRITE is not supported */
+		break;
+	case KQ:
+		EV_SET(&changes[0], m_fuse_fd, EVFILT_WRITE,
+			EV_ADD | EV_ONESHOT, 0, 0, 0);
+		nready = kevent(m_kq, &changes[0], 1, &events[0], 1,
+			NULL);
+		ASSERT_LE(0, nready) << strerror(errno);
+		ASSERT_EQ(events[0].ident, (uintptr_t)m_fuse_fd);
+		if (events[0].flags & EV_ERROR)
+			FAIL() << strerror(events[0].data);
+		else if (events[0].flags & EV_EOF)
+			FAIL() << strerror(events[0].fflags);
+		m_nready = events[0].data;
 		break;
 	case POLL:
 		fds[0].fd = m_fuse_fd;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106161934.15GJYqWX062564>