Page MenuHomeFreeBSD

D27770.id81155.diff
No OneTemporary

D27770.id81155.diff

Index: sys/fs/fuse/fuse_device.c
===================================================================
--- sys/fs/fuse/fuse_device.c
+++ sys/fs/fuse/fuse_device.c
@@ -276,6 +276,7 @@
return (revents);
}
+SDT_PROBE_DEFINE1(fusefs, , device, read_tick, "struct fuse_ticket*");
/*
* fuse_device_read hangs on the queue of VFS messages.
* When it's notified that there is a new one, it picks that and
@@ -287,9 +288,8 @@
int err;
struct fuse_data *data;
struct fuse_ticket *tick;
- void *buf[] = {NULL, NULL, NULL};
- int buflen[3];
- int i;
+ void *buf;
+ int buflen;
SDT_PROBE2(fusefs, , device, trace, 1, "fuse device read");
@@ -332,6 +332,7 @@
goto again;
}
fuse_lck_mtx_unlock(data->ms_mtx);
+ SDT_PROBE1(fusefs, , device, read_tick, tick);
if (fdata_get_dead(data)) {
/*
@@ -352,46 +353,27 @@
SDT_PROBE2(fusefs, , device, trace, 1,
"fuse device read message successfully");
- KASSERT(tick->tk_ms_bufdata || tick->tk_ms_bufsize == 0,
- ("non-null buf pointer with positive size"));
-
- switch (tick->tk_ms_type) {
- case FT_M_FIOV:
- buf[0] = tick->tk_ms_fiov.base;
- buflen[0] = tick->tk_ms_fiov.len;
- break;
- case FT_M_BUF:
- buf[0] = tick->tk_ms_fiov.base;
- buflen[0] = tick->tk_ms_fiov.len;
- buf[1] = tick->tk_ms_bufdata;
- buflen[1] = tick->tk_ms_bufsize;
- break;
- default:
- panic("unknown message type for fuse_ticket %p", tick);
- }
+ buf = tick->tk_ms_fiov.base;
+ buflen = tick->tk_ms_fiov.len;
- for (i = 0; buf[i]; i++) {
- /*
- * Why not ban mercilessly stupid daemons who can't keep up
- * with us? (There is no much use of a partial read here...)
- */
- /*
- * XXX note that in such cases Linux FUSE throws EIO at the
- * syscall invoker and stands back to the message queue. The
- * rationale should be made clear (and possibly adopt that
- * behaviour). Keeping the current scheme at least makes
- * fallacy as loud as possible...
- */
- if (uio->uio_resid < buflen[i]) {
- fdata_set_dead(data);
- SDT_PROBE2(fusefs, , device, trace, 2,
- "daemon is stupid, kick it off...");
- err = ENODEV;
- break;
- }
- err = uiomove(buf[i], buflen[i], uio);
- if (err)
- break;
+ /*
+ * Why not ban mercilessly stupid daemons who can't keep up
+ * with us? (There is no much use of a partial read here...)
+ */
+ /*
+ * XXX note that in such cases Linux FUSE throws EIO at the
+ * syscall invoker and stands back to the message queue. The
+ * rationale should be made clear (and possibly adopt that
+ * behaviour). Keeping the current scheme at least makes
+ * fallacy as loud as possible...
+ */
+ if (uio->uio_resid < buflen) {
+ fdata_set_dead(data);
+ SDT_PROBE2(fusefs, , device, trace, 2,
+ "daemon is stupid, kick it off...");
+ err = ENODEV;
+ } else {
+ err = uiomove(buf, buflen, uio);
}
FUSE_ASSERT_MS_DONE(tick);
Index: sys/fs/fuse/fuse_ipc.h
===================================================================
--- sys/fs/fuse/fuse_ipc.h
+++ sys/fs/fuse/fuse_ipc.h
@@ -123,17 +123,10 @@
/* fields for initiating an upgoing message */
struct fuse_iov tk_ms_fiov;
- void *tk_ms_bufdata;
- size_t tk_ms_bufsize;
- enum { FT_M_FIOV, FT_M_BUF } tk_ms_type;
STAILQ_ENTRY(fuse_ticket) tk_ms_link;
/* fields for handling answers coming from userspace */
struct fuse_iov tk_aw_fiov;
- void *tk_aw_bufdata;
- size_t tk_aw_bufsize;
- enum { FT_A_FIOV, FT_A_BUF } tk_aw_type;
-
struct fuse_out_header tk_aw_ohead;
int tk_aw_errno;
struct mtx tk_aw_mtx;
Index: sys/fs/fuse/fuse_ipc.c
===================================================================
--- sys/fs/fuse/fuse_ipc.c
+++ sys/fs/fuse/fuse_ipc.c
@@ -356,11 +356,9 @@
bzero(ftick, sizeof(struct fuse_ticket));
fiov_init(&ftick->tk_ms_fiov, sizeof(struct fuse_in_header));
- ftick->tk_ms_type = FT_M_FIOV;
mtx_init(&ftick->tk_aw_mtx, "fuse answer delivery mutex", NULL, MTX_DEF);
fiov_init(&ftick->tk_aw_fiov, 0);
- ftick->tk_aw_type = FT_A_FIOV;
return 0;
}
@@ -395,18 +393,11 @@
FUSE_ASSERT_AW_DONE(ftick);
fiov_refresh(&ftick->tk_ms_fiov);
- ftick->tk_ms_bufdata = NULL;
- ftick->tk_ms_bufsize = 0;
- ftick->tk_ms_type = FT_M_FIOV;
bzero(&ftick->tk_aw_ohead, sizeof(struct fuse_out_header));
fiov_refresh(&ftick->tk_aw_fiov);
ftick->tk_aw_errno = 0;
- ftick->tk_aw_bufdata = NULL;
- ftick->tk_aw_bufsize = 0;
- ftick->tk_aw_type = FT_A_FIOV;
-
ftick->tk_flag = 0;
}
@@ -417,17 +408,9 @@
FUSE_ASSERT_MS_DONE(ftick);
FUSE_ASSERT_AW_DONE(ftick);
- ftick->tk_ms_bufdata = NULL;
- ftick->tk_ms_bufsize = 0;
- ftick->tk_ms_type = FT_M_FIOV;
-
bzero(&ftick->tk_aw_ohead, sizeof(struct fuse_out_header));
ftick->tk_aw_errno = 0;
- ftick->tk_aw_bufdata = NULL;
- ftick->tk_aw_bufsize = 0;
- ftick->tk_aw_type = FT_A_FIOV;
-
ftick->tk_flag = 0;
}
@@ -546,20 +529,8 @@
size_t len = uio_resid(uio);
if (len) {
- switch (ftick->tk_aw_type) {
- case FT_A_FIOV:
- fiov_adjust(fticket_resp(ftick), len);
- err = uiomove(fticket_resp(ftick)->base, len, uio);
- break;
-
- case FT_A_BUF:
- ftick->tk_aw_bufsize = len;
- err = uiomove(ftick->tk_aw_bufdata, len, uio);
- break;
-
- default:
- panic("FUSE: unknown answer type for ticket %p", ftick);
- }
+ fiov_adjust(fticket_resp(ftick), len);
+ err = uiomove(fticket_resp(ftick)->base, len, uio);
}
return err;
}
Index: tests/sys/fs/fusefs/bmap.cc
===================================================================
--- tests/sys/fs/fusefs/bmap.cc
+++ tests/sys/fs/fusefs/bmap.cc
@@ -83,9 +83,9 @@
TEST_F(Bmap, bmap)
{
struct fiobmap2_arg arg;
- const off_t filesize = 1 << 20;
+ const off_t filesize = 1 << 30;
const ino_t ino = 42;
- int64_t lbn = 10;
+ int64_t lbn = 100;
int64_t pbn = 12345;
int fd;
@@ -112,7 +112,7 @@
TEST_F(Bmap, default_)
{
struct fiobmap2_arg arg;
- const off_t filesize = 1 << 20;
+ const off_t filesize = 1 << 30;
const ino_t ino = 42;
int64_t lbn;
int fd;
Index: tests/sys/fs/fusefs/mockfs.hh
===================================================================
--- tests/sys/fs/fusefs/mockfs.hh
+++ tests/sys/fs/fusefs/mockfs.hh
@@ -72,6 +72,14 @@
extern int verbosity;
+/*
+ * The maximum that a test case can set max_write, limited by the buffer
+ * supplied when reading from /dev/fuse. This limitation is imposed by
+ * fusefs-libs, but not by the FUSE protocol.
+ */
+const uint32_t max_max_write = 0x20000;
+
+
/* This struct isn't defined by fuse_kernel.h or libfuse, but it should be */
struct fuse_create_out {
struct fuse_entry_out entry;
@@ -138,8 +146,17 @@
union fuse_payloads_in {
fuse_access_in access;
fuse_bmap_in bmap;
- /* value is from fuse_kern_chan.c in fusefs-libs */
- uint8_t bytes[0x21000 - sizeof(struct fuse_in_header)];
+ /*
+ * In fusefs-libs 3.4.2 and below the buffer size is fixed at 0x21000
+ * minus the header sizes. fusefs-libs 3.4.3 (and FUSE Protocol 7.29)
+ * add a FUSE_MAX_PAGES option that allows it to be greater.
+ *
+ * See fuse_kern_chan.c in fusefs-libs 2.9.9 and below, or
+ * FUSE_DEFAULT_MAX_PAGES_PER_REQ in fusefs-libs 3.4.3 and above.
+ */
+ uint8_t bytes[
+ max_max_write + 0x1000 - sizeof(struct fuse_in_header)
+ ];
fuse_create_in create;
fuse_flush_in flush;
fuse_fsync_in fsync;
Index: tests/sys/fs/fusefs/mockfs.cc
===================================================================
--- tests/sys/fs/fusefs/mockfs.cc
+++ tests/sys/fs/fusefs/mockfs.cc
@@ -365,7 +365,7 @@
m_daemon_id = NULL;
m_kernel_minor_version = kernel_minor_version;
m_maxreadahead = max_readahead;
- m_maxwrite = max_write;
+ m_maxwrite = MIN(max_write, max_max_write);
m_nready = -1;
m_pm = pm;
m_time_gran = time_gran;
Index: tests/sys/fs/fusefs/utils.hh
===================================================================
--- tests/sys/fs/fusefs/utils.hh
+++ tests/sys/fs/fusefs/utils.hh
@@ -55,7 +55,6 @@
bool is_unsafe_aio_enabled(void);
extern const uint32_t libfuse_max_write;
-extern const uint32_t default_max_write;
class FuseTest : public ::testing::Test {
protected:
uint32_t m_maxreadahead;
@@ -80,7 +79,7 @@
FuseTest():
m_maxreadahead(0),
- m_maxwrite(default_max_write),
+ m_maxwrite(0),
m_init_flags(0),
m_allow_other(false),
m_default_permissions(false),
Index: tests/sys/fs/fusefs/utils.cc
===================================================================
--- tests/sys/fs/fusefs/utils.cc
+++ tests/sys/fs/fusefs/utils.cc
@@ -59,13 +59,6 @@
*/
const uint32_t libfuse_max_write = 32 * getpagesize() + 0x1000 - 4096;
-/*
- * Set the default max_write to a distinct value from MAXPHYS to catch bugs
- * that confuse the two.
- */
-const uint32_t default_max_write = MIN(libfuse_max_write, MAXPHYS / 2);
-
-
/* Check that fusefs(4) is accessible and the current user can mount(2) */
void check_environment()
{
@@ -156,6 +149,12 @@
ASSERT_EQ(0, sysctlbyname(maxphys_node, &val, &size, NULL, 0))
<< strerror(errno);
m_maxphys = val;
+ /*
+ * Set the default max_write to a distinct value from MAXPHYS to catch
+ * bugs that confuse the two.
+ */
+ if (m_maxwrite == 0)
+ m_maxwrite = MIN(libfuse_max_write, (uint32_t)m_maxphys / 2);
try {
m_mock = new MockFS(m_maxreadahead, m_allow_other,
Index: tests/sys/fs/fusefs/write.cc
===================================================================
--- tests/sys/fs/fusefs/write.cc
+++ tests/sys/fs/fusefs/write.cc
@@ -166,6 +166,7 @@
public:
virtual void SetUp() {
m_async = true;
+ m_maxwrite = 65536;
WriteBack::SetUp();
}
};
@@ -194,6 +195,19 @@
}
};
+/* Tests relating to the server's max_write property */
+class WriteMaxWrite: public Write {
+public:
+virtual void SetUp() {
+ /*
+ * For this test, m_maxwrite must be less than either m_maxbcachebuf or
+ * maxphys.
+ */
+ m_maxwrite = 32768;
+ Write::SetUp();
+}
+};
+
void sigxfsz_handler(int __unused sig) {
Write::s_sigxfsz = 1;
}
@@ -643,7 +657,7 @@
}
/* fuse(4) should not issue writes of greater size than the daemon requests */
-TEST_F(Write, write_large)
+TEST_F(WriteMaxWrite, write)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
@@ -653,6 +667,8 @@
ssize_t halfbufsize, bufsize;
halfbufsize = m_mock->m_maxwrite;
+ if (halfbufsize >= m_maxbcachebuf || halfbufsize >= m_maxphys)
+ GTEST_SKIP() << "Must lower m_maxwrite for this test";
bufsize = halfbufsize * 2;
contents = (int*)malloc(bufsize);
ASSERT_NE(nullptr, contents);

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 10, 10:21 AM (20 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23527635
Default Alt Text
D27770.id81155.diff (10 KB)

Event Timeline