svn commit: r346043 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs

Alan Somers asomers at FreeBSD.org
Mon Apr 8 18:45:46 UTC 2019


Author: asomers
Date: Mon Apr  8 18:45:41 2019
New Revision: 346043
URL: https://svnweb.freebsd.org/changeset/base/346043

Log:
  fusefs: cache file attributes
  
  FUSE_LOOKUP, FUSE_GETATTR, FUSE_SETATTR, FUSE_MKDIR, FUSE_LINK,
  FUSE_SYMLINK, FUSE_MKNOD, and FUSE_CREATE all return file attributes with a
  cache validity period.  fusefs will now cache the attributes, if the server
  returns a non-zero cache validity period.
  
  This change does _not_ implement finite attr cache timeouts.  That will
  follow as part of PR 235773.
  
  PR:		235775
  Reported by:	cem
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_internal.c
  projects/fuse2/sys/fs/fuse/fuse_internal.h
  projects/fuse2/sys/fs/fuse/fuse_node.c
  projects/fuse2/sys/fs/fuse/fuse_node.h
  projects/fuse2/sys/fs/fuse/fuse_vnops.c
  projects/fuse2/tests/sys/fs/fusefs/allow_other.cc
  projects/fuse2/tests/sys/fs/fusefs/create.cc
  projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
  projects/fuse2/tests/sys/fs/fusefs/flush.cc
  projects/fuse2/tests/sys/fs/fusefs/fsync.cc
  projects/fuse2/tests/sys/fs/fusefs/getattr.cc
  projects/fuse2/tests/sys/fs/fusefs/locks.cc
  projects/fuse2/tests/sys/fs/fusefs/lookup.cc
  projects/fuse2/tests/sys/fs/fusefs/open.cc
  projects/fuse2/tests/sys/fs/fusefs/read.cc
  projects/fuse2/tests/sys/fs/fusefs/release.cc
  projects/fuse2/tests/sys/fs/fusefs/setattr.cc
  projects/fuse2/tests/sys/fs/fusefs/unlink.cc
  projects/fuse2/tests/sys/fs/fusefs/utils.cc
  projects/fuse2/tests/sys/fs/fusefs/write.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.c	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.c	Mon Apr  8 18:45:41 2019	(r346043)
@@ -175,9 +175,9 @@ fuse_internal_access(struct vnode *vp,
 }
 
 /*
- * Cache FUSE attributes from feo, in attr cache associated with vnode 'vp'.
- * Optionally, if argument 'vap' is not NULL, store a copy of the converted
- * attributes there as well.
+ * Cache FUSE attributes from attr, in attribute cache associated with vnode
+ * 'vp'.  Optionally, if argument 'vap' is not NULL, store a copy of the
+ * converted attributes there as well.
  *
  * If the nominal attribute cache TTL is zero, do not cache on the 'vp' (but do
  * return the result to the caller).
@@ -581,6 +581,62 @@ fuse_internal_forget_send(struct mount *mp,
 
 	fuse_insert_message(fdi.tick);
 	fdisp_destroy(&fdi);
+}
+
+/* Read a vnode's attributes from cache or fetch them from the fuse daemon */
+int
+fuse_internal_getattr(struct vnode *vp, struct vattr *vap, struct ucred *cred,
+	struct thread *td)
+{
+	struct fuse_dispatcher fdi;
+	struct fuse_vnode_data *fvdat = VTOFUD(vp);
+	struct vattr *attrs;
+	struct fuse_attr_out *fao;
+	int err = 0;
+
+	if ((attrs = VTOVA(vp)) != NULL) {
+		/* struct copy */
+		*vap = *attrs;
+		if ((fvdat->flag & FN_SIZECHANGE) != 0)
+			vap->va_size = fvdat->filesize;
+		return 0;
+	}
+
+	fdisp_init(&fdi, 0);
+	if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) {
+		if (err == ENOENT) {
+			fuse_internal_vnode_disappear(vp);
+		}
+		goto out;
+	}
+
+	fao = (struct fuse_attr_out *)fdi.answ;
+	fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
+		fao->attr_valid_nsec, vap);
+	if (vap->va_type != vnode_vtype(vp)) {
+		fuse_internal_vnode_disappear(vp);
+		err = ENOENT;
+		goto out;
+	}
+	if ((fvdat->flag & FN_SIZECHANGE) != 0)
+		vap->va_size = fvdat->filesize;
+
+	if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) {
+		/*
+	         * This is for those cases when the file size changed without us
+	         * knowing, and we want to catch up.
+	         */
+		off_t new_filesize = fao->attr.size;
+
+		if (fvdat->filesize != new_filesize) {
+			fuse_vnode_setsize(vp, cred, new_filesize);
+			fvdat->flag &= ~FN_SIZECHANGE;
+		}
+	}
+
+out:
+	fdisp_destroy(&fdi);
+	return err;
 }
 
 void

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.h
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.h	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.h	Mon Apr  8 18:45:41 2019	(r346043)
@@ -199,6 +199,10 @@ int fuse_internal_fsync(struct vnode *vp, struct threa
 	bool datasync);
 int fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio);
 
