Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 03 Sep 2019 14:07:28 -0000
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r346637 - projects/fuse2/tests/sys/fs/fusefs
Message-ID:  <201904241425.x3OEPZeE075537@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Wed Apr 24 14:25:35 2019
New Revision: 346637
URL: https://svnweb.freebsd.org/changeset/base/346637

Log:
  fusefs: fix the FUSE_INTERRUPT tests when data_cache_mode==2
  
  Replace most write operations with mkdir so they won't be affected by the
  setting of vfs.fusefs.data_cache_mode.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/tests/sys/fs/fusefs/interrupt.cc

Modified: projects/fuse2/tests/sys/fs/fusefs/interrupt.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/interrupt.cc	Wed Apr 24 14:08:16 2019	(r346636)
+++ projects/fuse2/tests/sys/fs/fusefs/interrupt.cc	Wed Apr 24 14:25:35 2019	(r346637)
@@ -45,6 +45,10 @@ using namespace testing;
 
 /* Initial size of files used by these tests */
 const off_t FILESIZE = 1000;
+/* Access mode used by all directories in these tests */
+const mode_t MODE = 0755;
+const char FULLDIRPATH0[] = "mountpoint/some_dir";
+const char RELDIRPATH0[] = "some_dir";
 
 static sem_t *signaled_semaphore;
 
@@ -83,6 +87,23 @@ void expect_lookup(const char *relpath, uint64_t ino)
 }
 
 /* 
+ * Expect a FUSE_MKDIR but don't reply.  Instead, just record the unique value
+ * to the provided pointer
+ */
+void expect_mkdir(uint64_t *mkdir_unique)
+{
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([=](auto in) {
+			return (in->header.opcode == FUSE_MKDIR);
+				
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke([=](auto in, auto &out __unused) {
+		*mkdir_unique = in->header.unique;
+	}));
+}
+
+/* 
  * Expect a FUSE_READ but don't reply.  Instead, just record the unique value
  * to the provided pointer
  */
@@ -149,32 +170,27 @@ void TearDown() {
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */
 TEST_F(Interrupt, already_complete)
 {
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char RELPATH[] = "some_file.txt";
-	const char *CONTENTS = "abcdefgh";
 	uint64_t ino = 42;
-	int fd;
-	ssize_t bufsize = strlen(CONTENTS);
 	pthread_t self;
-	uint64_t write_unique = 0;
+	uint64_t mkdir_unique = 0;
 
 	self = pthread_self();
 
-	expect_lookup(RELPATH, ino);
-	expect_open(ino, 0, 1);
-	expect_write(ino, &write_unique);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	expect_mkdir(&mkdir_unique);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).WillOnce(Invoke([&](auto in, auto &out) {
-		// First complete the write request
+		// First complete the mkdir request
 		auto out0 = new mockfs_buf_out;
-		out0->header.unique = write_unique;
-		SET_OUT_HEADER_LEN(out0, write);
-		out0->body.write.size = bufsize;
+		out0->header.unique = mkdir_unique;
+		SET_OUT_HEADER_LEN(out0, entry);
+		out0->body.create.entry.attr.mode = S_IFDIR | MODE;
+		out0->body.create.entry.nodeid = ino;
 		out.push_back(out0);
 
 		// Then, respond EAGAIN to the interrupt request
@@ -185,13 +201,8 @@ TEST_F(Interrupt, already_complete)
 		out.push_back(out1);
 	}));
 
-	fd = open(FULLPATH, O_WRONLY);
-	ASSERT_LE(0, fd) << strerror(errno);
-
 	setup_interruptor(self);
-	EXPECT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno);
-
-	/* Deliberately leak fd.  close(2) will be tested in release.cc */
+	EXPECT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno);
 }
 
 /*
@@ -200,45 +211,31 @@ TEST_F(Interrupt, already_complete)
  */
 TEST_F(Interrupt, fatal_signal)
 {
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char *CONTENTS = "abcdefgh";
-	const char RELPATH[] = "some_file.txt";
-	ssize_t bufsize = strlen(CONTENTS);
-	uint64_t ino = 42;
 	int status;
 	pthread_t self;
-	uint64_t write_unique;
+	uint64_t mkdir_unique;
 
 	self = pthread_self();
 
-	expect_lookup(RELPATH, ino);
-	expect_open(ino, 0, 1);
-	expect_write(ino, &write_unique);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	expect_mkdir(&mkdir_unique);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).WillOnce(Invoke([&](auto in __unused, auto &out __unused) {
 		/* Don't respond.  The process should exit anyway */
 	}));
