git: 0b9f4c6b0a03 - stable/14 - nfs_nfsdserv.c: Fix setting of birthtime for some ZFS pools
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 02 Jul 2026 01:21:11 UTC
The branch stable/14 has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=0b9f4c6b0a03df1522bba415b67d875a1e73f811
commit 0b9f4c6b0a03df1522bba415b67d875a1e73f811
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-06-18 15:45:27 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2026-07-02 00:19:24 +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
(cherry picked from commit b1af05406b5117d76f567056fba0a023a6374465)
---
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 8d4501a286cc..3a5c45bacda8 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -545,6 +545,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);
}