+/* getattr */
+int fuse_internal_getattr(struct vnode *vp, struct vattr *vap,
+	struct ucred *cred, struct thread *td);
+
 /* readdir */
 
 struct pseudo_dirent {

Modified: projects/fuse2/sys/fs/fuse/fuse_node.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_node.c	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/sys/fs/fuse/fuse_node.c	Mon Apr  8 18:45:41 2019	(r346043)
@@ -403,6 +403,7 @@ int
 fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize)
 {
 	struct fuse_vnode_data *fvdat = VTOFUD(vp);
+	struct vattr *attrs;
 	off_t oldsize;
 	size_t iosize;
 	struct buf *bp = NULL;
@@ -413,6 +414,8 @@ fuse_vnode_setsize(struct vnode *vp, struct ucred *cre
 	iosize = fuse_iosize(vp);
 	oldsize = fvdat->filesize;
 	fvdat->filesize = newsize;
+	if ((attrs = VTOVA(vp)) != NULL)
+		attrs->va_size = newsize;
 	fvdat->flag |= FN_SIZECHANGE;
 
 	if (newsize < oldsize) {

Modified: projects/fuse2/sys/fs/fuse/fuse_node.h
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_node.h	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/sys/fs/fuse/fuse_node.h	Mon Apr  8 18:45:41 2019	(r346043)
@@ -80,7 +80,7 @@ struct fuse_vnode_data {
 	uint64_t	parent_nid;
 
 	/** I/O **/
-	/* List of file data for each of the vnode's open file descriptors */
+	/* List of file handles for all of the vnode's open file descriptors */
 	LIST_HEAD(, fuse_filehandle)	handles;
 
 	/** flags **/

Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c	Mon Apr  8 18:45:41 2019	(r346043)
@@ -478,6 +478,8 @@ fuse_vnop_create(struct vop_create_args *ap)
 		goto out;
 	}
 	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");
+	fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid,
+		feo->attr_valid_nsec, NULL);
 
 	fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo);
 	fuse_vnode_open(*vpp, foo->open_flags, td);
@@ -555,12 +557,9 @@ fuse_vnop_getattr(struct vop_getattr_args *ap)
 	struct vattr *vap = ap->a_vap;
 	struct ucred *cred = ap->a_cred;
 	struct thread *td = curthread;
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-	struct fuse_attr_out *fao;
 
 	int err = 0;
 	int dataflags;
-	struct fuse_dispatcher fdi;
 
 	dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags;
 
@@ -575,47 +574,13 @@ fuse_vnop_getattr(struct vop_getattr_args *ap)
 			goto fake;
 		}
 	}
