Date: Mon, 19 Apr 2021 00:39:53 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: ccd08b9293ca - stable/13 - nfsd: make the server repeat CB_RECALL every couple of seconds Message-ID: <202104190039.13J0dr3a005839@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=ccd08b9293cac51b3c4dcb5e0d261cb7aac0ffef commit ccd08b9293cac51b3c4dcb5e0d261cb7aac0ffef 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:36:26 +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 1cf0dcee99e9..fa7bb3ba9f56 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -3070,6 +3070,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); @@ -3191,6 +3192,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, @@ -3261,6 +3263,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); @@ -3339,6 +3342,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, @@ -5265,7 +5269,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 @@ -5280,11 +5285,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?202104190039.13J0dr3a005839>