nfsd: fix NFSv4.0 seqid handling for ERELOOKUP

Commit 774a36851e 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.
This commit is contained in:
Rick Macklem 2021-01-01 14:21:51 -08:00
parent 774a36851e
commit dc78533a52
3 changed files with 8 additions and 0 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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);