-	fdisp_init(&fdi, 0);
-	if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) {
-		if ((err == ENOTCONN) && vnode_isvroot(vp)) {
-			/* see comment in fuse_vfsop_statfs() */
-			fdisp_destroy(&fdi);
-			goto fake;
-		}
-		if (err == ENOENT) {
-			fuse_internal_vnode_disappear(vp);
-		}
-		goto out;
+	err = fuse_internal_getattr(vp, vap, cred, td);
+	if (err == ENOTCONN && vnode_isvroot(vp)) {
+		/* see comment in fuse_vfsop_statfs() */
+		goto fake;
+	} else {
+		return err;
 	}
-
-	fao = (struct fuse_attr_out *)fdi.answ;
-	fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid,
-		fao->attr_valid_nsec, vap);
-	if (vap->va_type != vnode_vtype(vp)) {
-		fuse_internal_vnode_disappear(vp);
-		err = ENOENT;
-		goto out;
-	}
-	if ((fvdat->flag & FN_SIZECHANGE) != 0)
-		vap->va_size = fvdat->filesize;
-
-	if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) {
-		/*
-	         * This is for those cases when the file size changed without us
-	         * knowing, and we want to catch up.
-	         */
-		off_t new_filesize = ((struct fuse_attr_out *)
-				      fdi.answ)->attr.size;
-
-		if (fvdat->filesize != new_filesize) {
-			fuse_vnode_setsize(vp, cred, new_filesize);
-			fvdat->flag &= ~FN_SIZECHANGE;
-		}
-	}
-
-out:
-	fdisp_destroy(&fdi);
-	return err;
 
 fake:
 	bzero(vap, sizeof(*vap));

Modified: projects/fuse2/tests/sys/fs/fusefs/allow_other.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/allow_other.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/allow_other.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -80,7 +80,6 @@ TEST_F(AllowOther, allowed)
 			expect_open(ino, 0, 1);
 			expect_flush(ino, 1, ReturnErrno(0));
 			expect_release(ino, FH);
-			expect_getattr(ino, 0);
 		}, []() {
 			int fd;
 
@@ -137,7 +136,6 @@ TEST_F(AllowOther, privilege_escalation)
 			_)
 		).Times(AnyNumber())
 		.WillRepeatedly(Invoke(ReturnErrno(EPERM)));
-		expect_getattr(ino, 0);
 
 		fd1 = open(FULLPATH, O_RDONLY);
 		EXPECT_LE(0, fd1) << strerror(errno);

Modified: projects/fuse2/tests/sys/fs/fusefs/create.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/create.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/create.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -59,8 +59,7 @@ void expect_create(const char *relpath, ProcessMockerT
  * If FUSE_CREATE sets the attr_valid, then subsequent GETATTRs should use the
  * attribute cache
  */
-/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235775 */
-TEST_F(Create, DISABLED_attr_cache)
+TEST_F(Create, attr_cache)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -151,19 +150,6 @@ TEST_F(Create, Enosys)
 		SET_OUT_HEADER_LEN(out, open);
 	})));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0644;
-	})));
-
 	fd = open(FULLPATH, O_CREAT | O_EXCL, mode);
 	EXPECT_LE(0, fd) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
@@ -196,19 +182,6 @@ TEST_F(Create, entry_cache_negative)
 		out->body.create.entry.attr_valid = UINT64_MAX;
 	}));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0644;
-	})));
-
 	fd = open(FULLPATH, O_CREAT | O_EXCL, mode);
 	ASSERT_LE(0, fd) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
@@ -239,19 +212,6 @@ TEST_F(Create, entry_cache_negative_purge)
 		out->body.create.entry.attr_valid = UINT64_MAX;
 	}));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0644;
-	})));
-
 	fd = open(FULLPATH, O_CREAT | O_EXCL, mode);
 	ASSERT_LE(0, fd) << strerror(errno);
 
@@ -296,19 +256,6 @@ TEST_F(Create, ok)
 		out->body.create.entry.attr_valid = UINT64_MAX;
 	}));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | mode;
-	})));
-
 	fd = open(FULLPATH, O_CREAT | O_EXCL, mode);
 	EXPECT_LE(0, fd) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
@@ -338,19 +285,6 @@ TEST_F(Create, wronly_0444)
 		out->body.create.entry.entry_valid = UINT64_MAX;
 		out->body.create.entry.attr_valid = UINT64_MAX;
 	}));
