git: b1af05406b51 - main - nfs_nfsdserv.c: Fix setting of birthtime for some ZFS pools
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 18 Jun 2026 15:47:04 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=b1af05406b5117d76f567056fba0a023a6374465
commit b1af05406b5117d76f567056fba0a023a6374465
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-06-18 15:45:27 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2026-06-18 15:45:27 +0000
nfs_nfsdserv.c: Fix setting of birthtime for some ZFS pools
Some ZFS pools do not support va_birthtime and will return
EINVAL when a VOP_SETATTR() of it is attempted. The MacOS
NFSv4 client sets va_birthtime (TimeCreate) in the same
Setattr with ctime/mtime and other attributes after a new
file is created. The EINVAL failure leaves these new files
messed up (mode == 0).
This patch pretends the setting of TimeCreate succeeded if
ctime/mtime were also set in the same Setattr RPC, which
resolves the problem for the MacOS client.
If this fix is not sufficient, a new pathconf name to detect
if a file system supports birthtime may be needed.
PR: 296066
Tested by: Will <freebsd.geography231@slmails.com>
MFC after: 2 weeks
---
sys/fs/nfsserver/nfs_nfsdserv.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 9e5235f95ed1..fe7f0e217a74 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -579,6 +579,16 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
NFSVNO_SETATTRVAL(&nva2, btime, nva.na_btime);
nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
exp);
+ /*
+ * ZFS stores with early versions do not support va_birthtime
+ * and will reply EINVAL when setting is attempted. This
+ * breaks the MacOS NFSv4 client, so pretend it succeeded if
+ * ctime and/or mtime were set as well.
+ */
+ if (nd->nd_repstat == EINVAL &&
+ (NFSISSET_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET) ||
+ NFSISSET_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET)))
+ nd->nd_repstat = 0;
if (!nd->nd_repstat)
NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMECREATE);
}