Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp2714666imj; Mon, 11 Feb 2019 07:23:58 -0800 (PST) X-Google-Smtp-Source: AHgI3IYjVjFu7nBodtuKLLuYkyp/EiycIM8WTjAnHrrqEEYL3vQDUvwzRTzMFitz2sPGcQoSDUBA X-Received: by 2002:a17:902:112c:: with SMTP id d41mr36852169pla.144.1549898638454; Mon, 11 Feb 2019 07:23:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549898638; cv=none; d=google.com; s=arc-20160816; b=LqCCO8LfkvBa4X7mCnyBhF3VLEGMxFJvvpCG6jIPopDQJkq/VEJQMweeoWHYY6ylZj ON4HhCH1jMvBwd4L4t9VryspLWyLz7JYCkS5T4B/Tx1H/eP2TsTsPhiN9eYrIdXXCnz+ +FS2gW5YMQSsAlQ/GmuH597HnFvoPdLrYNJ4qxPC71i+ODAQN+VKZk1Z5cRRmnbNpJRV U1fQmJ7tru4Dwzz3msldVmxaHvtjwMPFUkCH9SX9exlRLe1zxvo0nN4ppbPg/o3ZTiPa oZjXPARcShDFcePNfAPzcT+EDPheuwCTYyvc2J4RexRFV7OlsoJsovV9wajfi4/9Z+7V nmLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=DfOx52APAPU1S9+EYlfaIyujNccAlW4UTCmPP1k3HH4=; b=c3QW9Efbkc8besQGaLtLveVki3ZDh46NFzATHqTFdNN13bk4VTi7ZmizIq6EeP7/RC OukirZA62xR12t77O25NQCSXZ0QGcTqtBBDv4++6i4CO1dTm6jsy/gZ/J+yQnGN83UOz QXebDoi7qGoypIMbaO5vDo0KdbIlXhAoPYi5WVBC5p724cbQXhIVG+BNBIom7ulhP9KF oyuOdCVjlWt4c1L4haLMZIdpu4U709fAUJtiPHhdKj4b2/SHPRVH0iHR/15b3Nmi0yIW 672kJSujSfEx+tiF7R2mzjL3opfuGT+xy6bLss5mmYnHu1OZVCFYUxhBJJPXw2iFH7ki phLw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=n+1ZRgmu; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cs18si11445135plb.119.2019.02.11.07.23.42; Mon, 11 Feb 2019 07:23:58 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=n+1ZRgmu; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390685AbfBKPEA (ORCPT + 99 others); Mon, 11 Feb 2019 10:04:00 -0500 Received: from mail.kernel.org ([198.145.29.99]:52742 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390692AbfBKPD4 (ORCPT ); Mon, 11 Feb 2019 10:03:56 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C4906222A7; Mon, 11 Feb 2019 15:03:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1549897435; bh=iW6mC8q9qp44OB+XlsbuKgOUXFvnBfbZT40VslXRaxM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=n+1ZRgmuywKtGTJAn2U9xzaTONJ5QeIlyIJtBwES67aGQnU5+LzzBafT2/ZmeEIWq 4R4sxn3zlCA43kY3JjyDoh/9rDpLp3UyrAfDmw6BSTVWEcnjeJSZ88avStp/vokL+h sofdqIzHdr2IP1ixBKjpMyxqR2pKa4IK7Vht6qcI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Olga Kornievskaia , "J. Bruce Fields" , Donald Buczek Subject: [PATCH 4.14 202/205] nfsd4: fix cached replies to solo SEQUENCE compounds Date: Mon, 11 Feb 2019 15:20:00 +0100 Message-Id: <20190211141841.648316810@linuxfoundation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190211141827.214852402@linuxfoundation.org> References: <20190211141827.214852402@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: J. Bruce Fields commit 085def3ade52f2ffe3e31f42e98c27dcc222dd37 upstream. Currently our handling of 4.1+ requests without "cachethis" set is confusing and not quite correct. Suppose a client sends a compound consisting of only a single SEQUENCE op, and it matches the seqid in a session slot (so it's a retry), but the previous request with that seqid did not have "cachethis" set. The obvious thing to do might be to return NFS4ERR_RETRY_UNCACHED_REP, but the protocol only allows that to be returned on the op following the SEQUENCE, and there is no such op in this case. The protocol permits us to cache replies even if the client didn't ask us to. And it's easy to do so in the case of solo SEQUENCE compounds. So, when we get a solo SEQUENCE, we can either return the previously cached reply or NFSERR_SEQ_FALSE_RETRY if we notice it differs in some way from the original call. Currently, we're returning a corrupt reply in the case a solo SEQUENCE matches a previous compound with more ops. This actually matters because the Linux client recently started doing this as a way to recover from lost replies to idempotent operations in the case the process doing the original reply was killed: in that case it's difficult to keep the original arguments around to do a real retry, and the client no longer cares what the result is anyway, but it would like to make sure that the slot's sequence id has been incremented, and the solo SEQUENCE assures that: if the server never got the original reply, it will increment the sequence id. If it did get the original reply, it won't increment, and nothing else that about the reply really matters much. But we can at least attempt to return valid xdr! Tested-by: Olga Kornievskaia Signed-off-by: J. Bruce Fields Signed-off-by: Donald Buczek Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 20 +++++++++++++++----- fs/nfsd/state.h | 1 + fs/nfsd/xdr4.h | 13 +++++++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2331,14 +2331,16 @@ nfsd4_store_cache_entry(struct nfsd4_com dprintk("--> %s slot %p\n", __func__, slot); + slot->sl_flags |= NFSD4_SLOT_INITIALIZED; slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; - slot->sl_flags |= NFSD4_SLOT_INITIALIZED; - if (nfsd4_not_cached(resp)) { - slot->sl_datalen = 0; + if (!nfsd4_cache_this(resp)) { + slot->sl_flags &= ~NFSD4_SLOT_CACHED; return; } + slot->sl_flags |= NFSD4_SLOT_CACHED; + base = resp->cstate.data_offset; slot->sl_datalen = buf->len - base; if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen)) @@ -2365,8 +2367,16 @@ nfsd4_enc_sequence_replay(struct nfsd4_c op = &args->ops[resp->opcnt - 1]; nfsd4_encode_operation(resp, op); - /* Return nfserr_retry_uncached_rep in next operation. */ - if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) { + if (slot->sl_flags & NFSD4_SLOT_CACHED) + return op->status; + if (args->opcnt == 1) { + /* + * The original operation wasn't a solo sequence--we + * always cache those--so this retry must not match the + * original: + */ + op->status = nfserr_seq_false_retry; + } else { op = &args->ops[resp->opcnt++]; op->status = nfserr_retry_uncached_rep; nfsd4_encode_operation(resp, op); --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -174,6 +174,7 @@ struct nfsd4_slot { #define NFSD4_SLOT_INUSE (1 << 0) #define NFSD4_SLOT_CACHETHIS (1 << 1) #define NFSD4_SLOT_INITIALIZED (1 << 2) +#define NFSD4_SLOT_CACHED (1 << 3) u8 sl_flags; char sl_data[]; }; --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -651,9 +651,18 @@ static inline bool nfsd4_is_solo_sequenc return resp->opcnt == 1 && args->ops[0].opnum == OP_SEQUENCE; } -static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) +/* + * The session reply cache only needs to cache replies that the client + * actually asked us to. But it's almost free for us to cache compounds + * consisting of only a SEQUENCE op, so we may as well cache those too. + * Also, the protocol doesn't give us a convenient response in the case + * of a replay of a solo SEQUENCE op that wasn't cached + * (RETRY_UNCACHED_REP can only be returned in the second op of a + * compound). + */ +static inline bool nfsd4_cache_this(struct nfsd4_compoundres *resp) { - return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) + return (resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) || nfsd4_is_solo_sequence(resp); }