-
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | mode;
-	})));
 
 	fd = open(FULLPATH, O_CREAT | O_WRONLY, mode);
 	EXPECT_LE(0, fd) << strerror(errno);

Modified: projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -111,8 +111,6 @@ TEST_F(Open, ok)
 
 	expect_lookup(RELPATH, ino, S_IFREG | 0644);
 	expect_open(ino, 0, 1);
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	expect_getattr(ino, 0);
 
 	fd = open(FULLPATH, O_RDONLY);
 	EXPECT_LE(0, fd) << strerror(errno);

Modified: projects/fuse2/tests/sys/fs/fusefs/flush.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/flush.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/flush.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -96,7 +96,6 @@ TEST_F(Flush, open_twice)
 
 	expect_lookup(RELPATH, ino, 2);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 2, 0, ReturnErrno(0));
 	expect_release();
 
@@ -127,7 +126,6 @@ TEST_F(Flush, eio)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, 0, ReturnErrno(EIO));
 	expect_release();
 
@@ -153,14 +151,12 @@ TEST_F(Flush, enosys)
 
 	expect_lookup(RELPATH0, ino0, 1);
 	expect_open(ino0, 0, 1);
-	expect_getattr(ino0, 0);
 	/* On the 2nd close, FUSE_FLUSH won't be sent at all */
 	expect_flush(ino0, 1, 0, ReturnErrno(ENOSYS));
 	expect_release();
 
 	expect_lookup(RELPATH1, ino1, 1);
 	expect_open(ino1, 0, 1);
-	expect_getattr(ino1, 0);
 	/* On the 2nd close, FUSE_FLUSH won't be sent at all */
 	expect_release();
 
@@ -184,7 +180,6 @@ TEST_F(Flush, flush)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, 0, ReturnErrno(0));
 	expect_release();
 
@@ -210,7 +205,6 @@ TEST_F(FlushWithLocks, DISABLED_unlock_on_close)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&

Modified: projects/fuse2/tests/sys/fs/fusefs/fsync.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/fsync.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/fsync.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -93,7 +93,6 @@ TEST_F(Fsync, aio_fsync)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	expect_fsync(ino, 0, 0);
 
@@ -127,7 +126,6 @@ TEST_F(Fsync, close)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
@@ -164,7 +162,6 @@ TEST_F(Fsync, eio)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	expect_fsync(ino, FUSE_FSYNC_FDATASYNC, EIO);
 
@@ -194,7 +191,6 @@ TEST_F(Fsync, DISABLED_enosys)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	expect_fsync(ino, FUSE_FSYNC_FDATASYNC, ENOSYS);
 
@@ -220,7 +216,6 @@ TEST_F(Fsync, fdatasync)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	expect_fsync(ino, FUSE_FSYNC_FDATASYNC, 0);
 
@@ -243,7 +238,6 @@ TEST_F(Fsync, fsync)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, bufsize, CONTENTS);
 	expect_fsync(ino, 0, 0);
 

Modified: projects/fuse2/tests/sys/fs/fusefs/getattr.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/getattr.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/getattr.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -33,14 +33,32 @@
 
 using namespace testing;
 
-class Getattr : public FuseTest {};
+class Getattr : public FuseTest {
+public:
+void expect_lookup(const char *relpath, uint64_t ino, mode_t mode,
+	uint64_t size, int times, uint64_t attr_valid, uint32_t attr_valid_nsec)
+{
+	EXPECT_LOOKUP(1, relpath)
+	.Times(times)
+	.WillRepeatedly(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 = attr_valid;
+		out->body.entry.attr_valid_nsec = attr_valid_nsec;
+		out->body.entry.attr.size = size;
+		out->body.entry.entry_valid = UINT64_MAX;
+	})));
+}
+};
 
+
 /*
  * If getattr returns a non-zero cache timeout, then subsequent VOP_GETATTRs
  * should use the cached attributes, rather than query the daemon
  */
