Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Mar 2019 14:49:28 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r345185 - projects/fuse2/tests/sys/fs/fuse
Message-ID:  <201903151449.x2FEnSxX075550@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri Mar 15 14:49:27 2019
New Revision: 345185
URL: https://svnweb.freebsd.org/changeset/base/345185

Log:
  fuse(4): add tests for FUSE_DESTROY, FUSE_FORGET, and unlinking open files
  
  Sponsored by:	The FreeBSD Foundation

Added:
  projects/fuse2/tests/sys/fs/fuse/destroy.cc   (contents, props changed)
Modified:
  projects/fuse2/tests/sys/fs/fuse/Makefile
  projects/fuse2/tests/sys/fs/fuse/mockfs.cc
  projects/fuse2/tests/sys/fs/fuse/unlink.cc

Modified: projects/fuse2/tests/sys/fs/fuse/Makefile
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/Makefile	Fri Mar 15 14:42:23 2019	(r345184)
+++ projects/fuse2/tests/sys/fs/fuse/Makefile	Fri Mar 15 14:49:27 2019	(r345185)
@@ -9,6 +9,7 @@ TESTSDIR=	${TESTSBASE}/sys/fs/fuse
 # out, so we get more granular reporting.
 ATF_TESTS_CXX+=	access
 ATF_TESTS_CXX+=	create
+ATF_TESTS_CXX+=	destroy
 ATF_TESTS_CXX+=	flush
 ATF_TESTS_CXX+=	fsync
 ATF_TESTS_CXX+=	fsyncdir
@@ -44,6 +45,11 @@ SRCS.create+=	create.cc
 SRCS.create+=	getmntopts.c
 SRCS.create+=	mockfs.cc
 SRCS.create+=	utils.cc
+
+SRCS.destroy+=	destroy.cc
+SRCS.destroy+=	getmntopts.c
+SRCS.destroy+=	mockfs.cc
+SRCS.destroy+=	utils.cc
 
 SRCS.flush+=	flush.cc
 SRCS.flush+=	getmntopts.c

Added: projects/fuse2/tests/sys/fs/fuse/destroy.cc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/fuse2/tests/sys/fs/fuse/destroy.cc	Fri Mar 15 14:49:27 2019	(r345185)
@@ -0,0 +1,92 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 The FreeBSD Foundation
+ *
+ * This software was developed by BFF Storage Systems, LLC under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "mockfs.hh"
+#include "utils.hh"
+
+using namespace testing;
+
+class Destroy: public FuseTest {
+public:
+void expect_destroy(int error)
+{
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([=](auto in) {
+			return (in->header.opcode == FUSE_DESTROY);
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke(ReturnErrno(error)));
+}
+
+void expect_forget(uint64_t ino, uint64_t nlookup)
+{
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([=](auto in) {
+			return (in->header.opcode == FUSE_FORGET &&
+				in->header.nodeid == ino &&
+				in->body.forget.nlookup == nlookup);
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke([](auto in __unused, auto &out __unused) {
+		/* FUSE_FORGET has no response! */
+	}));
+}
+};
+
+/*
+ * On unmount the kernel should send a FUSE_DESTROY operation.  It should also
+ * send FUSE_FORGET operations for all inodes with lookup_count > 0.  It's hard
+ * to trigger FUSE_FORGET in way except by unmounting, so this is the only
+ * testing that FUSE_FORGET gets.
+ */
+TEST_F(Destroy, ok)
+{
+	const char FULLPATH[] = "mountpoint/some_file.txt";
+	const char RELPATH[] = "some_file.txt";
+	uint64_t ino = 42;
+
+	expect_lookup(RELPATH, ino, S_IFREG | 0644, 2);
+	expect_forget(1, 1);
+	expect_forget(ino, 2);
+	expect_destroy(0);
+
+	/*
+	 * access(2) the file to force a lookup.  Access it twice to double its
+	 * lookup count.
+	 */
+	ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno);
+	ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno);
+
+	/*
+	 * Unmount, triggering a FUSE_DESTROY and also causing a VOP_RECLAIM
+	 * for every vnode on this mp, triggering FUSE_FORGET for each of them.
+	 */
+	m_mock->unmount();
+}

