git: 709c18911ad7 - main - nfsd: Add support for the NFSv4.2 change_attr_type attribute
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 20 Jan 2025 21:52:42 UTC
The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=709c18911ad70978d47198556c0fb1c0e703fb68 commit 709c18911ad70978d47198556c0fb1c0e703fb68 Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2025-01-20 21:51:33 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> CommitDate: 2025-01-20 21:51:33 +0000 nfsd: Add support for the NFSv4.2 change_attr_type attribute Richard Kojedzinszky reported an intermittent problem where the Linux NFSv4.2 client would sometimes not see changes done to a directory by another client, although the change attribute for the directory had changed. A test patch that added the change_attr_type attribute to the server and always returned NFS4_CHANGE_TYPE_VERSION_COUNTER_NOPNFS seems to have resolved the issue. Somewhat oddly, the Linux knfsd server does not support this attribute but does not seem to exhibit the stale caching problem. This patch uses the VFCF_FILEREVINC flag on a file system (UFS, ZFS) to return NFS4_CHANGE_TYPE_VERSION_COUNTER_NOPNFS. It also returns NFS4_CHANGE_TYPE_TIME_METADATA if VFCF_FILEREVCT is set, which may be useful for exported fuse file systems. PR: 284186 Reported by: Richard Kojedzinszky <richard@kojedz.in> Tested by: Richard Kojedzinszky <richard@kojedz.in> MFC after: 2 weeks --- sys/fs/nfs/nfs_commonsubs.c | 32 ++++++++++++++++++++++++++++++++ sys/fs/nfs/nfsproto.h | 11 ++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index fc01630f77f9..d4d97f4eb966 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -2303,6 +2303,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp, if (compare && !(*retcmpp) && i != nfs_srvmaxio) *retcmpp = NFSERR_NOTSAME; break; + case NFSATTRBIT_CHANGEATTRTYPE: + NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); + if (compare) { + if (!(*retcmpp)) { + tuint = NFSV4CHANGETYPE_UNDEFINED; + if ((vp->v_mount->mnt_vfc->vfc_flags & + VFCF_FILEREVINC) != 0) + tuint = NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS; + else if ((vp->v_mount->mnt_vfc->vfc_flags & + VFCF_FILEREVCT) != 0) + tuint = NFSV4CHANGETYPE_TIME_METADATA; + if (fxdr_unsigned(uint32_t, *tl) != tuint) + *retcmpp = NFSERR_NOTSAME; + } + } + attrsum += NFSX_UNSIGNED; + break; default: printf("EEK! nfsv4_loadattr unknown attr=%d\n", bitpos); @@ -3127,6 +3144,21 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, *tl = 0; retnum += 2 * NFSX_UNSIGNED; break; + case NFSATTRBIT_CHANGEATTRTYPE: + NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); + *tl = txdr_unsigned(NFSV4CHANGETYPE_UNDEFINED); + if (mp != NULL) { + if ((mp->mnt_vfc->vfc_flags & + VFCF_FILEREVINC) != 0) + *tl = txdr_unsigned( + NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS); + else if ((mp->mnt_vfc->vfc_flags & + VFCF_FILEREVCT) != 0) + *tl = txdr_unsigned( + NFSV4CHANGETYPE_TIME_METADATA); + } + retnum += NFSX_UNSIGNED; + break; default: printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos); } diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h index ce7acf102d41..323746ebbb6c 100644 --- a/sys/fs/nfs/nfsproto.h +++ b/sys/fs/nfs/nfsproto.h @@ -1176,6 +1176,7 @@ struct nfsv3_sattr { NFSATTRBM_LAYOUTBLKSIZE | \ NFSATTRBM_LAYOUTALIGNMENT | \ NFSATTRBM_SUPPATTREXCLCREAT | \ + NFSATTRBM_CHANGEATTRTYPE | \ NFSATTRBM_XATTRSUPPORT) /* @@ -1221,7 +1222,8 @@ struct nfsv3_sattr { * NFSATTRBIT_NFSV42 - Attributes only supported by NFSv4.2. */ #define NFSATTRBIT_NFSV42_2 \ - (NFSATTRBM_XATTRSUPPORT | \ + (NFSATTRBM_CHANGEATTRTYPE | \ + NFSATTRBM_XATTRSUPPORT | \ NFSATTRBM_MODEUMASK) /* @@ -1657,4 +1659,11 @@ typedef struct nfsv4stateid nfsv4stateid_t; #define NFSV4SXATTR_CREATE 1 #define NFSV4SXATTR_REPLACE 2 +/* Values for ChangeAttrType (RFC-7862). */ +#define NFSV4CHANGETYPE_MONOTONIC_INCR 0 +#define NFSV4CHANGETYPE_VERS_COUNTER 1 +#define NFSV4CHANGETYPE_VERS_COUNTER_NOPNFS 2 +#define NFSV4CHANGETYPE_TIME_METADATA 3 +#define NFSV4CHANGETYPE_UNDEFINED 4 + #endif /* _NFS_NFSPROTO_H_ */