-/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235775 */
-TEST_F(Getattr, DISABLED_attr_cache)
+TEST_F(Getattr, attr_cache)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -52,6 +70,7 @@ TEST_F(Getattr, DISABLED_attr_cache)
 		SET_OUT_HEADER_LEN(out, entry);
 		out->body.entry.attr.mode = S_IFREG | 0644;
 		out->body.entry.nodeid = ino;
+		out->body.entry.entry_valid = UINT64_MAX;
 	})));
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
@@ -76,7 +95,7 @@ TEST_F(Getattr, DISABLED_attr_cache)
  * period passes.
  */
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235773 */
-TEST_F(Getattr, attr_cache_timeout)
+TEST_F(Getattr, DISABLED_attr_cache_timeout)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -88,7 +107,7 @@ TEST_F(Getattr, attr_cache_timeout)
 	 */
 	long timeout_ns = 250'000'000;
 
-	expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
+	expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2, 0, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
 			return (in->header.opcode == FUSE_GETATTR &&
@@ -116,7 +135,7 @@ TEST_F(Getattr, enoent)
 	struct stat sb;
 	const uint64_t ino = 42;
 
-	expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
+	expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1, 0, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
 			return (in->header.opcode == FUSE_GETATTR &&
@@ -135,7 +154,7 @@ TEST_F(Getattr, ok)
 	const uint64_t ino = 42;
 	struct stat sb;
 
-	expect_lookup(RELPATH, ino, S_IFREG | 0644, 1, 1);
+	expect_lookup(RELPATH, ino, S_IFREG | 0644, 1, 1, 0, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
 			return (in->header.opcode == FUSE_GETATTR &&

Modified: projects/fuse2/tests/sys/fs/fusefs/locks.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/locks.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/locks.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -80,7 +80,6 @@ TEST_F(GetlkFallback, local)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 
 	fd = open(FULLPATH, O_RDWR);
 	ASSERT_LE(0, fd) << strerror(errno);
@@ -110,7 +109,6 @@ TEST_F(Getlk, DISABLED_no_locks)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_GETLK &&
@@ -156,7 +154,6 @@ TEST_F(Getlk, DISABLED_lock_exists)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_GETLK &&
@@ -209,7 +206,6 @@ TEST_F(SetlkFallback, local)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 
 	fd = open(FULLPATH, O_RDWR);
 	ASSERT_LE(0, fd) << strerror(errno);
@@ -236,7 +232,6 @@ TEST_F(Setlk, DISABLED_set)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&
@@ -279,7 +274,6 @@ TEST_F(Setlk, DISABLED_set_eof)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&
@@ -322,7 +316,6 @@ TEST_F(Setlk, DISABLED_eagain)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&
@@ -364,7 +357,6 @@ TEST_F(SetlkwFallback, local)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 
 	fd = open(FULLPATH, O_RDWR);
 	ASSERT_LE(0, fd) << strerror(errno);
@@ -395,7 +387,6 @@ TEST_F(Setlkw, DISABLED_set)
 
 	expect_lookup(RELPATH, ino);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&

Modified: projects/fuse2/tests/sys/fs/fusefs/lookup.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/lookup.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/lookup.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -43,8 +43,7 @@ class Lookup: public FuseTest {};
  * If lookup returns a non-zero cache timeout, then subsequent VOP_GETATTRs
  * should use the cached attributes, rather than query the daemon
  */
-/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235775 */
-TEST_F(Lookup, DISABLED_attr_cache)
+TEST_F(Lookup, attr_cache)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -106,7 +105,7 @@ TEST_F(Lookup, DISABLED_attr_cache)
  * the cached attributes and requery the daemon.
  */
 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235773 */
-TEST_F(Lookup, attr_cache_timeout)
+TEST_F(Lookup, DISABLED_attr_cache_timeout)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";

Modified: projects/fuse2/tests/sys/fs/fusefs/open.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/open.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/open.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -61,9 +61,6 @@ void test_ok(int os_flags, int fuse_flags) {
 		SET_OUT_HEADER_LEN(out, open);
 	})));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
-	expect_getattr(ino, 0);
-
 	fd = open(FULLPATH, os_flags);
 	EXPECT_LE(0, fd) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
@@ -204,7 +201,6 @@ TEST_F(Open, multiple_creds)
 			out->header.len = sizeof(out->header);
 			SET_OUT_HEADER_LEN(out, open);
 		})));
