mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
cifs: do all necessary checks for credits within or before locking
[ Upstream commit326a8d04f1] 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:d7d7a66aac("cifs: avoid use of global locks for high contention data") Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
4fe07d55a5
commit
9fb981a86a
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user