Skip to content

Commit 326a8d0

Browse files
sprasad-microsoftsmfrench
authored andcommitted
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: d7d7a66 ("cifs: avoid use of global locks for high contention data") Signed-off-by: Shyam Prasad N <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 33f7361 commit 326a8d0

File tree

2 files changed

+20
-19
lines changed

2 files changed

+20
-19
lines changed

fs/smb/client/smb2ops.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
215215

216216
spin_lock(&server->req_lock);
217217
while (1) {
218+
spin_unlock(&server->req_lock);
219+
220+
spin_lock(&server->srv_lock);
221+
if (server->tcpStatus == CifsExiting) {
222+
spin_unlock(&server->srv_lock);
223+
return -ENOENT;
224+
}
225+
spin_unlock(&server->srv_lock);
226+
227+
spin_lock(&server->req_lock);
218228
if (server->credits <= 0) {
219229
spin_unlock(&server->req_lock);
220230
cifs_num_waiters_inc(server);
@@ -225,15 +235,6 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
225235
return rc;
226236
spin_lock(&server->req_lock);
227237
} else {
228-
spin_unlock(&server->req_lock);
229-
spin_lock(&server->srv_lock);
230-
if (server->tcpStatus == CifsExiting) {
231-
spin_unlock(&server->srv_lock);
232-
return -ENOENT;
233-
}
234-
spin_unlock(&server->srv_lock);
235-
236-
spin_lock(&server->req_lock);
237238
scredits = server->credits;
238239
/* can deadlock with reopen */
239240
if (scredits <= 8) {

fs/smb/client/transport.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,16 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
522522
}
523523

524524
while (1) {
525+
spin_unlock(&server->req_lock);
526+
527+
spin_lock(&server->srv_lock);
528+
if (server->tcpStatus == CifsExiting) {
529+
spin_unlock(&server->srv_lock);
530+
return -ENOENT;
531+
}
532+
spin_unlock(&server->srv_lock);
533+
534+
spin_lock(&server->req_lock);
525535
if (*credits < num_credits) {
526536
scredits = *credits;
527537
spin_unlock(&server->req_lock);
@@ -547,15 +557,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
547557
return -ERESTARTSYS;
548558
spin_lock(&server->req_lock);
549559
} else {
550-
spin_unlock(&server->req_lock);
551-
552-
spin_lock(&server->srv_lock);
553-
if (server->tcpStatus == CifsExiting) {
554-
spin_unlock(&server->srv_lock);
555-
return -ENOENT;
556-
}
557-
spin_unlock(&server->srv_lock);
558-
559560
/*
560561
* For normal commands, reserve the last MAX_COMPOUND
561562
* credits to compound requests.
@@ -569,7 +570,6 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
569570
* for servers that are slow to hand out credits on
570571
* new sessions.
571572
*/
572-
spin_lock(&server->req_lock);
573573
if (!optype && num_credits == 1 &&
574574
server->in_flight > 2 * MAX_COMPOUND &&
575575
*credits <= MAX_COMPOUND) {

0 commit comments

Comments
 (0)