From patchwork Wed Feb 20 23:35:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 10822859 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2792D17E4 for ; Wed, 20 Feb 2019 23:36:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 138F72F1C8 for ; Wed, 20 Feb 2019 23:36:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 07AB42FC00; Wed, 20 Feb 2019 23:36:07 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,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 756372F1C8 for ; Wed, 20 Feb 2019 23:36:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726304AbfBTXgG (ORCPT ); Wed, 20 Feb 2019 18:36:06 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:38149 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726126AbfBTXgF (ORCPT ); Wed, 20 Feb 2019 18:36:05 -0500 Received: by mail-pl1-f196.google.com with SMTP id e5so13077625plb.5 for ; Wed, 20 Feb 2019 15:36:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=gl6wLsK421P2iEH+tnmE/IxRCFPkhT5JDzl0zhLJGi8=; b=Ts0uGlKIK6G4Grd/CnaeqHtFX72mKYPfykUKRhqDmDduJKaj3KW1N/Hs1cH5o0zv9u fVx8oVCAre35QSFHi/AsQeWtNPtIzvr1z7xVnx88nosBiIXZRBuhZnbVT7stixdAIHj5 3V77tQeSg8EyD5CZ830+Ukwj6RaF2G1HSCJ4GB4KL+fe5pXDA1gLO5BwgdCkdb+HIJXZ KdC79ifeI4ve6qKbpcSe+nw9nfS4ulw15/dAwedyG/XOVNFMbHSVePOuG4Hn8SfwLd/y Dk9GBdpRydmM+ejeSDh6F/qtW0CEm/EwXeOmvyXNRZBvFBkJl4x6OKL+vzaijUNURcjO 1L+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=gl6wLsK421P2iEH+tnmE/IxRCFPkhT5JDzl0zhLJGi8=; b=MmM2M9de39xOSUNG8xK07qR3XcZ0t14p5vadafoUv0w1dipDO1YqIsuGSOU24lxeMO c46GaEcb1yyjssh4hOcwCMGH1zMawRKLT12jO76IrUoqqaC8tQGwLm68KN/ROkJNmaxr FozTXz7YzeSANrbQcqjYhOOc//UCXbR8LRwaDouIuyKHUTgTPYuROhmNt/EMD7qDcCL4 9z5BKQb7I0l+OdKlHTQ2dMDP6Y0HS/cyO+/cxI8ToTWwkPUx50PPlAeewSk9wAan4J6V wNktIALQBzhOILYqhp+wfJ1XWRRDFL2sQlbJqNiB8KhU88d8H/hOxey+i3mSFMgRhEXr HQ9A== X-Gm-Message-State: AHQUAuajCNUdHpL8KWHvEt2W7pHP8m4sOZlb+eHXqrk/cYGzqnc+RPh6 CerLPSsQ+DP8svd4/urBe6TnmkQ= X-Google-Smtp-Source: AHgI3IaMqkfj6rEzgdp9V8eJcZp0nryiYABi9/EYa09UVwpGwJHT7JogoGBgbklQZ/sRjpZtB7IYcw== X-Received: by 2002:a17:902:1105:: with SMTP id d5mr38125933pla.47.1550705764586; Wed, 20 Feb 2019 15:36:04 -0800 (PST) Received: from ubuntu-vm.corp.microsoft.com ([2001:4898:80e8:0:a18e:4e9f:6b7c:507d]) by smtp.gmail.com with ESMTPSA id f16sm31941550pgg.20.2019.02.20.15.36.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Feb 2019 15:36:03 -0800 (PST) From: Pavel Shilovsky X-Google-Original-From: Pavel Shilovsky To: linux-cifs@vger.kernel.org, smfrench@gmail.com Subject: [PATCH] CIFS: Reset current mid to next value in sequence on send failures Date: Wed, 20 Feb 2019 15:35:53 -0800 Message-Id: <1550705753-15443-1-git-send-email-pshilov@microsoft.com> X-Mailer: git-send-email 2.7.4 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 When we hit failures during constructing MIDs or sending PDUs through the network, we end up not using the message IDs assigned to the packet. The next SMB packet will skip those message IDs and continue with the next one. This behavior may lead to a server not granting us credits until we use the skipped IDs. Fix this by reverting the current ID to the original value if any errors occur before we push the packet through the network stack. This patch fixes the generic/310 test from the xfs-tests. Signed-off-by: Pavel Shilovsky Reviewed-by: Ronnie Sahlberg --- fs/cifs/cifsglob.h | 15 +++++++++++++++ fs/cifs/smb2ops.c | 12 ++++++++++++ fs/cifs/smb2transport.c | 13 +++++++++++-- fs/cifs/transport.c | 6 +++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 5bf463c..10be31e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -238,6 +238,8 @@ struct smb_version_operations { int * (*get_credits_field)(struct TCP_Server_Info *, const int); unsigned int (*get_credits)(struct mid_q_entry *); __u64 (*get_next_mid)(struct TCP_Server_Info *); + void (*revert_current_mid)(struct TCP_Server_Info *server, + const unsigned int val); /* data offset from read response message */ unsigned int (*read_data_offset)(char *); /* @@ -789,6 +791,19 @@ get_next_mid(struct TCP_Server_Info *server) return cpu_to_le16(mid); } +static inline void +revert_current_mid(struct TCP_Server_Info *server, const unsigned int val) +{ + if (server->ops->revert_current_mid) + server->ops->revert_current_mid(server, val); +} + +static inline void +dec_current_mid(struct TCP_Server_Info *server) +{ + return revert_current_mid(server, 1); +} + static inline __u16 get_mid(const struct smb_hdr *smb) { diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 080929a..1243407 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -265,6 +265,14 @@ smb2_get_next_mid(struct TCP_Server_Info *server) return mid; } +static void +smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val) +{ + spin_lock(&GlobalMid_Lock); + server->CurrentMid -= val; + spin_unlock(&GlobalMid_Lock); +} + static struct mid_q_entry * smb2_find_mid(struct TCP_Server_Info *server, char *buf) { @@ -3606,6 +3614,7 @@ struct smb_version_operations smb20_operations = { .get_credits = smb2_get_credits, .wait_mtu_credits = cifs_wait_mtu_credits, .get_next_mid = smb2_get_next_mid, + .revert_current_mid = smb2_revert_current_mid, .read_data_offset = smb2_read_data_offset, .read_data_length = smb2_read_data_length, .map_error = map_smb2_to_linux_error, @@ -3702,6 +3711,7 @@ struct smb_version_operations smb21_operations = { .wait_mtu_credits = smb2_wait_mtu_credits, .adjust_credits = smb2_adjust_credits, .get_next_mid = smb2_get_next_mid, + .revert_current_mid = smb2_revert_current_mid, .read_data_offset = smb2_read_data_offset, .read_data_length = smb2_read_data_length, .map_error = map_smb2_to_linux_error, @@ -3799,6 +3809,7 @@ struct smb_version_operations smb30_operations = { .wait_mtu_credits = smb2_wait_mtu_credits, .adjust_credits = smb2_adjust_credits, .get_next_mid = smb2_get_next_mid, + .revert_current_mid = smb2_revert_current_mid, .read_data_offset = smb2_read_data_offset, .read_data_length = smb2_read_data_length, .map_error = map_smb2_to_linux_error, @@ -3905,6 +3916,7 @@ struct smb_version_operations smb311_operations = { .wait_mtu_credits = smb2_wait_mtu_credits, .adjust_credits = smb2_adjust_credits, .get_next_mid = smb2_get_next_mid, + .revert_current_mid = smb2_revert_current_mid, .read_data_offset = smb2_read_data_offset, .read_data_length = smb2_read_data_length, .map_error = map_smb2_to_linux_error, diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 7b351c6..36baf1b 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -674,13 +674,18 @@ smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) smb2_seq_num_into_buf(ses->server, shdr); rc = smb2_get_mid_entry(ses, shdr, &mid); - if (rc) + if (rc) { + dec_current_mid(ses->server); return ERR_PTR(rc); + } + rc = smb2_sign_rqst(rqst, ses->server); if (rc) { + dec_current_mid(ses->server); cifs_delete_mid(mid); return ERR_PTR(rc); } + return mid; } @@ -690,16 +695,20 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) int rc; struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; + unsigned int num = le16_to_cpu(shdr->CreditCharge); struct mid_q_entry *mid; smb2_seq_num_into_buf(server, shdr); mid = smb2_mid_entry_alloc(shdr, server); - if (mid == NULL) + if (mid == NULL) { + revert_current_mid(server, num); return ERR_PTR(-ENOMEM); + } rc = smb2_sign_rqst(rqst, server); if (rc) { + revert_current_mid(server, num); DeleteMidQEntry(mid); return ERR_PTR(rc); } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index d4f1224f..849a45d 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -695,6 +695,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, cifs_in_send_dec(server); if (rc < 0) { + revert_current_mid(server, credits.value); server->sequence_number -= 2; cifs_delete_mid(mid); } @@ -988,6 +989,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, for (i = 0; i < num_rqst; i++) { midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]); if (IS_ERR(midQ[i])) { + revert_current_mid(ses->server, i); for (j = 0; j < i; j++) cifs_delete_mid(midQ[j]); mutex_unlock(&ses->server->srv_mutex); @@ -1017,8 +1019,10 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, for (i = 0; i < num_rqst; i++) cifs_save_when_sent(midQ[i]); - if (rc < 0) + if (rc < 0) { + revert_current_mid(ses->server, num_rqst); ses->server->sequence_number -= 2; + } mutex_unlock(&ses->server->srv_mutex);