cifs: do all necessary checks for credits within or before locking
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>
This commit is contained in:
parent
33f736187d
commit
326a8d04f1
|
@ -215,6 +215,16 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||||
|
|
||||||
spin_lock(&server->req_lock);
|
spin_lock(&server->req_lock);
|
||||||
while (1) {
|
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) {
|
if (server->credits <= 0) {
|
||||||
spin_unlock(&server->req_lock);
|
spin_unlock(&server->req_lock);
|
||||||
cifs_num_waiters_inc(server);
|
cifs_num_waiters_inc(server);
|
||||||
|
@ -225,15 +235,6 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
|
||||||
return rc;
|
return rc;
|
||||||
spin_lock(&server->req_lock);
|
spin_lock(&server->req_lock);
|
||||||
} else {
|
} 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;
|
scredits = server->credits;
|
||||||
/* can deadlock with reopen */
|
/* can deadlock with reopen */
|
||||||
if (scredits <= 8) {
|
if (scredits <= 8) {
|
||||||
|
|
|
@ -522,6 +522,16 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
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) {
|
if (*credits < num_credits) {
|
||||||
scredits = *credits;
|
scredits = *credits;
|
||||||
spin_unlock(&server->req_lock);
|
spin_unlock(&server->req_lock);
|
||||||
|
@ -547,15 +557,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
spin_lock(&server->req_lock);
|
spin_lock(&server->req_lock);
|
||||||
} else {
|
} 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
|
* For normal commands, reserve the last MAX_COMPOUND
|
||||||
* credits to compound requests.
|
* credits to compound requests.
|
||||||
|
@ -569,7 +570,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
|
||||||
* for servers that are slow to hand out credits on
|
* for servers that are slow to hand out credits on
|
||||||
* new sessions.
|
* new sessions.
|
||||||
*/
|
*/
|
||||||
spin_lock(&server->req_lock);
|
|
||||||
if (!optype && num_credits == 1 &&
|
if (!optype && num_credits == 1 &&
|
||||||
server->in_flight > 2 * MAX_COMPOUND &&
|
server->in_flight > 2 * MAX_COMPOUND &&
|
||||||
*credits <= MAX_COMPOUND) {
|
*credits <= MAX_COMPOUND) {
|
||||||
|
|
Loading…
Reference in New Issue