-		expect_getattr(ino, 0);
 		expect_flush(ino, 2, ReturnErrno(0));
 		expect_release(ino, fh0);
 		expect_release(ino, fh1);

Modified: projects/fuse2/tests/sys/fs/fusefs/read.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/read.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/read.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -117,7 +117,6 @@ TEST_F(AioRead, aio_read)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	expect_read(ino, 0, bufsize, bufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -152,7 +151,6 @@ TEST_F(AioRead, async_read_disabled)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_READ &&
@@ -230,7 +228,6 @@ TEST_F(AsyncRead, DISABLED_async_read)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_READ &&
@@ -299,7 +296,6 @@ TEST_F(Read, direct_io_read_nothing)
 
 	expect_lookup(RELPATH, ino, offset + 1000);
 	expect_open(ino, FOPEN_DIRECT_IO, 1);
-	expect_getattr(ino, offset + 1000);
 
 	fd = open(FULLPATH, O_RDONLY);
 	ASSERT_LE(0, fd) << strerror(errno);
@@ -325,7 +321,6 @@ TEST_F(Read, direct_io_pread)
 
 	expect_lookup(RELPATH, ino, offset + bufsize);
 	expect_open(ino, FOPEN_DIRECT_IO, 1);
-	expect_getattr(ino, offset + bufsize);
 	expect_read(ino, offset, bufsize, bufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -354,7 +349,6 @@ TEST_F(Read, direct_io_short_read)
 
 	expect_lookup(RELPATH, ino, offset + bufsize);
 	expect_open(ino, FOPEN_DIRECT_IO, 1);
-	expect_getattr(ino, offset + bufsize);
 	expect_read(ino, offset, bufsize, halfbufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -378,7 +372,6 @@ TEST_F(Read, eio)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_READ);
@@ -410,7 +403,6 @@ TEST_F(Read, keep_cache)
 
 	FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, bufsize, 2);
 	expect_open(ino, FOPEN_KEEP_CACHE, 2);
-	expect_getattr(ino, bufsize);
 	expect_read(ino, 0, bufsize, bufsize, CONTENTS);
 
 	fd0 = open(FULLPATH, O_RDONLY);
@@ -445,7 +437,6 @@ TEST_F(Read, keep_cache_disabled)
 
 	FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, bufsize, 2);
 	expect_open(ino, 0, 2);
-	expect_getattr(ino, bufsize);
 	expect_read(ino, 0, bufsize, bufsize, CONTENTS);
 
 	fd0 = open(FULLPATH, O_RDONLY);
@@ -482,7 +473,6 @@ TEST_F(ReadCacheable, mmap)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	/* mmap may legitimately try to read more data than is available */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
@@ -526,7 +516,6 @@ TEST_F(Read, o_direct)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	expect_read(ino, 0, bufsize, bufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -563,7 +552,6 @@ TEST_F(Read, pread)
 
 	expect_lookup(RELPATH, ino, offset + bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, offset + bufsize);
 	expect_read(ino, offset, bufsize, bufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -586,7 +574,6 @@ TEST_F(Read, read)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	expect_read(ino, 0, bufsize, bufsize, CONTENTS);
 
 	fd = open(FULLPATH, O_RDONLY);
@@ -620,7 +607,6 @@ TEST_F(ReadCacheable, default_readahead)
 
 	expect_lookup(RELPATH, ino, filesize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, filesize);
 	expect_read(ino, 0, default_maxreadahead, default_maxreadahead,
 		contents);
 
@@ -651,7 +637,6 @@ TEST_F(ReadCacheable, sendfile)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	/* Like mmap, sendfile may request more data than is available */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
@@ -697,7 +682,6 @@ TEST_F(ReadCacheable, DISABLED_sendfile_eio)
 
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, bufsize);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_READ);
@@ -739,7 +723,6 @@ TEST_P(ReadAhead, DISABLED_readahead) {
 
 	expect_lookup(RELPATH, ino, filesize);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, filesize);
 	/* fuse(4) should only read ahead the allowed amount */
 	expect_read(ino, 0, GetParam(), GetParam(), contents);
 