-	expect_flush(ino, 1, ReturnErrno(0));
-	expect_release(ino, FH);
 
 	fork(false, &status, [&] {
 	}, [&]() {
 		struct sigaction sa;
-		int fd, r;
+		int r;
 		pthread_t killer_th;
 		pthread_t self;
 
-		fd = open(FULLPATH, O_WRONLY);
-		if (fd < 0) {
-			perror("open");
-			return 1;
-		}
-
 		/* SIGUSR2 terminates the process by default */
 		bzero(&sa, sizeof(sa));
 		sa.sa_handler = SIG_DFL;
@@ -254,12 +251,10 @@ TEST_F(Interrupt, fatal_signal)
 			return 1;
 		}
 
-		write(fd, CONTENTS, bufsize);
+		mkdir(FULLDIRPATH0, MODE);
 		return 1;
 	});
 	ASSERT_EQ(SIGUSR2, WTERMSIG(status));
-
-	/* Deliberately leak fd.  close(2) will be tested in release.cc */
 }
 
 /*
@@ -269,45 +264,45 @@ TEST_F(Interrupt, fatal_signal)
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */
 TEST_F(Interrupt, ignore)
 {
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char RELPATH[] = "some_file.txt";
-	const char *CONTENTS = "abcdefgh";
 	uint64_t ino = 42;
-	int fd;
-	ssize_t bufsize = strlen(CONTENTS);
 	pthread_t self;
-	uint64_t write_unique;
+	uint64_t mkdir_unique;
 
 	self = pthread_self();
 
-	expect_lookup(RELPATH, ino);
-	expect_open(ino, 0, 1);
-	expect_write(ino, &write_unique);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	expect_mkdir(&mkdir_unique);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).WillOnce(Invoke([&](auto in __unused, auto &out) {
 		// Ignore FUSE_INTERRUPT; respond to the FUSE_WRITE
 		auto out0 = new mockfs_buf_out;
-		out0->header.unique = write_unique;
-		SET_OUT_HEADER_LEN(out0, write);
-		out0->body.write.size = bufsize;
+		out0->header.unique = mkdir_unique;
+		SET_OUT_HEADER_LEN(out0, entry);
+		out0->body.create.entry.attr.mode = S_IFDIR | MODE;
+		out0->body.create.entry.nodeid = ino;
 		out.push_back(out0);
 	}));
 
-	fd = open(FULLPATH, O_WRONLY);
-	ASSERT_LE(0, fd) << strerror(errno);
-
 	setup_interruptor(self);
-	ASSERT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno);
+	ASSERT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno);
+}
 
-	/* Deliberately leak fd.  close(2) will be tested in release.cc */
+void* mkdir0(void* arg __unused) {
+	ssize_t r;
+
+	r = mkdir(FULLDIRPATH0, MODE);
+	if (r >= 0)
+		return 0;
+	else
+		return (void*)(intptr_t)errno;
 }
 
