git: 55b80e2ca52c - main - fusefs: fix invalid value for st_birthtime.tv_nsec

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Sun, 04 Feb 2024 21:02:53 UTC
The branch main has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=55b80e2ca52c4b27c4920d372a6e71ac9ab7da9e

commit 55b80e2ca52c4b27c4920d372a6e71ac9ab7da9e
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-01-25 15:19:37 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-02-04 21:01:06 +0000

    fusefs: fix invalid value for st_birthtime.tv_nsec
    
    If a file system's on-disk format does not support st_birthtime, it
    isn't clear what value it should return in stat(2).  Neither our man
    page nor the OpenGroup specifies.  But our convention for UFS and
    msdosfs is to return { .tv_sec = -1, .tv_nsec = 0 }.  fusefs is
    different.  It returns { .tv_sec = -1, .tv_nsec = -1 }.  It's done that
    ever since the initial import in SVN r241519.
    
    Most software apparently handles this just fine.  It must, because we've
    had no complaints.  But the Rust standard library will panic when
    reading such a timestamp during std::fs::metadata, even if the caller
    doesn't care about that particular value.  That's a separate bug, and
    should be fixed.
    
    Change our invalid value to match msdosfs and ufs, pacifying the Rust
    standard library.
    
    PR:             276602
    MFC after:      1 week
    Sponsored by:   Axcient
    Reviewed by:    emaste
    Differential Revision: https://reviews.freebsd.org/D43590
---
 sys/fs/fuse/fuse_internal.c    |  1 -
 sys/fs/fuse/fuse_node.c        |  7 +++++++
 tests/sys/fs/fusefs/getattr.cc | 15 +++++++++------
 tests/sys/fs/fusefs/lookup.cc  | 15 +++++++++------
 4 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c
index f4a2e7efc908..ffbf1f9bcc40 100644
--- a/sys/fs/fuse/fuse_internal.c
+++ b/sys/fs/fuse/fuse_internal.c
@@ -325,7 +325,6 @@ fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
 	else
 		return;
 
-	vattr_null(vp_cache_at);
 	vp_cache_at->va_fsid = mp->mnt_stat.f_fsid.val[0];
 	vp_cache_at->va_fileid = attr->ino;
 	vp_cache_at->va_mode = attr->mode & ~S_IFMT;
diff --git a/sys/fs/fuse/fuse_node.c b/sys/fs/fuse/fuse_node.c
index ecff94cf6dd9..13c2b59c7c97 100644
--- a/sys/fs/fuse/fuse_node.c
+++ b/sys/fs/fuse/fuse_node.c
@@ -155,7 +155,14 @@ fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
 {
 	fvdat->nid = nodeid;
 	LIST_INIT(&fvdat->handles);
+
 	vattr_null(&fvdat->cached_attrs);
+	fvdat->cached_attrs.va_birthtime.tv_sec = -1;
+	fvdat->cached_attrs.va_birthtime.tv_nsec = 0;
+	fvdat->cached_attrs.va_fsid = VNOVAL;
+	fvdat->cached_attrs.va_gen = 0;
+	fvdat->cached_attrs.va_rdev = NODEV;
+
 	if (nodeid == FUSE_ROOT_ID) {
 		vp->v_vflag |= VV_ROOT;
 	}
diff --git a/tests/sys/fs/fusefs/getattr.cc b/tests/sys/fs/fusefs/getattr.cc
index 1795f29a5d76..98a757fdff94 100644
--- a/tests/sys/fs/fusefs/getattr.cc
+++ b/tests/sys/fs/fusefs/getattr.cc
@@ -246,12 +246,15 @@ TEST_F(Getattr, ok)
 	EXPECT_EQ(ino, sb.st_ino);
 	EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
 
-	//st_birthtim and st_flags are not supported by protocol 7.8.  They're
-	//only supported as OS-specific extensions to OSX.
-	//EXPECT_EQ(, sb.st_birthtim);
-	//EXPECT_EQ(, sb.st_flags);
-	
-	//FUSE can't set st_blksize until protocol 7.9
+	/*
+	 * st_birthtim and st_flags are not supported by the fuse protocol.
+	 * They're only supported as OS-specific extensions to OSX.  For
+	 * birthtime, the convention for "not supported" is "negative one
+	 * second".
+	 */
+	EXPECT_EQ(-1, sb.st_birthtim.tv_sec);
+	EXPECT_EQ(0, sb.st_birthtim.tv_nsec);
+	EXPECT_EQ(0u, sb.st_flags);
 }
 
 /*
diff --git a/tests/sys/fs/fusefs/lookup.cc b/tests/sys/fs/fusefs/lookup.cc
index 549df0369fa7..6d506c1ab700 100644
--- a/tests/sys/fs/fusefs/lookup.cc
+++ b/tests/sys/fs/fusefs/lookup.cc
@@ -112,12 +112,15 @@ TEST_F(Lookup, attr_cache)
 	// fuse(4) does not _yet_ support inode generations
 	//EXPECT_EQ(generation, sb.st_gen);
 
-	//st_birthtim and st_flags are not supported by protocol 7.8.  They're
-	//only supported as OS-specific extensions to OSX.
-	//EXPECT_EQ(, sb.st_birthtim);
-	//EXPECT_EQ(, sb.st_flags);
-	
-	//FUSE can't set st_blksize until protocol 7.9
+	/*
+	 * st_birthtim and st_flags are not supported by the fuse protocol.
+	 * They're only supported as OS-specific extensions to OSX.  For
+	 * birthtime, the convention for "not supported" is "negative one
+	 * second".
+	 */
+	EXPECT_EQ(-1, sb.st_birthtim.tv_sec);
+	EXPECT_EQ(0, sb.st_birthtim.tv_nsec);
+	EXPECT_EQ(0u, sb.st_flags);
 }
 
 /*