Modified: projects/fuse2/tests/sys/fs/fuse/mockfs.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/mockfs.cc	Fri Mar 15 14:42:23 2019	(r345184)
+++ projects/fuse2/tests/sys/fs/fuse/mockfs.cc	Fri Mar 15 14:49:27 2019	(r345185)
@@ -159,6 +159,9 @@ void debug_fuseop(const mockfs_buf_in *in)
 			in->header.unique, in->header.len);
 	}
 	switch (in->header.opcode) {
+		case FUSE_FORGET:
+			printf(" nlookup=%lu", in->body.forget.nlookup);
+			break;
 		case FUSE_FSYNC:
 			printf(" flags=%#x", in->body.fsync.fsync_flags);
 			break;

Modified: projects/fuse2/tests/sys/fs/fuse/unlink.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/unlink.cc	Fri Mar 15 14:42:23 2019	(r345184)
+++ projects/fuse2/tests/sys/fs/fuse/unlink.cc	Fri Mar 15 14:49:27 2019	(r345185)
@@ -38,10 +38,23 @@ using namespace testing;
 
 class Unlink: public FuseTest {
 public:
-void expect_lookup(const char *relpath, uint64_t ino)
+void expect_lookup(const char *relpath, uint64_t ino, int times)
 {
-	FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1);
+	FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, times);
 }
+
+void expect_unlink(uint64_t parent, const char *path, int error)
+{
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([=](auto in) {
+			return (in->header.opcode == FUSE_UNLINK &&
+				0 == strcmp(path, in->body.unlink) &&
+				in->header.nodeid == parent);
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke(ReturnErrno(error)));
+}
+
 };
 
 TEST_F(Unlink, eperm)
@@ -50,15 +63,8 @@ TEST_F(Unlink, eperm)
 	const char RELPATH[] = "some_file.txt";
 	uint64_t ino = 42;
 
-	expect_lookup(RELPATH, ino);
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_UNLINK &&
-				0 == strcmp(RELPATH, in->body.unlink) &&
-				in->header.nodeid == 1);
-		}, Eq(true)),
-		_)
-	).WillOnce(Invoke(ReturnErrno(EPERM)));
+	expect_lookup(RELPATH, ino, 1);
+	expect_unlink(1, RELPATH, EPERM);
 
 	ASSERT_NE(0, unlink(FULLPATH));
 	ASSERT_EQ(EPERM, errno);
@@ -70,15 +76,27 @@ TEST_F(Unlink, ok)
 	const char RELPATH[] = "some_file.txt";
 	uint64_t ino = 42;
 
-	expect_lookup(RELPATH, ino);
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_UNLINK &&
-				0 == strcmp(RELPATH, in->body.unlink) &&
-				in->header.nodeid == 1);
-		}, Eq(true)),
-		_)
-	).WillOnce(Invoke(ReturnErrno(0)));
+	expect_lookup(RELPATH, ino, 1);
+	expect_unlink(1, RELPATH, 0);
 
 	ASSERT_EQ(0, unlink(FULLPATH)) << strerror(errno);
+}
+
+/* Unlink an open file */
+TEST_F(Unlink, open_but_deleted)
+{
+	const char FULLPATH[] = "mountpoint/some_file.txt";
+	const char RELPATH[] = "some_file.txt";
+	uint64_t ino = 42;
+	int fd;
+
+	expect_lookup(RELPATH, ino, 2);
+	expect_open(ino, 0, 1);
+	expect_getattr(ino, 0);
+	expect_unlink(1, RELPATH, 0);
+
+	fd = open(FULLPATH, O_RDWR);
+	ASSERT_LE(0, fd) << strerror(errno);
+	ASSERT_EQ(0, unlink(FULLPATH)) << strerror(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?201903151449.x2FEnSxX075550>