-void* write0(void* arg) {
+void* setxattr0(void* arg) {
 	const char *CONTENTS = "abcdefgh";
 	ssize_t bufsize = strlen(CONTENTS);
 	int fd = (int)(intptr_t)arg;
@@ -334,87 +329,16 @@ void* read1(void* arg) {
 }
 
 /*
- * An operation that hasn't yet been sent to userland can be interrupted
- * without sending FUSE_INTERRUPT
- */
-TEST_F(Interrupt, in_kernel)
-{
-	const char FULLPATH0[] = "mountpoint/some_file.txt";
-	const char RELPATH0[] = "some_file.txt";
-	const char FULLPATH1[] = "mountpoint/other_file.txt";
-	const char RELPATH1[] = "other_file.txt";
-	const char *CONTENTS = "ijklmnop";
-	ssize_t bufsize = strlen(CONTENTS);
-	uint64_t ino0 = 42, ino1 = 43;
-	int fd0, fd1;
-	pthread_t self, th0;
-	sem_t sem0, sem1;
-	void *thr0_value;
-
-	ASSERT_EQ(0, sem_init(&sem0, 0, 0)) << strerror(errno);
-	ASSERT_EQ(0, sem_init(&sem1, 0, 0)) << strerror(errno);
-	self = pthread_self();
-
-	expect_lookup(RELPATH0, ino0);
-	expect_open(ino0, 0, 1);
-	expect_lookup(RELPATH1, ino1);
-	expect_open(ino1, 0, 1);
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_WRITE &&
-				in->header.nodeid == ino0);
-		}, Eq(true)),
-		_)
-	).WillOnce(Invoke(ReturnImmediate([&](auto in, auto out) {
-		/* Let the next write proceed */
-		sem_post(&sem1);
-		/* Pause the daemon thread so it won't read the next op */
-		sem_wait(&sem0);
-
-		SET_OUT_HEADER_LEN(out, write);
-		out->body.write.size = in->body.write.size;
-	})));
-
-	fd0 = open(FULLPATH0, O_WRONLY);
-	ASSERT_LE(0, fd0) << strerror(errno);
-	fd1 = open(FULLPATH1, O_WRONLY);
-	ASSERT_LE(0, fd1) << strerror(errno);
-
-	/* Use a separate thread for the first write */
-	ASSERT_EQ(0, pthread_create(&th0, NULL, write0, (void*)(intptr_t)fd0))
-		<< strerror(errno);
-
-	setup_interruptor(self);
-
-	sem_wait(&sem1);	/* Sequence the two writes */
-	ASSERT_EQ(-1, write(fd1, CONTENTS, bufsize));
-	EXPECT_EQ(EINTR, errno);
-
-	/* Unstick the daemon */
-	ASSERT_EQ(0, sem_post(&sem0)) << strerror(errno);
-
-	/* Wait awhile to make sure the signal generates no FUSE_INTERRUPT */
-	usleep(250'000);
-
-	pthread_join(th0, &thr0_value);
-	EXPECT_EQ(0, (intptr_t)thr0_value);
-	sem_destroy(&sem1);
-	sem_destroy(&sem0);
-}
-
-/*
  * A restartable operation (basically, anything except write or setextattr)
  * that hasn't yet been sent to userland can be interrupted without sending
  * FUSE_INTERRUPT, and will be automatically restarted.
  */
 TEST_F(Interrupt, in_kernel_restartable)
 {
-	const char FULLPATH0[] = "mountpoint/some_file.txt";
-	const char RELPATH0[] = "some_file.txt";
 	const char FULLPATH1[] = "mountpoint/other_file.txt";
 	const char RELPATH1[] = "other_file.txt";
 	uint64_t ino0 = 42, ino1 = 43;
-	int fd0, fd1;
+	int fd1;
 	pthread_t self, th0, th1;
 	sem_t sem0, sem1;
 	void *thr0_value, *thr1_value;
@@ -423,34 +347,31 @@ TEST_F(Interrupt, in_kernel_restartable)
 	ASSERT_EQ(0, sem_init(&sem1, 0, 0)) << strerror(errno);
 	self = pthread_self();
 
-	expect_lookup(RELPATH0, ino0);
-	expect_open(ino0, 0, 1);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
 	expect_lookup(RELPATH1, ino1);
 	expect_open(ino1, 0, 1);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_WRITE &&
-				in->header.nodeid == ino0);
+			return (in->header.opcode == FUSE_MKDIR);
 		}, Eq(true)),
 		_)
