From patchwork Tue Sep 20 12:37:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 9341599 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DAE626077A for ; Tue, 20 Sep 2016 12:37:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CB3262964F for ; Tue, 20 Sep 2016 12:37:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BFD2629652; Tue, 20 Sep 2016 12:37:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D30CB2964F for ; Tue, 20 Sep 2016 12:37:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751765AbcITMhV (ORCPT ); Tue, 20 Sep 2016 08:37:21 -0400 Received: from smtp02.citrix.com ([66.165.176.63]:27518 "EHLO SMTP02.CITRIX.COM" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752070AbcITMhU (ORCPT ); Tue, 20 Sep 2016 08:37:20 -0400 X-IronPort-AV: E=Sophos;i="5.30,368,1470700800"; d="scan'208";a="387614230" From: Ross Lagerwall To: CC: Steve French , Ross Lagerwall Subject: [PATCH] cifs: Limit the overall credit acquired Date: Tue, 20 Sep 2016 13:37:13 +0100 Message-ID: <1474375033-19895-1-git-send-email-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 X-DLP: MIA1 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The kernel client requests 2 credits for many operations even though they only use 1 credit (presumably to build up a buffer of credit). Some servers seem to give the client as much credit as is requested. In this case, the amount of credit the client has continues increasing to the point where (server->credits * MAX_BUFFER_SIZE) overflows in smb2_wait_mtu_credits(). Fix this by throttling the credit requests if an set limit is reached. For async requests where the credit charge may be > 1, request as much credit as what is charged. The limit is chosen somewhat arbitrarily. The Windows client defaults to 128 credits, the Windows server allows clients up to 512 credits, and the NetApp server does not limit clients at all. Choose a high enough value such that the client shouldn't limit performance. This behavior was seen with a NetApp filer (NetApp Release 9.0RC2). Signed-off-by: Ross Lagerwall --- fs/cifs/smb2glob.h | 10 ++++++++++ fs/cifs/smb2pdu.c | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index 0ffa180..0e1d788 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h @@ -61,4 +61,14 @@ /* Maximum buffer size value we can send with 1 credit */ #define SMB2_MAX_BUFFER_SIZE 65536 +/* + * Maximum number of credits to keep available. + * This value is chosen somewhat arbitrarily. The Windows client + * defaults to 128 credits, the Windows server allows clients up to + * 512 credits, and the NetApp server does not limit clients at all. + * Choose a high enough value such that the client shouldn't limit + * performance. + */ +#define SMB2_MAX_CREDITS_AVAILABLE 1024 + #endif /* _SMB2_GLOB_H */ diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 29e06db..967a790 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -100,7 +100,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , hdr->ProtocolId = SMB2_PROTO_NUMBER; hdr->StructureSize = cpu_to_le16(64); hdr->Command = smb2_cmd; - hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */ + if (tcon && tcon->ses && tcon->ses->server) { + struct TCP_Server_Info *server = tcon->ses->server; + + spin_lock(&server->req_lock); + /* Request up to 2 credits but don't go over the limit. */ + if (server->credits >= SMB2_MAX_CREDITS_AVAILABLE) + hdr->CreditRequest = cpu_to_le16(0); + else + hdr->CreditRequest = cpu_to_le16( + min_t(int, SMB2_MAX_CREDITS_AVAILABLE - + server->credits, 2)); + spin_unlock(&server->req_lock); + } else { + hdr->CreditRequest = cpu_to_le16(2); + } hdr->ProcessId = cpu_to_le32((__u16)current->tgid); if (!tcon) @@ -2057,6 +2071,7 @@ smb2_async_readv(struct cifs_readdata *rdata) if (rdata->credits) { buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, SMB2_MAX_BUFFER_SIZE)); + buf->CreditRequest = buf->CreditCharge; spin_lock(&server->req_lock); server->credits += rdata->credits - le16_to_cpu(buf->CreditCharge); @@ -2243,6 +2258,7 @@ smb2_async_writev(struct cifs_writedata *wdata, if (wdata->credits) { req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, SMB2_MAX_BUFFER_SIZE)); + req->hdr.CreditRequest = req->hdr.CreditCharge; spin_lock(&server->req_lock); server->credits += wdata->credits - le16_to_cpu(req->hdr.CreditCharge);