Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 May 2019 16:41:34 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r347438 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Message-ID:  <201905101641.x4AGfYJk084356@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri May 10 16:41:33 2019
New Revision: 347438
URL: https://svnweb.freebsd.org/changeset/base/347438

Log:
  fusefs: return ENOTCONN instead of EIO if the daemon dies suddenly
  
  If the daemon dies, return ENOTCONN for all operations that have already
  been sent to the daemon, as well as any new ones.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_ipc.c
  projects/fuse2/tests/sys/fs/fusefs/statfs.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_ipc.c	Fri May 10 16:38:48 2019	(r347437)
+++ projects/fuse2/sys/fs/fuse/fuse_ipc.c	Fri May 10 16:41:33 2019	(r347438)
@@ -1028,7 +1028,15 @@ fdisp_wait_answ(struct fuse_dispatcher *fdip)
 		}
 	}
 
-	if (fdip->tick->tk_aw_errno) {
+	if (fdip->tick->tk_aw_errno == ENOTCONN) {
+		/* The daemon died while we were waiting for a response */
+		err = ENOTCONN;
+		goto out;
+	} else if (fdip->tick->tk_aw_errno) {
+		/* 
+		 * There was some sort of communication error with the daemon
+		 * that the client wouldn't understand.
+		 */
 		SDT_PROBE2(fusefs, , ipc, fdisp_wait_answ_error,
 			"IPC: explicit EIO-ing", fdip->tick->tk_aw_errno);
 		err = EIO;

Modified: projects/fuse2/tests/sys/fs/fusefs/statfs.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/statfs.cc	Fri May 10 16:38:48 2019	(r347437)
+++ projects/fuse2/tests/sys/fs/fusefs/statfs.cc	Fri May 10 16:41:33 2019	(r347438)
@@ -31,6 +31,7 @@
 extern "C" {
 #include <sys/param.h>
 #include <sys/mount.h>
+#include <semaphore.h>
 }
 
 #include "mockfs.hh"
@@ -69,6 +70,58 @@ TEST_F(Statfs, enotconn)
 	ASSERT_NE(NULL, getcwd(mp, PATH_MAX)) << strerror(errno);
 	strlcat(mp, "/mountpoint", PATH_MAX);
 	ASSERT_EQ(0, statfs("mountpoint", &statbuf)) << strerror(errno);
+
+	EXPECT_EQ(getuid(), statbuf.f_owner);
+	EXPECT_EQ(0, strcmp("fusefs", statbuf.f_fstypename));
+	EXPECT_EQ(0, strcmp("/dev/fuse", statbuf.f_mntfromname));
+	EXPECT_EQ(0, strcmp(mp, statbuf.f_mntonname));
+}
+
+static void* statfs_th(void* arg) {
+	ssize_t r;
+	struct statfs *sb = (struct statfs*)arg;
+
+	r = statfs("mountpoint", sb);
+	if (r >= 0)
+		return 0;
+	else
+		return (void*)(intptr_t)errno;
+}
+
+/*
+ * Like the enotconn test, but in this case the daemon dies after we send the
+ * FUSE_STATFS operation but before we get a response.
+ */
+TEST_F(Statfs, enotconn_while_blocked)
+{
+	struct statfs statbuf;
+	void *thr0_value;
+	pthread_t th0;
+	char mp[PATH_MAX];
+	sem_t sem;
+
+	ASSERT_EQ(0, sem_init(&sem, 0, 0)) << strerror(errno);
+
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([](auto in) {
+			return (in->header.opcode == FUSE_STATFS);
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke([&](auto in __unused, auto &out __unused) {
+		sem_post(&sem);
+		/* Just block until the daemon dies */
+	}));
+
+	ASSERT_NE(NULL, getcwd(mp, PATH_MAX)) << strerror(errno);
+	strlcat(mp, "/mountpoint", PATH_MAX);
+	ASSERT_EQ(0, pthread_create(&th0, NULL, statfs_th, (void*)&statbuf))
+		<< strerror(errno);
+
+	ASSERT_EQ(0, sem_wait(&sem)) << strerror(errno);
+	m_mock->kill_daemon();
+
+	pthread_join(th0, &thr0_value);
+	ASSERT_EQ(0, (intptr_t)thr0_value);
 
 	EXPECT_EQ(getuid(), statbuf.f_owner);
 	EXPECT_EQ(0, strcmp("fusefs", statbuf.f_fstypename));



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