Modified: projects/fuse2/tests/sys/fs/fusefs/release.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/release.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/release.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -81,7 +81,6 @@ TEST_F(Release, dup)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, ReturnErrno(0));
 	expect_release(ino, 0, O_RDONLY, 0);
 	
@@ -111,7 +110,6 @@ TEST_F(Release, eio)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, ReturnErrno(0));
 	expect_release(ino, 0, O_WRONLY, EIO);
 	
@@ -134,7 +132,6 @@ TEST_F(Release, DISABLED_flags)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, ReturnErrno(0));
 	expect_release(ino, 0, O_RDWR | O_APPEND, 0);
 	
@@ -158,7 +155,6 @@ TEST_F(Release, multiple_opens)
 
 	expect_lookup(RELPATH, ino, 2);
 	expect_open(ino, 0, 2);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 2, ReturnErrno(0));
 	expect_release(ino, 0, O_RDONLY, 0);
 	
@@ -182,7 +178,6 @@ TEST_F(Release, ok)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_flush(ino, 1, ReturnErrno(0));
 	expect_release(ino, 0, O_RDONLY, 0);
 	
@@ -205,7 +200,6 @@ TEST_F(ReleaseWithLocks, DISABLED_unlock_on_close)
 
 	expect_lookup(RELPATH, ino, 1);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_SETLK &&

Modified: projects/fuse2/tests/sys/fs/fusefs/setattr.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/setattr.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/setattr.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -46,8 +46,7 @@ class Setattr : public FuseTest {};
  * If setattr returns a non-zero cache timeout, then subsequent VOP_GETATTRs
  * should use the cached attributes, rather than query the daemon
  */
-/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235775 */
-TEST_F(Setattr, DISABLED_attr_cache)
+TEST_F(Setattr, attr_cache)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -60,11 +59,11 @@ TEST_F(Setattr, DISABLED_attr_cache)
 		SET_OUT_HEADER_LEN(out, entry);
 		out->body.entry.attr.mode = S_IFREG | 0644;
 		out->body.entry.nodeid = ino;
+		out->body.entry.entry_valid = UINT64_MAX;
 	})));
 
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
-			/* In protocol 7.23, ctime will be changed too */
 			return (in->header.opcode == FUSE_SETATTR &&
 				in->header.nodeid == ino);
 		}, Eq(true)),
@@ -73,6 +72,7 @@ TEST_F(Setattr, DISABLED_attr_cache)
 		SET_OUT_HEADER_LEN(out, attr);
 		out->body.attr.attr.ino = ino;	// Must match nodeid
 		out->body.attr.attr.mode = S_IFREG | newmode;
+		out->body.attr.attr_valid = UINT64_MAX;
 	})));
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([](auto in) {
@@ -227,21 +227,8 @@ TEST_F(Setattr, fchmod)
 		SET_OUT_HEADER_LEN(out, open);
 	})));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | oldmode;
-	})));
-
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
 			/* In protocol 7.23, ctime will be changed too */
 			uint32_t valid = FATTR_MODE;
 			return (in->header.opcode == FUSE_SETATTR &&
@@ -294,22 +281,8 @@ TEST_F(Setattr, ftruncate)
 		out->body.open.fh = fh;
 	})));
 
-	/* Until the attr cache is working, we may send an additional GETATTR */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0755;
-		out->body.attr.attr.size = oldsize;
-	})));
-
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([=](auto in) {
 			/* In protocol 7.23, ctime will be changed too */
 			uint32_t valid = FATTR_SIZE | FATTR_FH;
 			return (in->header.opcode == FUSE_SETATTR &&
@@ -502,27 +475,7 @@ TEST_F(Setattr, utimensat) {
 		out->body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
 	})));
 
