svn commit: r348313 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Alan Somers
asomers at FreeBSD.org
Mon May 27 21:36:30 UTC 2019
Author: asomers
Date: Mon May 27 21:36:28 2019
New Revision: 348313
URL: https://svnweb.freebsd.org/changeset/base/348313
Log:
fusefs: set FUSE_WRITE_CACHE when writing from cache
This bit tells the server that we're not sure which uid, gid, and/or pid
originated the write. I don't know of a single file system that cares, but
it's part of the protocol.
Sponsored by: The FreeBSD Foundation
Modified:
projects/fuse2/sys/fs/fuse/fuse_io.c
projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
projects/fuse2/tests/sys/fs/fusefs/fsync.cc
projects/fuse2/tests/sys/fs/fusefs/utils.cc
projects/fuse2/tests/sys/fs/fusefs/utils.hh
projects/fuse2/tests/sys/fs/fusefs/write.cc
Modified: projects/fuse2/sys/fs/fuse/fuse_io.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_io.c Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/sys/fs/fuse/fuse_io.c Mon May 27 21:36:28 2019 (r348313)
@@ -119,7 +119,7 @@ fuse_read_biobackend(struct vnode *vp, struct uio *uio
static int
fuse_write_directbackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, off_t filesize,
- int ioflag);
+ int ioflag, bool pages);
static int
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid);
@@ -245,7 +245,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, in
if (!pages )
v_inval_buf_range(vp, start, end, iosize);
err = fuse_write_directbackend(vp, uio, cred, fufh,
- filesize, ioflag);
+ filesize, ioflag, pages);
} else {
SDT_PROBE2(fusefs, , io, trace, 1,
"buffered write of vnode");
@@ -405,7 +405,7 @@ out:
static int
fuse_write_directbackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, off_t filesize,
- int ioflag)
+ int ioflag, bool pages)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct fuse_data *data;
@@ -418,9 +418,29 @@ fuse_write_directbackend(struct vnode *vp, struct uio
int diff;
int err = 0;
bool direct_io = fufh->fuse_open_flags & FOPEN_DIRECT_IO;
+ uint32_t write_flags;
data = fuse_get_mpdata(vp->v_mount);
+ /*
+ * Don't set FUSE_WRITE_LOCKOWNER in write_flags. It can't be set
+ * accurately when using POSIX AIO, libfuse doesn't use it, and I'm not
+ * aware of any file systems that do. It was an attempt to add
+ * Linux-style mandatory locking to the FUSE protocol, but mandatory
+ * locking is deprecated even on Linux. See Linux commit
+ * f33321141b273d60cbb3a8f56a5489baad82ba5e .
+ */
+ /*
+ * Set FUSE_WRITE_CACHE whenever we don't know the uid, gid, and/or pid
+ * that originated a write. For example when writing from the
+ * writeback cache. I don't know of a single file system that cares,
+ * but the protocol says we're supposed to do this.
+ */
+ write_flags = !pages && (
+ (ioflag & IO_DIRECT) ||
+ !fsess_opt_datacache(vnode_mount(vp)) ||
+ fuse_data_cache_mode != FUSE_CACHE_WB) ? 0 : FUSE_WRITE_CACHE;
+
if (uio->uio_resid == 0)
return (0);
@@ -439,17 +459,8 @@ fuse_write_directbackend(struct vnode *vp, struct uio
fwi->fh = fufh->fh_id;
fwi->offset = uio->uio_offset;
fwi->size = chunksize;
+ fwi->write_flags = write_flags;
if (fuse_libabi_geq(data, 7, 9)) {
- /*
- * Don't set FUSE_WRITE_LOCKOWNER. It can't be set
- * accurately when using POSIX AIO, libfuse doesn't use
- * it, and I'm not aware of any file systems that do.
- * It was an attempt to add Linux-style mandatory
- * locking to the FUSE protocol, but mandatory locking
- * is deprecated even on Linux. See Linux commit
- * f33321141b273d60cbb3a8f56a5489baad82ba5e .
- */
- fwi->write_flags = 0;
fwi->flags = 0; /* TODO */
fwi_data = (char *)fdi.indata + sizeof(*fwi);
} else {
@@ -525,6 +536,7 @@ retry:
fwi->fh = fufh->fh_id;
fwi->offset = as_written_offset;
fwi->size = diff;
+ fwi->write_flags = write_flags;
goto retry;
}
}
@@ -884,7 +896,7 @@ fuse_io_strategy(struct vnode *vp, struct buf *bp)
uiop->uio_rw = UIO_WRITE;
error = fuse_write_directbackend(vp, uiop, cred, fufh,
- filesize, 0);
+ filesize, 0, false);
if (error == EINTR || error == ETIMEDOUT
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
Modified: projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc Mon May 27 21:36:28 2019 (r348313)
@@ -1229,7 +1229,7 @@ TEST_F(Write, clear_suid)
expect_getattr(1, S_IFDIR | 0755, UINT64_MAX, 1);
expect_lookup(RELPATH, ino, S_IFREG | oldmode, UINT64_MAX);
expect_open(ino, 0, 1);
- expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, wbuf);
+ expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, 0, wbuf);
expect_chmod(ino, newmode, sizeof(wbuf));
fd = open(FULLPATH, O_WRONLY);
@@ -1255,7 +1255,7 @@ TEST_F(Write, clear_sgid)
expect_getattr(1, S_IFDIR | 0755, UINT64_MAX, 1);
expect_lookup(RELPATH, ino, S_IFREG | oldmode, UINT64_MAX);
expect_open(ino, 0, 1);
- expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, wbuf);
+ expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, 0, wbuf);
expect_chmod(ino, newmode, sizeof(wbuf));
fd = open(FULLPATH, O_WRONLY);
@@ -1285,7 +1285,7 @@ TEST_F(Write, recursion_panic_while_clearing_suid)
expect_getattr(1, S_IFDIR | 0755, UINT64_MAX, 1);
expect_lookup(RELPATH, ino, S_IFREG | oldmode, UINT64_MAX);
expect_open(ino, 0, 1);
- expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, wbuf);
+ expect_write(ino, 0, sizeof(wbuf), sizeof(wbuf), 0, 0, wbuf);
/* XXX Return a smaller file size than what we just wrote! */
expect_chmod(ino, newmode, 0);
Modified: projects/fuse2/tests/sys/fs/fusefs/fsync.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/fsync.cc Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/tests/sys/fs/fusefs/fsync.cc Mon May 27 21:36:28 2019 (r348313)
@@ -75,7 +75,7 @@ void expect_lookup(const char *relpath, uint64_t ino)
void expect_write(uint64_t ino, uint64_t size, const void *contents)
{
- FuseTest::expect_write(ino, 0, size, size, 0, contents);
+ FuseTest::expect_write(ino, 0, size, size, 0, 0, contents);
}
};
Modified: projects/fuse2/tests/sys/fs/fusefs/utils.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/utils.cc Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/tests/sys/fs/fusefs/utils.cc Mon May 27 21:36:28 2019 (r348313)
@@ -377,15 +377,17 @@ void FuseTest::expect_unlink(uint64_t parent, const ch
}
void FuseTest::expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
- uint64_t osize, uint32_t flags, const void *contents)
+ uint64_t osize, uint32_t flags_set, uint32_t flags_unset,
+ const void *contents)
{
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
const char *buf = (const char*)in.body.bytes +
sizeof(struct fuse_write_in);
bool pid_ok;
+ uint32_t wf = in.body.write.write_flags;
- if (in.body.write.write_flags & FUSE_WRITE_CACHE)
+ if (wf & FUSE_WRITE_CACHE)
pid_ok = true;
else
pid_ok = (pid_t)in.header.pid == getpid();
@@ -396,7 +398,8 @@ void FuseTest::expect_write(uint64_t ino, uint64_t off
in.body.write.offset == offset &&
in.body.write.size == isize &&
pid_ok &&
- in.body.write.write_flags == flags &&
+ (wf & flags_set) == flags_set &&
+ (wf & flags_unset) == 0 &&
0 == bcmp(buf, contents, isize));
}, Eq(true)),
_)
@@ -407,7 +410,7 @@ void FuseTest::expect_write(uint64_t ino, uint64_t off
}
void FuseTest::expect_write_7_8(uint64_t ino, uint64_t offset, uint64_t isize,
- uint64_t osize, uint32_t flags, const void *contents)
+ uint64_t osize, const void *contents)
{
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
@@ -420,7 +423,6 @@ void FuseTest::expect_write_7_8(uint64_t ino, uint64_t
in.body.write.offset == offset &&
in.body.write.size == isize &&
pid_ok &&
- in.body.write.write_flags == flags &&
0 == bcmp(buf, contents, isize));
}, Eq(true)),
_)
Modified: projects/fuse2/tests/sys/fs/fusefs/utils.hh
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/utils.hh Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/tests/sys/fs/fusefs/utils.hh Mon May 27 21:36:28 2019 (r348313)
@@ -169,15 +169,18 @@ class FuseTest : public ::testing::Test {
/*
* Create an expectation that FUSE_WRITE will be called exactly once
- * for the given inode, at offset offset, with write_flags flags,
- * size isize and buffer contents. It will return osize
+ * for the given inode, at offset offset, with size isize and buffer
+ * contents. Any flags present in flags_set must be set, and any
+ * present in flags_unset must not be set. Other flags are don't care.
+ * It will return osize.
*/
void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
- uint64_t osize, uint32_t flags, const void *contents);
+ uint64_t osize, uint32_t flags_set, uint32_t flags_unset,
+ const void *contents);
/* Protocol 7.8 version of expect_write */
void expect_write_7_8(uint64_t ino, uint64_t offset, uint64_t isize,
- uint64_t osize, uint32_t flags, const void *contents);
+ uint64_t osize, const void *contents);
/*
* Helper that runs code in a child process.
Modified: projects/fuse2/tests/sys/fs/fusefs/write.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/write.cc Mon May 27 20:22:54 2019 (r348312)
+++ projects/fuse2/tests/sys/fs/fusefs/write.cc Mon May 27 21:36:28 2019 (r348313)
@@ -65,6 +65,12 @@ void expect_release(uint64_t ino, ProcessMockerT r)
).WillRepeatedly(Invoke(r));
}
+void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
+ uint64_t osize, const void *contents)
+{
+ FuseTest::expect_write(ino, offset, isize, osize, 0, 0, contents);
+}
+
};
class Write_7_8: public FuseTest {
@@ -100,7 +106,7 @@ virtual void SetUp() {
/* Tests for the write-through cache mode */
class WriteThrough: public Write {
-
+public:
virtual void SetUp() {
const char *cache_mode_node = "vfs.fusefs.data_cache_mode";
int val = 0;
@@ -117,11 +123,17 @@ virtual void SetUp() {
"(writethrough) for this test";
}
+void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
+ uint64_t osize, const void *contents)
+{
+ FuseTest::expect_write(ino, offset, isize, osize, 0, FUSE_WRITE_CACHE,
+ contents);
+}
};
/* Tests for the writeback cache mode */
class WriteBack: public Write {
-
+public:
virtual void SetUp() {
const char *node = "vfs.fusefs.data_cache_mode";
int val = 0;
@@ -138,6 +150,12 @@ virtual void SetUp() {
"(writeback) for this test";
}
+void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
+ uint64_t osize, const void *contents)
+{
+ FuseTest::expect_write(ino, offset, isize, osize, FUSE_WRITE_CACHE, 0,
+ contents);
+}
};
/* AIO writes need to set the header's pid field correctly */
@@ -155,7 +173,7 @@ TEST_F(AioWrite, DISABLED_aio_write)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, offset, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, offset, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -196,7 +214,7 @@ TEST_F(Write, append)
expect_lookup(RELPATH, ino, initial_offset);
expect_open(ino, 0, 1);
- expect_write(ino, initial_offset, BUFSIZE, BUFSIZE, 0, CONTENTS);
+ expect_write(ino, initial_offset, BUFSIZE, BUFSIZE, CONTENTS);
/* Must open O_RDWR or fuse(4) implicitly sets direct_io */
fd = open(FULLPATH, O_RDWR | O_APPEND);
@@ -218,7 +236,7 @@ TEST_F(Write, append_direct_io)
expect_lookup(RELPATH, ino, initial_offset);
expect_open(ino, FOPEN_DIRECT_IO, 1);
- expect_write(ino, initial_offset, BUFSIZE, BUFSIZE, 0, CONTENTS);
+ expect_write(ino, initial_offset, BUFSIZE, BUFSIZE, CONTENTS);
fd = open(FULLPATH, O_WRONLY | O_APPEND);
EXPECT_LE(0, fd) << strerror(errno);
@@ -242,7 +260,7 @@ TEST_F(Write, direct_io_evicts_cache)
expect_lookup(RELPATH, ino, bufsize);
expect_open(ino, 0, 1);
expect_read(ino, 0, bufsize, bufsize, CONTENTS0);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS1);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS1);
fd = open(FULLPATH, O_RDWR);
EXPECT_LE(0, fd) << strerror(errno);
@@ -285,9 +303,8 @@ TEST_F(Write, indirect_io_short_write)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize0, 0, CONTENTS);
- expect_write(ino, bufsize0, bufsize1, bufsize1, 0,
- contents1);
+ expect_write(ino, 0, bufsize, bufsize0, CONTENTS);
+ expect_write(ino, bufsize0, bufsize1, bufsize1, contents1);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -312,7 +329,7 @@ TEST_F(Write, direct_io_short_write)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, FOPEN_DIRECT_IO, 1);
- expect_write(ino, 0, bufsize, halfbufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, halfbufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -342,7 +359,7 @@ TEST_F(Write, direct_io_short_write_iov)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, FOPEN_DIRECT_IO, 1);
- expect_write(ino, 0, totalsize, size0, 0, EXPECTED0);
+ expect_write(ino, 0, totalsize, size0, EXPECTED0);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -388,9 +405,8 @@ TEST_F(Write, mmap)
/*
* Writes from the pager may or may not be associated with the correct
* pid, so they must set FUSE_WRITE_CACHE.
- * TODO: expect FUSE_WRITE_CACHE after upgrading to protocol 7.9
*/
- expect_write(ino, 0, len, len, 0, expected);
+ FuseTest::expect_write(ino, 0, len, len, FUSE_WRITE_CACHE, 0, expected);
expect_flush(ino, 1, ReturnErrno(0));
expect_release(ino, ReturnErrno(0));
@@ -435,7 +451,7 @@ TEST_F(WriteThrough, evicts_read_cache)
expect_lookup(RELPATH, ino, bufsize);
expect_open(ino, 0, 1);
expect_read(ino, 0, bufsize, bufsize, contents0);
- expect_write(ino, 0, wrsize, wrsize, 0, contents1);
+ expect_write(ino, 0, wrsize, wrsize, contents1);
fd = open(FULLPATH, O_RDWR);
EXPECT_LE(0, fd) << strerror(errno);
@@ -468,7 +484,7 @@ TEST_F(WriteThrough, pwrite)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, offset, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, offset, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -489,7 +505,7 @@ TEST_F(Write, write)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -518,8 +534,8 @@ TEST_F(Write, write_large)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, halfbufsize, halfbufsize, 0, contents);
- expect_write(ino, halfbufsize, halfbufsize, halfbufsize, 0,
+ expect_write(ino, 0, halfbufsize, halfbufsize, contents);
+ expect_write(ino, halfbufsize, halfbufsize, halfbufsize,
&contents[halfbufsize / sizeof(int)]);
fd = open(FULLPATH, O_WRONLY);
@@ -561,7 +577,7 @@ TEST_F(Write_7_8, write)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write_7_8(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write_7_8(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -582,7 +598,7 @@ TEST_F(WriteBack, close)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS);
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
return (in.header.opcode == FUSE_SETATTR);
@@ -621,7 +637,7 @@ TEST_F(WriteBack, rmw)
FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, fsize, 1);
expect_open(ino, 0, 1);
expect_read(ino, 0, fsize, fsize, INITIAL);
- expect_write(ino, offset, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, offset, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
@@ -646,7 +662,7 @@ TEST_F(WriteBack, writeback)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_RDWR);
EXPECT_LE(0, fd) << strerror(errno);
@@ -678,7 +694,8 @@ TEST_F(WriteBack, o_direct)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ FuseTest::expect_write(ino, 0, bufsize, bufsize, 0, FUSE_WRITE_CACHE,
+ CONTENTS);
expect_read(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_RDWR | O_DIRECT);
@@ -711,7 +728,7 @@ TEST_F(WriteThrough, DISABLED_writethrough)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_RDWR);
EXPECT_LE(0, fd) << strerror(errno);
@@ -738,7 +755,7 @@ TEST_F(WriteThrough, update_file_size)
expect_lookup(RELPATH, ino, 0);
expect_open(ino, 0, 1);
- expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS);
+ expect_write(ino, 0, bufsize, bufsize, CONTENTS);
fd = open(FULLPATH, O_RDWR);
EXPECT_LE(0, fd) << strerror(errno);
More information about the svn-src-projects
mailing list