Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Mar 2020 15:16:59 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r359213 - in stable/12: sys/fs/fuse tests/sys/fs/fusefs
Message-ID:  <202003221516.02MFGxLw065574@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Sun Mar 22 15:16:59 2020
New Revision: 359213
URL: https://svnweb.freebsd.org/changeset/base/359213

Log:
  MFC r358798:
  
  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@gmail.com>

Modified:
  stable/12/sys/fs/fuse/fuse_internal.c
  stable/12/tests/sys/fs/fusefs/fsync.cc
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/fs/fuse/fuse_internal.c
==============================================================================
--- stable/12/sys/fs/fuse/fuse_internal.c	Sun Mar 22 15:03:09 2020	(r359212)
+++ stable/12/sys/fs/fuse/fuse_internal.c	Sun Mar 22 15:16:59 2020	(r359213)
@@ -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: stable/12/tests/sys/fs/fusefs/fsync.cc
==============================================================================
--- stable/12/tests/sys/fs/fusefs/fsync.cc	Sun Mar 22 15:03:09 2020	(r359212)
+++ stable/12/tests/sys/fs/fusefs/fsync.cc	Sun Mar 22 15:16:59 2020	(r359213)
@@ -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);
 }



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