-	/* 
-	 * Until bug 235775 is fixed, utimensat will make an extra FUSE_GETATTR
-	 * call
-	 */ 
 	EXPECT_CALL(*m_mock, process(
-		ResultOf([](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0644;
-		out->body.attr.attr.atime = oldtimes[0].tv_sec;
-		out->body.attr.attr.atimensec = oldtimes[0].tv_nsec;
-		out->body.attr.attr.mtime = oldtimes[1].tv_sec;
-		out->body.attr.attr.mtimensec = oldtimes[1].tv_nsec;
-	})));
-
-	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			/* In protocol 7.23, ctime will be changed too */
 			uint32_t valid = FATTR_ATIME | FATTR_MTIME;
@@ -574,26 +527,6 @@ TEST_F(Setattr, utimensat_mtime_only) {
 		out->body.entry.attr.atimensec = oldtimes[0].tv_nsec;
 		out->body.entry.attr.mtime = oldtimes[1].tv_sec;
 		out->body.entry.attr.mtimensec = oldtimes[1].tv_nsec;
-	})));
-
-	/* 
-	 * Until bug 235775 is fixed, utimensat will make an extra FUSE_GETATTR
-	 * call
-	 */ 
-	EXPECT_CALL(*m_mock, process(
-		ResultOf([](auto in) {
-			return (in->header.opcode == FUSE_GETATTR &&
-				in->header.nodeid == ino);
-		}, Eq(true)),
-		_)
-	).WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, attr);
-		out->body.attr.attr.ino = ino;	// Must match nodeid
-		out->body.attr.attr.mode = S_IFREG | 0644;
-		out->body.attr.attr.atime = oldtimes[0].tv_sec;
-		out->body.attr.attr.atimensec = oldtimes[0].tv_nsec;
-		out->body.attr.attr.mtime = oldtimes[1].tv_sec;
-		out->body.attr.attr.mtimensec = oldtimes[1].tv_nsec;
 	})));
 
 	EXPECT_CALL(*m_mock, process(

Modified: projects/fuse2/tests/sys/fs/fusefs/unlink.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/unlink.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/unlink.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -92,7 +92,6 @@ TEST_F(Unlink, open_but_deleted)
 
 	expect_lookup(RELPATH, ino, 2);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_unlink(1, RELPATH, 0);
 
 	fd = open(FULLPATH, O_RDWR);

Modified: projects/fuse2/tests/sys/fs/fusefs/utils.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/utils.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/utils.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -144,14 +144,13 @@ FuseTest::expect_flush(uint64_t ino, int times, Proces
 
 void FuseTest::expect_getattr(uint64_t ino, uint64_t size)
 {
-	/* Until the attr cache is working, we may send an additional GETATTR */
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
 			return (in->header.opcode == FUSE_GETATTR &&
 				in->header.nodeid == ino);
 		}, Eq(true)),
 		_)
-	).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
+	).WillOnce(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
 		SET_OUT_HEADER_LEN(out, attr);
 		out->body.attr.attr.ino = ino;	// Must match nodeid
 		out->body.attr.attr.mode = S_IFREG | 0644;

Modified: projects/fuse2/tests/sys/fs/fusefs/write.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/write.cc	Mon Apr  8 18:38:18 2019	(r346042)
+++ projects/fuse2/tests/sys/fs/fusefs/write.cc	Mon Apr  8 18:45:41 2019	(r346043)
@@ -153,7 +153,6 @@ TEST_F(AioWrite, DISABLED_aio_write)
 
 	expect_lookup(RELPATH, ino, 0);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, 0);
 	expect_write(ino, offset, bufsize, bufsize, 0, CONTENTS);
 
 	fd = open(FULLPATH, O_WRONLY);
@@ -197,7 +196,6 @@ TEST_F(Write, append)
 
 	expect_lookup(RELPATH, ino, initial_offset);
 	expect_open(ino, 0, 1);
-	expect_getattr(ino, initial_offset);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list