Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 May 2019 18:12:38 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r347358 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Message-ID:  <201905081812.x48ICcL1095254@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Wed May  8 18:12:38 2019
New Revision: 347358
URL: https://svnweb.freebsd.org/changeset/base/347358

Log:
  fusefs: updated cached attributes during VOP_LINK.
  
  FUSE_LINK returns a new set of attributes.  fusefs should cache them just
  like it does during other VOPs.  This is not only a matter of performance
  but of correctness too; without caching the new attributes the vnode's nlink
  value would be out-of-date.
  
  Reported by:	pjdfstest
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_vnops.c
  projects/fuse2/tests/sys/fs/fusefs/link.cc
  projects/fuse2/tests/sys/fs/fusefs/setattr.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c	Wed May  8 18:10:19 2019	(r347357)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c	Wed May  8 18:12:38 2019	(r347358)
@@ -817,6 +817,9 @@ fuse_vnop_link(struct vop_link_args *ap)
 	feo = fdi.answ;
 
 	err = fuse_internal_checkentry(feo, vnode_vtype(vp));
+	if (!err)
+		fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid,
+			feo->attr_valid_nsec, NULL);
 out:
 	fdisp_destroy(&fdi);
 	return err;

Modified: projects/fuse2/tests/sys/fs/fusefs/link.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/link.cc	Wed May  8 18:10:19 2019	(r347357)
+++ projects/fuse2/tests/sys/fs/fusefs/link.cc	Wed May  8 18:12:38 2019	(r347358)
@@ -77,26 +77,41 @@ TEST_F(Link, ok)
 	const char RELPATH[] = "src";
 	const char FULLDST[] = "mountpoint/dst";
 	const char RELDST[] = "dst";
-	uint64_t dst_ino = 42;
 	const uint64_t ino = 42;
+	mode_t mode = S_IFREG | 0644;
+	struct stat sb;
 
 	EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT)));
-	expect_lookup(RELDST, dst_ino);
+	EXPECT_LOOKUP(1, RELDST)
+	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.entry.attr.mode = mode;
+		out->body.entry.nodeid = ino;
+		out->body.entry.attr.nlink = 1;
+		out->body.entry.attr_valid = UINT64_MAX;
+		out->body.entry.entry_valid = UINT64_MAX;
+	})));
 
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			const char *name = (const char*)in->body.bytes
 				+ sizeof(struct fuse_link_in);
 			return (in->header.opcode == FUSE_LINK &&
-				in->body.link.oldnodeid == dst_ino &&
+				in->body.link.oldnodeid == ino &&
 				(0 == strcmp(name, RELPATH)));
 		}, Eq(true)),
 		_)
 	).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
 		SET_OUT_HEADER_LEN(out, entry);
-		out->body.entry.attr.mode = S_IFREG | 0644;
+		out->body.entry.attr.mode = mode;
 		out->body.entry.nodeid = ino;
+		out->body.entry.attr.nlink = 2;
+		out->body.entry.attr_valid = UINT64_MAX;
+		out->body.entry.entry_valid = UINT64_MAX;
 	})));
 
-	EXPECT_EQ(0, link(FULLDST, FULLPATH)) << strerror(errno);
+	ASSERT_EQ(0, link(FULLDST, FULLPATH)) << strerror(errno);
+	// Check that the original file's nlink count has increased.
+	ASSERT_EQ(0, stat(FULLDST, &sb)) << strerror(errno);
+	EXPECT_EQ(2ul, sb.st_nlink);
 }

Modified: projects/fuse2/tests/sys/fs/fusefs/setattr.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/setattr.cc	Wed May  8 18:10:19 2019	(r347357)
+++ projects/fuse2/tests/sys/fs/fusefs/setattr.cc	Wed May  8 18:12:38 2019	(r347358)
@@ -131,6 +131,70 @@ TEST_F(Setattr, chmod)
 	EXPECT_EQ(0, chmod(FULLPATH, newmode)) << strerror(errno);
 }
 
+/* 
+ * Chmod a multiply-linked file with cached attributes.  Check that both files'
+ * attributes have changed.
+ */
+TEST_F(Setattr, chmod_multiply_linked)
+{
+	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";
+	struct stat sb;
+	const uint64_t ino = 42;
+	const mode_t oldmode = 0777;
+	const mode_t newmode = 0666;
+
+	EXPECT_LOOKUP(1, RELPATH0)
+	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.entry.attr.mode = S_IFREG | oldmode;
+		out->body.entry.nodeid = ino;
+		out->body.entry.attr.nlink = 2;
+		out->body.entry.attr_valid = UINT64_MAX;
+		out->body.entry.entry_valid = UINT64_MAX;
+	})));
+
+	EXPECT_LOOKUP(1, RELPATH1)
+	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.entry.attr.mode = S_IFREG | oldmode;
+		out->body.entry.nodeid = ino;
+		out->body.entry.attr.nlink = 2;
+		out->body.entry.attr_valid = UINT64_MAX;
+		out->body.entry.entry_valid = UINT64_MAX;
+	})));
+
+	EXPECT_CALL(*m_mock, process(
+		ResultOf([](auto in) {
+			uint32_t valid = FATTR_MODE;
+			return (in->header.opcode == FUSE_SETATTR &&
+				in->header.nodeid == ino &&
+				in->body.setattr.valid == valid &&
+				in->body.setattr.mode == newmode);
+		}, Eq(true)),
+		_)
+	).WillOnce(Invoke(ReturnImmediate([](auto in __unused, auto out) {
+		SET_OUT_HEADER_LEN(out, attr);
+		out->body.attr.attr.ino = ino;
+		out->body.attr.attr.mode = S_IFREG | newmode;
+		out->body.attr.attr.nlink = 2;
+		out->body.attr.attr_valid = UINT64_MAX;
+	})));
+
+	/* For a lookup of the 2nd file to get it into the cache*/
+	ASSERT_EQ(0, stat(FULLPATH1, &sb)) << strerror(errno);
+	EXPECT_EQ(S_IFREG | oldmode, sb.st_mode);
+
+	ASSERT_EQ(0, chmod(FULLPATH0, newmode)) << strerror(errno);
+	ASSERT_EQ(0, stat(FULLPATH0, &sb)) << strerror(errno);
+	EXPECT_EQ(S_IFREG | newmode, sb.st_mode);
+	ASSERT_EQ(0, stat(FULLPATH1, &sb)) << strerror(errno);
+	EXPECT_EQ(S_IFREG | newmode, sb.st_mode);
+}
+
+
 /* Change the owner and group of a file */
 TEST_F(Setattr, chown)
 {



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