Date: Mon, 19 Apr 2021 00:44:30 GMT From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 1efbf1a24cfb - stable/12 - nfsd: make the server repeat CB_RECALL every couple of seconds Message-ID: <202104190044.13J0iUgH018344@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=1efbf1a24cfbfb659712ebb29c92b8589485faff commit 1efbf1a24cfbfb659712ebb29c92b8589485faff Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2021-04-05 01:15:54 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> CommitDate: 2021-04-19 00:41:07 +0000 nfsd: make the server repeat CB_RECALL every couple of seconds Commit 01ae8969a9ee stopped the NFSv4.1/4.2 server from implicitly binding the back channel to a new TCP connection so that it conforms to RFC5661, for NFSv4.1/4.2. An effect of this for the Linux NFS client is that it will do a BindConnectionToSession when it sees NFSV4SEQ_CBPATHDOWN set in a sequence reply. This will fix the back channel, but the first attempt at a callback like CB_RECALL will already have failed. Without this patch, a CB_RECALL will not be retried and that can result in a 5 minute delay until the delegation times out. This patch modifies the code so that it will retry the CB_RECALL every couple of seconds, often avoiding the 5 minute delay. This is not critical for correct behaviour, but avoids the 5 minute delay for the case where the Linux client re-binds the back channel via BindConnectionToSession. (cherry picked from commit 7a606f280a3e174dcdd12736b7b976903809eb9c) --- sys/fs/nfs/nfsrvstate.h | 2 ++ sys/fs/nfsserver/nfs_nfsdstate.c | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/fs/nfs/nfsrvstate.h b/sys/fs/nfs/nfsrvstate.h index 2d60e8e8141f..427d5b132281 100644 --- a/sys/fs/nfs/nfsrvstate.h +++ b/sys/fs/nfs/nfsrvstate.h @@ -220,6 +220,7 @@ struct nfsstate { time_t expiry; time_t limit; u_int64_t compref; + time_t last; } deleg; } ls_un; struct nfslockfile *ls_lfp; /* Back pointer */ @@ -238,6 +239,7 @@ struct nfsstate { #define ls_delegtime ls_un.deleg.expiry #define ls_delegtimelimit ls_un.deleg.limit #define ls_compref ls_un.deleg.compref +#define ls_lastrecall ls_un.deleg.last /* * Nfs lock structure. diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 09b637c14e52..5aafebf0dd77 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -3071,6 +3071,7 @@ tryagain: new_deleg->ls_clp = clp; new_deleg->ls_filerev = filerev; new_deleg->ls_compref = nd->nd_compref; + new_deleg->ls_lastrecall = 0; LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_deleg->ls_stateid), new_deleg, ls_hash); @@ -3192,6 +3193,7 @@ tryagain: new_deleg->ls_clp = clp; new_deleg->ls_filerev = filerev; new_deleg->ls_compref = nd->nd_compref; + new_deleg->ls_lastrecall = 0; nfsrv_writedelegcnt++; LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); LIST_INSERT_HEAD(NFSSTATEHASH(clp, @@ -3262,6 +3264,7 @@ tryagain: new_deleg->ls_clp = clp; new_deleg->ls_filerev = filerev; new_deleg->ls_compref = nd->nd_compref; + new_deleg->ls_lastrecall = 0; LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_deleg->ls_stateid), new_deleg, ls_hash); @@ -3340,6 +3343,7 @@ tryagain: new_deleg->ls_clp = clp; new_deleg->ls_filerev = filerev; new_deleg->ls_compref = nd->nd_compref; + new_deleg->ls_lastrecall = 0; LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); LIST_INSERT_HEAD(NFSSTATEHASH(clp, @@ -5252,7 +5256,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, * - check to see if the delegation has expired * - if so, get the v4root lock and then expire it */ - if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { + if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0 || stp->ls_lastrecall < + time_uptime) { /* * - do a recall callback, since not yet done * For now, never allow truncate to be set. To use @@ -5267,11 +5272,14 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, * will be extended when ops are done on the delegation * stateid, up to the timelimit.) */ - stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + - NFSRV_LEASEDELTA; - stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + - NFSRV_LEASEDELTA; - stp->ls_flags |= NFSLCK_DELEGRECALL; + if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) { + stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + + NFSRV_LEASEDELTA; + stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * + nfsrv_lease) + NFSRV_LEASEDELTA; + stp->ls_flags |= NFSLCK_DELEGRECALL; + } + stp->ls_lastrecall = time_uptime + 1; /* * Loop NFSRV_CBRETRYCNT times while the CBRecall replies
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202104190044.13J0iUgH018344>