-	).WillOnce(Invoke(ReturnImmediate([&](auto in, auto out) {
+	).WillOnce(Invoke(ReturnImmediate([&](auto in __unused, auto out) {
 		/* Let the next write proceed */
 		sem_post(&sem1);
 		/* Pause the daemon thread so it won't read the next op */
 		sem_wait(&sem0);
 
-		SET_OUT_HEADER_LEN(out, write);
-		out->body.write.size = in->body.write.size;
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.create.entry.attr.mode = S_IFDIR | MODE;
+		out->body.create.entry.nodeid = ino0;
 	})));
 	FuseTest::expect_read(ino1, 0, FILESIZE, 0, NULL);
 
-	fd0 = open(FULLPATH0, O_WRONLY);
-	ASSERT_LE(0, fd0) << strerror(errno);
 	fd1 = open(FULLPATH1, O_RDONLY);
 	ASSERT_LE(0, fd1) << strerror(errno);
 
 	/* Use a separate thread for each operation */
-	ASSERT_EQ(0, pthread_create(&th0, NULL, write0, (void*)(intptr_t)fd0))
+	ASSERT_EQ(0, pthread_create(&th0, NULL, mkdir0, NULL))
 		<< strerror(errno);
 
 	sem_wait(&sem1);	/* Sequence the two operations */
@@ -476,21 +397,20 @@ TEST_F(Interrupt, in_kernel_restartable)
 	sem_destroy(&sem0);
 }
 
-/* 
- * Like FUSE_WRITE, FUSE_SETXATTR is non-restartable because it calls uiomove
- * before blocking in fticket_wait_answ
+/*
+ * An operation that hasn't yet been sent to userland can be interrupted
+ * without sending FUSE_INTERRUPT.  If it's a non-restartable operation (write
+ * or setextattr) it will return EINTR.
  */
-TEST_F(Interrupt, in_kernel_setxattr)
+TEST_F(Interrupt, in_kernel_nonrestartable)
 {
-	const char FULLPATH0[] = "mountpoint/some_file.txt";
-	const char RELPATH0[] = "some_file.txt";
 	const char FULLPATH1[] = "mountpoint/other_file.txt";
 	const char RELPATH1[] = "other_file.txt";
 	const char value[] = "whatever";
 	ssize_t value_len = strlen(value) + 1;
 	uint64_t ino0 = 42, ino1 = 43;
 	int ns = EXTATTR_NAMESPACE_USER;
-	int fd0, fd1;
+	int fd1;
 	pthread_t self, th0;
 	sem_t sem0, sem1;
 	void *thr0_value;
@@ -500,33 +420,30 @@ TEST_F(Interrupt, in_kernel_setxattr)
 	ASSERT_EQ(0, sem_init(&sem1, 0, 0)) << strerror(errno);
 	self = pthread_self();
 
-	expect_lookup(RELPATH0, ino0);
-	expect_open(ino0, 0, 1);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
 	expect_lookup(RELPATH1, ino1);
 	expect_open(ino1, 0, 1);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_WRITE &&
-				in->header.nodeid == ino0);
+			return (in->header.opcode == FUSE_MKDIR);
 		}, Eq(true)),
 		_)
