From nobody Wed Jul 13 23:30:25 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 03A801D09034; Wed, 13 Jul 2022 23:30:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Ljv4K6gHVz3Zcn; Wed, 13 Jul 2022 23:30:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657755025; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qWJAoqyuYWR8rkwIrigCFf/3wy5/rLOdLRN/KMgx3mQ=; b=nAkrPtg9u0OD83vDtRl+Xj1ABy+qV4h91jatsW0dOJUGd08kdrxUt4VNrTpA/JomDAJbn+ tOaodERuebWMqob8xYXHjgZFU28NlQAb5O2boMI7H191yPo16cNCm5zTHc3BrjUf2FQH4C N9HWIMu1HCRdoAvH+3TL8EsIL1tVGD8xLfnW4htcpuGaV8pFeHfB/HZ5shU471mNiafFIv MkH5SI89Lr8J9XxbNzyD2FRTjICwiSmyyKBXCdFG2pMjfDOHvPVP0RqMHahD7O5477SNt9 LI0TJgFUUmmkyd9GXhZnKo4BySh52aarFS8Fhd7v7kP6S0Hv7Gwz1YBUIMffUQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Ljv4K5k3rzhrQ; Wed, 13 Jul 2022 23:30:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 26DNUP5F003998; Wed, 13 Jul 2022 23:30:25 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 26DNUPio003997; Wed, 13 Jul 2022 23:30:25 GMT (envelope-from git) Date: Wed, 13 Jul 2022 23:30:25 GMT Message-Id: <202207132330.26DNUPio003997@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Rick Macklem Subject: git: 088ba4356a11 - main - nfsd: Fix CreateSession for an established ClientID List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 088ba4356a114416b1d68bf5ae3b3e0accf6d0df Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657755025; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qWJAoqyuYWR8rkwIrigCFf/3wy5/rLOdLRN/KMgx3mQ=; b=UXTvUbjj3kiXiMKorPW4G82PMy71OBw8+f+Md0J0KQ1v4bVFBJ+MBPKDPtAd5kEg5OhLf+ S82DMYnwkUK2iPQvGeKtJWJTCTVTSzX6kZ0su2lSmvts9z3QIkhyWJOnh5WzsiQSck+Usp GfHn5PdCtQVcGIbyQRbRB7qCHx+ViuCm0fRwB5D+JwLwYOhb5kyummMdeDoJkr+tYA41a5 RbrrC1W7FK3AjEm+pZkHa9rSUipa8jRXHlzV/f3z107V5LTaPkhhwlyEJkhhkg7AFu/Mig dZgFxz8QwH4riSwmgFVFYkZhRVpGl1KW2tIQ63hKCx4tj7+2c94wPiKW9Qtu+Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1657755025; a=rsa-sha256; cv=none; b=ev56ZhIvTVJtfbxmZ0miuqFAb49BEVB99nrsvWWRaLHqng0mi4L+eFCrJb13+GeFwdF6Nr QgQ3C7RT5ap82D7vAiJHX2S3xrLFnRKfGUkKkVon4xhzjXCnJ+AWhOFkvyscQXka9y6RBP QYufRnjALdsbJezVf8unDp3+hRDgi4aAUjMjjsvgBUBUCDD/HRddvj3FuSPdNVIHOrtVwd XQ966CWnIepz8PjKFwdEI/YpAnll9kuNWHu3WbyICdmDUzLGoa3M0YQr9UfWp/1N/gp6Yl S9o2gYOZKw2L55uZ3QBeJSSK2/yK62ScCAMM3uO+ArcGwPOSR8vrSjTYpxSvuQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=088ba4356a114416b1d68bf5ae3b3e0accf6d0df commit 088ba4356a114416b1d68bf5ae3b3e0accf6d0df Author: Rick Macklem AuthorDate: 2022-07-13 23:28:56 +0000 Commit: Rick Macklem CommitDate: 2022-07-13 23:28:56 +0000 nfsd: Fix CreateSession for an established ClientID I mis-read the RFC w.r.t. handling of the sequenceid when a CreateSession is done after the initial one that confirms the ClientID. Fortunately this does not affect most extant NFSv4.1/4.2 clients, since they only acquire a single session for TCP for a ClientID (Solaris might be an exception?). This patch fixes the server to handle this case, where the RFC requires the sequenceid be incremented for each CreateSession and is required to reply to a retried CreateSession with a cached reply. It adds a field to nfsclient called lc_prevsess, which caches the sessionid, which is the only field in a CreateSession reply that will change for a retry, to implement this reply cache. The recent commits up to d4a11b3e3bdd that mark session slots bad when "intr" and/or "soft" mounts are used by the client needs this server patch. Without this patch, the client will do a full recovery, including a new ClientID, losing all byte range locks. However, prior to the recent client commits, the client would hang when all session slots were bad, so even without this patch it is not a regression. PR: 260011 MFC after: 2 weeks --- sys/fs/nfs/nfsrvstate.h | 1 + sys/fs/nfsserver/nfs_nfsdstate.c | 63 ++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/sys/fs/nfs/nfsrvstate.h b/sys/fs/nfs/nfsrvstate.h index 9eebeece9727..4c171e8b3f50 100644 --- a/sys/fs/nfs/nfsrvstate.h +++ b/sys/fs/nfs/nfsrvstate.h @@ -99,6 +99,7 @@ struct nfsclient { struct nfsstatehead lc_deleg; /* Delegations */ struct nfsstatehead lc_olddeleg; /* and old delegations */ struct nfssessionhead lc_session; /* List of NFSv4.1 sessions */ + uint64_t lc_prevsess; /* CreateSession cache */ time_t lc_expiry; /* Expiry time (sec) */ time_t lc_delegtime; /* Old deleg expiry (sec) */ nfsquad_t lc_clientid; /* 64 bit clientid */ diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index eafb7c958396..aac845e68af7 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -336,10 +336,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, * Add it after assigning a client id to it. */ new_clp->lc_flags |= LCL_NEEDSCONFIRM; - if ((nd->nd_flag & ND_NFSV41) != 0) - new_clp->lc_confirm.lval[0] = confirmp->lval[0] = - ++confirm_index; - else + if ((nd->nd_flag & ND_NFSV41) != 0) { + confirmp->lval[0] = ++confirm_index; + new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; + } else confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; clientidp->lval[0] = new_clp->lc_clientid.lval[0] = @@ -348,6 +348,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, nfsrv_nextclientindex(); new_clp->lc_stateindex = 0; new_clp->lc_statemaxindex = 0; + new_clp->lc_prevsess = 0; new_clp->lc_cbref = 0; new_clp->lc_expiry = nfsrv_leaseexpiry(); LIST_INIT(&new_clp->lc_open); @@ -449,10 +450,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, } new_clp->lc_flags |= LCL_NEEDSCONFIRM; - if ((nd->nd_flag & ND_NFSV41) != 0) - new_clp->lc_confirm.lval[0] = confirmp->lval[0] = - ++confirm_index; - else + if ((nd->nd_flag & ND_NFSV41) != 0) { + confirmp->lval[0] = ++confirm_index; + new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; + } else confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; clientidp->lval[0] = new_clp->lc_clientid.lval[0] = @@ -461,6 +462,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, nfsrv_nextclientindex(); new_clp->lc_stateindex = 0; new_clp->lc_statemaxindex = 0; + new_clp->lc_prevsess = 0; new_clp->lc_cbref = 0; new_clp->lc_expiry = nfsrv_leaseexpiry(); @@ -596,6 +598,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, struct nfssessionhash *shp; struct nfsdsession *sep; uint64_t sessid[2]; + bool sess_replay; static uint64_t next_sess = 0; if (clpp) @@ -676,13 +679,29 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, * Perform any operations specified by the opflags. */ if (opflags & CLOPS_CONFIRM) { - if ((nd->nd_flag & ND_NFSV41) != 0 && - clp->lc_confirm.lval[0] != confirm.lval[0]) + sess_replay = false; + if ((nd->nd_flag & ND_NFSV41) != 0) { + /* + * For the case where lc_confirm.lval[0] == confirm.lval[0], + * use the new session, but with the previous sessionid. + * This is not exactly what the RFC describes, but should + * result in the same reply as the previous CreateSession. + */ + if (clp->lc_confirm.lval[0] + 1 == confirm.lval[0]) { + clp->lc_confirm.lval[0] = confirm.lval[0]; + clp->lc_prevsess = sessid[0]; + } else if (clp->lc_confirm.lval[0] == confirm.lval[0]) { + if (clp->lc_prevsess == 0) + error = NFSERR_SEQMISORDERED; + else + sessid[0] = clp->lc_prevsess; + sess_replay = true; + } else error = NFSERR_SEQMISORDERED; - else if ((nd->nd_flag & ND_NFSV41) == 0 && + } else if ((nd->nd_flag & ND_NFSV41) == 0 && clp->lc_confirm.qval != confirm.qval) error = NFSERR_STALECLIENTID; - else if (nfsrv_notsamecredname(nd, clp)) + if (error == 0 && nfsrv_notsamecredname(nd, clp)) error = NFSERR_CLIDINUSE; if (!error) { @@ -716,7 +735,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, if (nsep != NULL) { /* Hold a reference on the xprt for a backchannel. */ if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) - != 0) { + != 0 && !sess_replay) { if (clp->lc_req.nr_client == NULL) clp->lc_req.nr_client = (struct __rpc_client *) clnt_bck_create(nd->nd_xprt->xp_socket, @@ -735,14 +754,16 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, NFSX_V4SESSIONID); NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid, NFSX_V4SESSIONID); - shp = NFSSESSIONHASH(nsep->sess_sessionid); - NFSLOCKSTATE(); - NFSLOCKSESSION(shp); - LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); - LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); - nsep->sess_clp = clp; - NFSUNLOCKSESSION(shp); - NFSUNLOCKSTATE(); + if (!sess_replay) { + shp = NFSSESSIONHASH(nsep->sess_sessionid); + NFSLOCKSTATE(); + NFSLOCKSESSION(shp); + LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); + LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); + nsep->sess_clp = clp; + NFSUNLOCKSESSION(shp); + NFSUNLOCKSTATE(); + } } } } else if (clp->lc_flags & LCL_NEEDSCONFIRM) {