From owner-dev-commits-src-all@freebsd.org Sun Apr 11 23:54:42 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9AEEB5E3494; Sun, 11 Apr 2021 23:54:42 +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 4FJTHk3zJ5z4mZ6; Sun, 11 Apr 2021 23:54:42 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 7B4EC55EF; Sun, 11 Apr 2021 23:54:42 +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 13BNsgV1039211; Sun, 11 Apr 2021 23:54:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 13BNsgPU039210; Sun, 11 Apr 2021 23:54:42 GMT (envelope-from git) Date: Sun, 11 Apr 2021 23:54:42 GMT Message-Id: <202104112354.13BNsgPU039210@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: 9edaceca8165 - main - nfsd: cut the Linux NFSv4.1/4.2 some slack w.r.t. RFC5661 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: 9edaceca8165e2864267547311daf145bb520270 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Apr 2021 23:54:42 -0000 The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=9edaceca8165e2864267547311daf145bb520270 commit 9edaceca8165e2864267547311daf145bb520270 Author: Rick Macklem AuthorDate: 2021-04-11 23:51:25 +0000 Commit: Rick Macklem CommitDate: 2021-04-11 23:51:25 +0000 nfsd: cut the Linux NFSv4.1/4.2 some slack w.r.t. RFC5661 Recent testing of network partitioning a FreeBSD NFSv4.1 server from a Linux NFSv4.1 client identified problems with both the FreeBSD server and Linux client. Sometimes, after some Linux NFSv4.1/4.2 clients establish a new TCP connection, they will advance the sequence number for a session slot by 2 instead of 1. RFC5661 specifies that a server should reply NFS4ERR_SEQ_MISORDERED for this case. This might result in a system call error in the client and seems to disable future use of the slot by the client. Since advancing the sequence number by 2 seems harmless, allow this case if vfs.nfs.linuxseqsesshack is non-zero. Note that, if the order of RPCs is actually reversed, a subsequent RPC with a smaller sequence number value for the slot will be received. This will result in a NFS4ERR_SEQ_MISORDERED reply. This has not been observed during testing. Setting vfs.nfs.linuxseqsesshack to 0 will provide RFC5661 compliant behaviour. This fix affects the fairly rare case where a NFSv4 Linux client does a TCP reconnect and then apparently erroneously increments the sequence number for the session slot twice during the reconnect cycle. PR: 254816 MFC after: 2 weeks --- sys/fs/nfs/nfs_commonsubs.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 4afa4c2d9ab4..d7009b1e0ca4 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -98,6 +98,11 @@ int nfs_maxcopyrange = 10 * 1024 * 1024; SYSCTL_INT(_vfs_nfs, OID_AUTO, maxcopyrange, CTLFLAG_RW, &nfs_maxcopyrange, 0, "Max size of a Copy so RPC times reasonable"); +static int nfs_allowskip_sessionseq = 1; +SYSCTL_INT(_vfs_nfs, OID_AUTO, linuxseqsesshack, CTLFLAG_RW, + &nfs_allowskip_sessionseq, 0, "Allow client to skip ahead one seq# for" + " session slot"); + /* * This array of structures indicates, for V4: * retfh - which of 3 types of calling args are used @@ -4614,7 +4619,7 @@ nfsmout: * Handle an NFSv4.1 Sequence request for the session. * If reply != NULL, use it to return the cached reply, as required. * The client gets a cached reply via this call for callbacks, however the - * server gets a cached reply via the nfsv4_seqsess_cachereply() call. + * server gets a cached reply via the nfsv4_seqsess_cacherep() call. */ int nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot, @@ -4648,12 +4653,24 @@ nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot, } else /* No reply cached, so just do it. */ slots[slotid].nfssl_inprog = 1; - } else if ((slots[slotid].nfssl_seq + 1) == seqid) { + } else if (slots[slotid].nfssl_seq + 1 == seqid || + (slots[slotid].nfssl_seq + 2 == seqid && + nfs_allowskip_sessionseq != 0)) { + /* + * Allowing the seqid to be ahead by 2 is technically + * a violation of RFC5661, but it seems harmless to do + * and avoids returning NFSERR_SEQMISORDERED to a + * slightly broken Linux NFSv4.1/4.2 client. + * If the RPCs are really out of order, one with a + * lower seqid will be subsequently received and that + * one will get a NFSERR_SEQMISORDERED reply. + * Can be disabled by setting vfs.nfs.linuxseqsesshack to 0. + */ if (slots[slotid].nfssl_reply != NULL) m_freem(slots[slotid].nfssl_reply); slots[slotid].nfssl_reply = NULL; slots[slotid].nfssl_inprog = 1; - slots[slotid].nfssl_seq++; + slots[slotid].nfssl_seq = seqid; } else error = NFSERR_SEQMISORDERED; return (error);