-	).WillOnce(Invoke(ReturnImmediate([&](auto in, auto out) {
+	).WillOnce(Invoke(ReturnImmediate([&](auto in __unused, auto out) {
 		/* Let the next write proceed */
 		sem_post(&sem1);
 		/* Pause the daemon thread so it won't read the next op */
 		sem_wait(&sem0);
 
-		SET_OUT_HEADER_LEN(out, write);
-		out->body.write.size = in->body.write.size;
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.create.entry.attr.mode = S_IFDIR | MODE;
+		out->body.create.entry.nodeid = ino0;
 	})));
 
-	fd0 = open(FULLPATH0, O_WRONLY);
-	ASSERT_LE(0, fd0) << strerror(errno);
 	fd1 = open(FULLPATH1, O_WRONLY);
 	ASSERT_LE(0, fd1) << strerror(errno);
 
 	/* Use a separate thread for the first write */
-	ASSERT_EQ(0, pthread_create(&th0, NULL, write0, (void*)(intptr_t)fd0))
+	ASSERT_EQ(0, pthread_create(&th0, NULL, mkdir0, NULL))
 		<< strerror(errno);
 
 	setup_interruptor(self);
@@ -556,42 +473,30 @@ TEST_F(Interrupt, in_kernel_setxattr)
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */
 TEST_F(Interrupt, in_progress)
 {
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char RELPATH[] = "some_file.txt";
-	const char *CONTENTS = "abcdefgh";
-	uint64_t ino = 42;
-	int fd;
-	ssize_t bufsize = strlen(CONTENTS);
 	pthread_t self;
-	uint64_t write_unique;
+	uint64_t mkdir_unique;
 
 	self = pthread_self();
 
-	expect_lookup(RELPATH, ino);
-	expect_open(ino, 0, 1);
-	expect_write(ino, &write_unique);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	expect_mkdir(&mkdir_unique);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).WillOnce(Invoke([&](auto in __unused, auto &out) {
 		auto out0 = new mockfs_buf_out;
 		out0->header.error = -EINTR;
-		out0->header.unique = write_unique;
+		out0->header.unique = mkdir_unique;
 		out0->header.len = sizeof(out0->header);
 		out.push_back(out0);
 	}));
 
-	fd = open(FULLPATH, O_WRONLY);
-	ASSERT_LE(0, fd) << strerror(errno);
-
 	setup_interruptor(self);
-	ASSERT_EQ(-1, write(fd, CONTENTS, bufsize));
+	ASSERT_EQ(-1, mkdir(FULLDIRPATH0, MODE));
 	EXPECT_EQ(EINTR, errno);
-
-	/* Deliberately leak fd.  close(2) will be tested in release.cc */
 }
 
 /* Reads should also be interruptible */
@@ -638,16 +543,11 @@ TEST_F(Interrupt, in_progress_read)
 /* FUSE_INTERRUPT operations should take priority over other pending ops */
 TEST_F(Interrupt, priority)
 {
-	const char FULLPATH0[] = "mountpoint/some_file.txt";
-	const char RELPATH0[] = "some_file.txt";
-	const char FULLPATH1[] = "mountpoint/other_file.txt";
-	const char RELPATH1[] = "other_file.txt";
-	const char *CONTENTS = "ijklmnop";
+	const char FULLPATH1[] = "mountpoint/other_dir";
+	const char RELPATH1[] = "other_dir";
 	Sequence seq;
-	ssize_t bufsize = strlen(CONTENTS);
-	uint64_t ino0 = 42, ino1 = 43;
-	int fd0, fd1;
-	uint64_t write_unique;
+	uint64_t ino1 = 43;
+	uint64_t mkdir_unique;
 	pthread_t self, th0;
 	sem_t sem0, sem1;
 
@@ -655,21 +555,19 @@ TEST_F(Interrupt, priority)
 	ASSERT_EQ(0, sem_init(&sem1, 0, 0)) << strerror(errno);
 	self = pthread_self();
 
-	expect_lookup(RELPATH0, ino0);
-	expect_open(ino0, 0, 1);
-	expect_lookup(RELPATH1, ino1);
-	expect_open(ino1, 0, 1);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	EXPECT_LOOKUP(1, RELPATH1).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	//expect_mkdir(&mkdir_unique);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_WRITE &&
-				in->header.nodeid == ino0);
+			return (in->header.opcode == FUSE_MKDIR);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
 	.WillOnce(Invoke(ReturnImmediate([&](auto in, auto out) {
-		write_unique = in->header.unique;
+		mkdir_unique = in->header.unique;
 
-		/* Let the next write proceed */
+		/* Let the next mkdir proceed */
 		sem_post(&sem1);
 
 		/* Pause the daemon thread so it won't read the next op */
@@ -677,47 +575,42 @@ TEST_F(Interrupt, priority)
 
 		/* Finally, interrupt the original op */
 		out->header.error = -EINTR;
-		out->header.unique = write_unique;
+		out->header.unique = mkdir_unique;
 		out->header.len = sizeof(out->header);
 	})));
 	/* 
-	 * FUSE_INTERRUPT should be received before the second FUSE_WRITE, even
+	 * FUSE_INTERRUPT should be received before the second FUSE_MKDIR, even
 	 * though it was generated later
 	 */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
 	.WillOnce(Invoke(ReturnErrno(EAGAIN)));
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
-			return (in->header.opcode == FUSE_WRITE &&
-				in->header.nodeid == ino1);
+			return (in->header.opcode == FUSE_MKDIR);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
-	.WillOnce(Invoke(ReturnImmediate([=](auto in , auto out) {
-		SET_OUT_HEADER_LEN(out, write);
-		out->body.write.size = in->body.write.size;
+	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.create.entry.attr.mode = S_IFDIR | MODE;
+		out->body.create.entry.nodeid = ino1;
 	})));
 
-	fd0 = open(FULLPATH0, O_WRONLY);
-	ASSERT_LE(0, fd0) << strerror(errno);
-	fd1 = open(FULLPATH1, O_WRONLY);
-	ASSERT_LE(0, fd1) << strerror(errno);
-
-	/* Use a separate thread for the first write */
-	ASSERT_EQ(0, pthread_create(&th0, NULL, write0, (void*)(intptr_t)fd0))
+	/* Use a separate thread for the first mkdir */
+	ASSERT_EQ(0, pthread_create(&th0, NULL, mkdir0, NULL))
 		<< strerror(errno);
 
 	signaled_semaphore = &sem0;
 
-	sem_wait(&sem1);	/* Sequence the two writes */
+	sem_wait(&sem1);	/* Sequence the two mkdirs */
 	setup_interruptor(th0);
-	ASSERT_EQ(bufsize, write(fd1, CONTENTS, bufsize)) << strerror(errno);
+	ASSERT_EQ(0, mkdir(FULLPATH1, MODE)) << strerror(errno);
 
 	/* Wait awhile to make sure the signal generates no FUSE_INTERRUPT */
 	usleep(250'000);
@@ -740,26 +633,19 @@ TEST_F(Interrupt, priority)
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */
 TEST_F(Interrupt, too_soon)
 {
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char RELPATH[] = "some_file.txt";
-	const char *CONTENTS = "abcdefgh";
 	Sequence seq;
-	uint64_t ino = 42;
-	int fd;
-	ssize_t bufsize = strlen(CONTENTS);
 	pthread_t self;
-	uint64_t write_unique;
+	uint64_t mkdir_unique;
 
 	self = pthread_self();
 
-	expect_lookup(RELPATH, ino);
-	expect_open(ino, 0, 1);
-	expect_write(ino, &write_unique);
+	EXPECT_LOOKUP(1, RELDIRPATH0).WillOnce(Invoke(ReturnErrno(ENOENT)));
+	expect_mkdir(&mkdir_unique);
 
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
@@ -768,23 +654,20 @@ TEST_F(Interrupt, too_soon)
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([&](auto in) {
 			return (in->header.opcode == FUSE_INTERRUPT &&
-				in->body.interrupt.unique == write_unique);
+				in->body.interrupt.unique == mkdir_unique);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
 	.WillOnce(Invoke([&](auto in __unused, auto &out __unused) {
 		auto out0 = new mockfs_buf_out;
 		out0->header.error = -EINTR;
-		out0->header.unique = write_unique;
+		out0->header.unique = mkdir_unique;
 		out0->header.len = sizeof(out0->header);
 		out.push_back(out0);
 	}));
 
-	fd = open(FULLPATH, O_WRONLY);
-	ASSERT_LE(0, fd) << strerror(errno);
-
 	setup_interruptor(self);
-	ASSERT_EQ(-1, write(fd, CONTENTS, bufsize));
+	ASSERT_EQ(-1, mkdir(FULLDIRPATH0, MODE));
 	EXPECT_EQ(EINTR, errno);
 
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */





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