From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01CDF8F57 for ; Sun, 16 Jul 2023 20:46:59 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4943C433C7; Sun, 16 Jul 2023 20:46:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1689540419; bh=eS+UyUz8srakJcfiKtXumDf28wuRPZ1CmhV5tbGHFBc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d4tKP0TY0Ns83WK9Ars+OleOJopNfLPufzfJhYwqm58xIEew3wr0zxJB6dyszDn+G SDlTJwnF7r4s4F7dMm1QTXZf7kcNsAUPNHMYOVmgBzudCcrZoQgFvpZ3QKd2R6EV7x nsDeL8YqLSw/r7w1Zq80tx25ACwB0tPkGHFfM+Cw= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Shyam Prasad N , Steve French , Sasha Levin Subject: [PATCH 6.1 357/591] cifs: do all necessary checks for credits within or before locking Date: Sun, 16 Jul 2023 21:48:16 +0200 Message-ID: <20230716194933.149496967@linuxfoundation.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230716194923.861634455@linuxfoundation.org> References: <20230716194923.861634455@linuxfoundation.org> User-Agent: quilt/0.67 Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Shyam Prasad N [ Upstream commit 326a8d04f147e2bf393f6f9cdb74126ee6900607 ] All the server credits and in-flight info is protected by req_lock. Once the req_lock is held, and we've determined that we have enough credits to continue, this lock cannot be dropped till we've made the changes to credits and in-flight count. However, we used to drop the lock in order to avoid deadlock with the recent srv_lock. This could cause the checks already made to be invalidated. Fixed it by moving the server status check to before locking req_lock. Fixes: d7d7a66aacd6 ("cifs: avoid use of global locks for high contention data") Signed-off-by: Shyam Prasad N Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/smb/client/smb2ops.c | 19 ++++++++++--------- fs/smb/client/transport.c | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index d512440d35b6f..e6a191a7499e8 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -208,6 +208,16 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, spin_lock(&server->req_lock); while (1) { + spin_unlock(&server->req_lock); + + spin_lock(&server->srv_lock); + if (server->tcpStatus == CifsExiting) { + spin_unlock(&server->srv_lock); + return -ENOENT; + } + spin_unlock(&server->srv_lock); + + spin_lock(&server->req_lock); if (server->credits <= 0) { spin_unlock(&server->req_lock); cifs_num_waiters_inc(server); @@ -218,15 +228,6 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, return rc; spin_lock(&server->req_lock); } else { - spin_unlock(&server->req_lock); - spin_lock(&server->srv_lock); - if (server->tcpStatus == CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - - spin_lock(&server->req_lock); scredits = server->credits; /* can deadlock with reopen */ if (scredits <= 8) { diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index c961b90f92b9f..e03ffcf7e201c 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -549,6 +549,16 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, } while (1) { + spin_unlock(&server->req_lock); + + spin_lock(&server->srv_lock); + if (server->tcpStatus == CifsExiting) { + spin_unlock(&server->srv_lock); + return -ENOENT; + } + spin_unlock(&server->srv_lock); + + spin_lock(&server->req_lock); if (*credits < num_credits) { scredits = *credits; spin_unlock(&server->req_lock); @@ -574,15 +584,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, return -ERESTARTSYS; spin_lock(&server->req_lock); } else { - spin_unlock(&server->req_lock); - - spin_lock(&server->srv_lock); - if (server->tcpStatus == CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - /* * For normal commands, reserve the last MAX_COMPOUND * credits to compound requests. @@ -596,7 +597,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, * for servers that are slow to hand out credits on * new sessions. */ - spin_lock(&server->req_lock); if (!optype && num_credits == 1 && server->in_flight > 2 * MAX_COMPOUND && *credits <= MAX_COMPOUND) { -- 2.39.2