Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp924832pxp; Wed, 16 Mar 2022 21:30:47 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy/Phf7BDdRluuO1bYI42/VeXOtAC2yBusAHWV3EGxy63RJxoAM0MRYOplcz39k1BF0IjHx X-Received: by 2002:a17:902:8f94:b0:14f:d9b3:52c2 with SMTP id z20-20020a1709028f9400b0014fd9b352c2mr2869461plo.103.1647491447536; Wed, 16 Mar 2022 21:30:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647491447; cv=none; d=google.com; s=arc-20160816; b=tv8mxIpKw69TPasZrk7nvEks0b4TmjMQzKjC0cHvQVgx6o3bDHbHsMqhvvoInXOCOp TE81Dh7TTyIH3Q3SWn9heUVCJjuTelhfIlVBH3Vm6/kgLnBOsG2Cp7O7bqWBZkGvJc/2 oUOEDBjkI4EQyR0w5Tf+bvyE9sfW3NAJ4K6/heaGsPeNC25hm6z0epFP7LV74IK6lu5B VPLThmMnAAUMmDyaIFKJTLXejU6YkOb8JPvptmtGjUTedldU+5TOQvhCt3ujLeXnMPQ1 ERa/6GV9BmFZbtczGezEZCCSxZvDenZvstVvcaWmDOG4G6rUgKUi2t5gqc1efPja0Ibg IWqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=sErw0Jxn2ledoVSmFIoZbk3fAsv/UUypqdqm3PnVX40=; b=wAqB/Hl248KwQ/Nun9J809dnKeywqTbATjYFufaSBofTBdDeiHE9d+ti0cJWLoSpbx Inq2ttxmfs1kxF0VSq6ONfWTfmCMpHFryK4j9vsZ2xEfMIqvsAUDbYesavL5NHMtOuzX 9UwzHkm7wUSMtRdPxlGlmGM5en35wjkUm3n9p54GPd6Kk8i4HWAi0vLzqjqDEicpSuW1 RDh41076eAe9ry/2oa6gVsMUiCFkXp7iSqR3C2gz8Gf/r1HmW+t1oVdrUKWPi8PFwrZ7 f6B/ilN/9LirRsGTuHmWC9UDA0SphoWscrWuypnAsZqLzKdX/5idtEWlt4k7ZTiLpTsY mmng== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=b+AjVT7t; spf=softfail (google.com: domain of transitioning linux-nfs-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id t5-20020a056a0021c500b004f7b6da9ed9si3937731pfj.235.2022.03.16.21.30.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Mar 2022 21:30:47 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-nfs-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=b+AjVT7t; spf=softfail (google.com: domain of transitioning linux-nfs-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A9A8B102404; Wed, 16 Mar 2022 21:00:09 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350096AbiCOQfs (ORCPT + 99 others); Tue, 15 Mar 2022 12:35:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232897AbiCOQfs (ORCPT ); Tue, 15 Mar 2022 12:35:48 -0400 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF71D5005F for ; Tue, 15 Mar 2022 09:34:35 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 1B82FCE1BB4 for ; Tue, 15 Mar 2022 16:34:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CA37C340F4 for ; Tue, 15 Mar 2022 16:34:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1647362072; bh=uJxKKJu2tEJQPfSUQtoREIBPxxuB+bwNaGc87lg9iaE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=b+AjVT7tQ+3zlfR0J/lHMR41QEkFMhOAc2p1TCJk8wmFR1ZalSnDQYm7HawHC9NEt 1/9CCWJLVxIJJBqSkzcojjr4iYKKjFk2Rcsp1Q2jQ8aNAZuAdb5Fylfez5KiiVbrRh H1RWjqi8/ZIFMUImcPFBLAsgogmLrnbwgXTjoNsMxyqMvX9ThIWIvSgDhTo1unUI7Z a/4UV07YWVnAf6v4W1GOdSVopqupAKqVPxGoGfxaFwl2LcUWOw/mLv+3z1AuVkMPnc m97Wrmc8Sdc6pY88WinwCEaDIvLv5KrVwvl9rmAopPLMHncxnR7eMeFX/nFf0mYQiH psYOHVwz0JxXw== From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 3/3] SUNRPC: Improve accuracy of socket ENOBUFS determination Date: Tue, 15 Mar 2022 12:28:05 -0400 Message-Id: <20220315162805.570850-3-trondmy@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220315162805.570850-2-trondmy@kernel.org> References: <20220315162805.570850-1-trondmy@kernel.org> <20220315162805.570850-2-trondmy@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust The current code checks for whether or not the socket is in a writeable state after we get an EAGAIN. That is racy, since we've dropped the socket lock, so the amount of free buffer may have changed. Instead, let's check whether the socket is writeable before we try to write to it. If that was the case, we do expect the message to be at least partially sent unless we're in a low memory situation. Signed-off-by: Trond Myklebust --- net/sunrpc/xprtsock.c | 53 +++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 23cdb841f056..87cc97d6c677 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -805,13 +805,15 @@ static int xs_sock_nospace(struct rpc_rqst *req) return ret; } -static int xs_stream_nospace(struct rpc_rqst *req) +static int xs_stream_nospace(struct rpc_rqst *req, bool vm_wait) { struct sock_xprt *transport = container_of(req->rq_xprt, struct sock_xprt, xprt); struct sock *sk = transport->inet; int ret = -EAGAIN; + if (vm_wait) + return -ENOBUFS; lock_sock(sk); if (!sk_stream_memory_free(sk)) ret = xs_nospace(req, transport); @@ -869,6 +871,7 @@ static int xs_local_send_request(struct rpc_rqst *req) struct msghdr msg = { .msg_flags = XS_SENDMSG_FLAGS, }; + bool vm_wait; unsigned int sent; int status; @@ -881,15 +884,14 @@ static int xs_local_send_request(struct rpc_rqst *req) xs_pktdump("packet data:", req->rq_svec->iov_base, req->rq_svec->iov_len); + vm_wait = sk_stream_is_writeable(transport->inet) ? true : false; + req->rq_xtime = ktime_get(); status = xprt_sock_sendmsg(transport->sock, &msg, xdr, transport->xmit.offset, rm, &sent); dprintk("RPC: %s(%u) = %d\n", __func__, xdr->len - transport->xmit.offset, status); - if (status == -EAGAIN && sock_writeable(transport->inet)) - status = -ENOBUFS; - if (likely(sent > 0) || status == 0) { transport->xmit.offset += sent; req->rq_bytes_sent = transport->xmit.offset; @@ -899,13 +901,12 @@ static int xs_local_send_request(struct rpc_rqst *req) return 0; } status = -EAGAIN; + vm_wait = false; } switch (status) { - case -ENOBUFS: - break; case -EAGAIN: - status = xs_stream_nospace(req); + status = xs_stream_nospace(req, vm_wait); break; default: dprintk("RPC: sendmsg returned unrecognized error %d\n", @@ -1023,7 +1024,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req) struct msghdr msg = { .msg_flags = XS_SENDMSG_FLAGS, }; - bool vm_wait = false; + bool vm_wait; unsigned int sent; int status; @@ -1048,7 +1049,10 @@ static int xs_tcp_send_request(struct rpc_rqst *req) * called sendmsg(). */ req->rq_xtime = ktime_get(); tcp_sock_set_cork(transport->inet, true); - while (1) { + + vm_wait = sk_stream_is_writeable(transport->inet) ? true : false; + + do { status = xprt_sock_sendmsg(transport->sock, &msg, xdr, transport->xmit.offset, rm, &sent); @@ -1069,31 +1073,10 @@ static int xs_tcp_send_request(struct rpc_rqst *req) WARN_ON_ONCE(sent == 0 && status == 0); - if (status == -EAGAIN ) { - /* - * Return EAGAIN if we're sure we're hitting the - * socket send buffer limits. - */ - if (test_bit(SOCK_NOSPACE, &transport->sock->flags)) - break; - /* - * Did we hit a memory allocation failure? - */ - if (sent == 0) { - status = -ENOBUFS; - if (vm_wait) - break; - /* Retry, knowing now that we're below the - * socket send buffer limit - */ - vm_wait = true; - } - continue; - } - if (status < 0) - break; - vm_wait = false; - } + if (sent > 0) + vm_wait = false; + + } while (status == 0); switch (status) { case -ENOTSOCK: @@ -1101,7 +1084,7 @@ static int xs_tcp_send_request(struct rpc_rqst *req) /* Should we call xs_close() here? */ break; case -EAGAIN: - status = xs_stream_nospace(req); + status = xs_stream_nospace(req, vm_wait); break; case -ECONNRESET: case -ECONNREFUSED: -- 2.35.1