git: dc78533a5204 - main - nfsd: fix NFSv4.0 seqid handling for ERELOOKUP

Rick Macklem rmacklem at FreeBSD.org
Fri Jan 1 22:24:12 UTC 2021


The branch main has been updated by rmacklem:

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

commit dc78533a5204ae487bf9b27badb134ffa40733ab
Author:     Rick Macklem <rmacklem at FreeBSD.org>
AuthorDate: 2021-01-01 22:21:51 +0000
Commit:     Rick Macklem <rmacklem at FreeBSD.org>
CommitDate: 2021-01-01 22:21:51 +0000

    nfsd: fix NFSv4.0 seqid handling for ERELOOKUP
    
    Commit 774a36851e0e fixed the NFS server so that it could handle
    ERELOOKUP returns from VOP calls by redoing the operation/RPC.
    However, for NFSv4.0, redoing an Open would increment
    the open_owner's seqid multiple times, breaking the protocol.
    This patch sets a new flag called ND_ERELOOKUP on the RPC when
    a redo is in progress.  Then the code that increments the seqid
    avoids the seqid increment/check when the flag is set, since
    it indicates this has already been done for the Open.
---
 sys/fs/nfs/nfs.h                  | 1 +
 sys/fs/nfsserver/nfs_nfsdsocket.c | 2 ++
 sys/fs/nfsserver/nfs_nfsdstate.c  | 5 +++++
 3 files changed, 8 insertions(+)

diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index f6acb807fc6e..44b6042a2ce7 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -721,6 +721,7 @@ struct nfsrv_descript {
 #define	ND_EXTLS		0x8000000000
 #define	ND_EXTLSCERT		0x10000000000
 #define	ND_EXTLSCERTUSER	0x20000000000
+#define	ND_ERELOOKUP		0x40000000000
 
 /*
  * ND_GSS should be the "or" of all GSS type authentications.
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c
index 1a54914fc9dc..530ebb8a8cc8 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -1212,8 +1212,10 @@ tryagain:
 			 */
 			nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
 			nd->nd_repstat = 0;
+			nd->nd_flag |= ND_ERELOOKUP;
 			goto tryagain;
 		}
+		nd->nd_flag &= ~ND_ERELOOKUP;
 
 		if (statsinprog != 0) {
 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index f80b386ae839..1f6e8b7ef526 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -4016,6 +4016,11 @@ nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
 		printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
 		panic("nfsrvstate op refcnt");
 	}
+
+	/* If ND_ERELOOKUP is set, the seqid has already been handled. */
+	if ((nd->nd_flag & ND_ERELOOKUP) != 0)
+		goto out;
+
 	if ((stp->ls_seq + 1) == seqid) {
 		if (stp->ls_op)
 			nfsrvd_derefcache(stp->ls_op);


More information about the dev-commits-src-main mailing list