aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2021-07-20 00:35:39 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2021-08-05 00:30:40 +0000
commitdfe4c2024fbc0df2d73bb0be71736943533b4a9a (patch)
tree3b3f1d2e6e2f01154a3ad7288f1f1871e4f97909
parent5f27244beb8a1943238e64f530270679fbfa8e16 (diff)
downloadsrc-dfe4c2024fbc0df2d73bb0be71736943533b4a9a.tar.gz
src-dfe4c2024fbc0df2d73bb0be71736943533b4a9a.zip
nfscl: Send stateid.seqid of 0 for NFSv4.1/4.2 mounts
For NFSv4.1/4.2, the client may set the "seqid" field of the stateid to 0 in RPC requests. This indicates to the server that it should not check the "seqid" or return NFSERR_OLDSTATEID if the "seqid" value is not up to date w.r.t. Open/Lock operations on the stateid. This "seqid" is incremented by the NFSv4 server for each Open/OpenDowngrade/Lock/Locku operation done on the stateid. Since a failure return of NFSERR_OLDSTATEID is of no use to the client for I/O operations, it makes sense to set "seqid" to 0 for the stateid argument for I/O operations. This avoids server failure replies of NFSERR_OLDSTATEID, although I am not aware of any case where this failure occurs. This makes the FreeBSD NFSv4.1/4.2 client compatible with the Linux NFSv4.1/4.2 client. (cherry picked from commit 7685f8344d9a59e9498bdfebb48066f98216fecd)
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 8ea5d77d2053..406dcc9d9b80 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -569,7 +569,11 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
!NFSBCMP(nfhp, dp->nfsdl_fh, fhlen)) {
if (!(mode & NFSV4OPEN_ACCESSWRITE) ||
(dp->nfsdl_flags & NFSCLDL_WRITE)) {
- stateidp->seqid = dp->nfsdl_stateid.seqid;
+ if (NFSHASNFSV4N(nmp))
+ stateidp->seqid = 0;
+ else
+ stateidp->seqid =
+ dp->nfsdl_stateid.seqid;
stateidp->other[0] = dp->nfsdl_stateid.other[0];
stateidp->other[1] = dp->nfsdl_stateid.other[1];
stateidp->other[2] = dp->nfsdl_stateid.other[2];
@@ -604,8 +608,10 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
own, own, mode, &lp, &op);
if (error == 0 && lp != NULL && fords == 0) {
/* Don't return a lock stateid for a DS. */
- stateidp->seqid =
- lp->nfsl_stateid.seqid;
+ if (NFSHASNFSV4N(nmp))
+ stateidp->seqid = 0;
+ else
+ stateidp->seqid = lp->nfsl_stateid.seqid;
stateidp->other[0] =
lp->nfsl_stateid.other[0];
stateidp->other[1] =
@@ -656,7 +662,10 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
/*
* No lock stateid, so return the open stateid.
*/
- stateidp->seqid = op->nfso_stateid.seqid;
+ if (NFSHASNFSV4N(nmp))
+ stateidp->seqid = 0;
+ else
+ stateidp->seqid = op->nfso_stateid.seqid;
stateidp->other[0] = op->nfso_stateid.other[0];
stateidp->other[1] = op->nfso_stateid.other[1];
stateidp->other[2] = op->nfso_stateid.other[2];