svn commit: r358798 - in head: sys/fs/fuse tests/sys/fs/fusefs
Alan Somers
asomers at FreeBSD.org
Mon Mar 9 01:57:22 UTC 2020
Author: asomers
Date: Mon Mar 9 01:57:21 2020
New Revision: 358798
URL: https://svnweb.freebsd.org/changeset/base/358798
Log:
fusefs: fix fsync for files with multiple open handles
We were reusing a structure for multiple operations, but failing to
reinitialize one member. The result is that a server that cares about FUSE
file handle IDs would see one correct FUSE_FSYNC operation, and one with the
FHID unset.
PR: 244431
Reported by: Agata <chogata at gmail.com>
MFC after: 2 weeks
Modified:
head/sys/fs/fuse/fuse_internal.c
head/tests/sys/fs/fusefs/fsync.cc
Modified: head/sys/fs/fuse/fuse_internal.c
==============================================================================
--- head/sys/fs/fuse/fuse_internal.c Mon Mar 9 00:14:09 2020 (r358797)
+++ head/sys/fs/fuse/fuse_internal.c Mon Mar 9 01:57:21 2020 (r358798)
@@ -345,6 +345,7 @@ fuse_internal_fsync(struct vnode *vp,
* which file handle the caller is really referring to.
*/
LIST_FOREACH(fufh, &fvdat->handles, next) {
+ fdi.iosize = sizeof(*ffsi);
if (ffsi == NULL)
fdisp_make_vp(&fdi, op, vp, td, NULL);
else
Modified: head/tests/sys/fs/fusefs/fsync.cc
==============================================================================
--- head/tests/sys/fs/fusefs/fsync.cc Mon Mar 9 00:14:09 2020 (r358797)
+++ head/tests/sys/fs/fusefs/fsync.cc Mon Mar 9 01:57:21 2020 (r358798)
@@ -52,7 +52,7 @@ using namespace testing;
class Fsync: public FuseTest {
public:
-void expect_fsync(uint64_t ino, uint32_t flags, int error)
+void expect_fsync(uint64_t ino, uint32_t flags, int error, int times = 1)
{
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
@@ -67,12 +67,13 @@ void expect_fsync(uint64_t ino, uint32_t flags, int er
in.body.fsync.fsync_flags == flags);
}, Eq(true)),
_)
- ).WillOnce(Invoke(ReturnErrno(error)));
+ ).Times(times)
+ .WillRepeatedly(Invoke(ReturnErrno(error)));
}
-void expect_lookup(const char *relpath, uint64_t ino)
+void expect_lookup(const char *relpath, uint64_t ino, int times = 1)
{
- FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 0, 1);
+ FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 0, times);
}
void expect_write(uint64_t ino, uint64_t size, const void *contents)
@@ -257,4 +258,30 @@ TEST_F(Fsync, fsync)
ASSERT_EQ(0, fsync(fd)) << strerror(errno);
leak(fd);
+}
+
+/* If multiple FUSE file handles are active, we must fsync them all */
+TEST_F(Fsync, two_handles)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ const char *CONTENTS = "abcdefgh";
+ ssize_t bufsize = strlen(CONTENTS);
+ uint64_t ino = 42;
+ int fd1, fd2;
+
+ expect_lookup(RELPATH, ino, 2);
+ expect_open(ino, 0, 2);
+ expect_write(ino, bufsize, CONTENTS);
+ expect_fsync(ino, 0, 0, 2);
+
+ fd1 = open(FULLPATH, O_WRONLY);
+ ASSERT_LE(0, fd1) << strerror(errno);
+ fd2 = open(FULLPATH, O_RDONLY);
+ ASSERT_LE(0, fd2) << strerror(errno);
+ ASSERT_EQ(bufsize, write(fd1, CONTENTS, bufsize)) << strerror(errno);
+ ASSERT_EQ(0, fsync(fd1)) << strerror(errno);
+
+ leak(fd1);
+ leak(fd2);
}
More information about the svn-src-head
mailing list