Skip to content

Commit 9bd4279

Browse files
Wang Zhaolongsmfrench
authored andcommitted
smb: client: add mid_counter_lock to protect the mid counter counter
This is step 2/4 of a patch series to fix mid_q_entry memory leaks caused by race conditions in callback execution. Add a dedicated mid_counter_lock to protect current_mid counter, separating it from mid_queue_lock which protects pending_mid_q operations. This reduces lock contention and prepares for finer- grained locking in subsequent patches. Changes: - Add TCP_Server_Info->mid_counter_lock spinlock - Rename CurrentMid to current_mid for consistency - Use mid_counter_lock to protect current_mid access - Update locking documentation in cifsglob.h This separation allows mid allocation to proceed without blocking queue operations, improving performance under heavy load. Signed-off-by: Wang Zhaolong <[email protected]> Acked-by: Enzo Matsumiya <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent f3ba7c9 commit 9bd4279

File tree

5 files changed

+38
-35
lines changed

5 files changed

+38
-35
lines changed

fs/smb/client/cifsglob.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ struct TCP_Server_Info {
733733
wait_queue_head_t response_q;
734734
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
735735
spinlock_t mid_queue_lock; /* protect mid queue */
736+
spinlock_t mid_counter_lock;
736737
struct list_head pending_mid_q;
737738
bool noblocksnd; /* use blocking sendmsg */
738739
bool noautotune; /* do not autotune send buf sizes */
@@ -770,7 +771,7 @@ struct TCP_Server_Info {
770771
/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
771772
unsigned int capabilities; /* selective disabling of caps by smb sess */
772773
int timeAdj; /* Adjust for difference in server time zone in sec */
773-
__u64 CurrentMid; /* multiplex id - rotating counter, protected by GlobalMid_Lock */
774+
__u64 current_mid; /* multiplex id - rotating counter, protected by mid_counter_lock */
774775
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
775776
/* 16th byte of RFC1001 workstation name is always null */
776777
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
@@ -2008,8 +2009,8 @@ require use of the stronger protocol */
20082009
* GlobalTotalActiveXid
20092010
* TCP_Server_Info->srv_lock (anything in struct not protected by another lock and can change)
20102011
* TCP_Server_Info->mid_queue_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_session
2011-
* ->CurrentMid
20122012
* (any changes in mid_q_entry fields)
2013+
* TCP_Server_Info->mid_counter_lock TCP_Server_Info->current_mid cifs_get_tcp_session
20132014
* TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_session
20142015
* ->credits
20152016
* ->echo_credits

fs/smb/client/connect.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num
358358
}
359359

360360
cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
361-
trace_smb3_reconnect(server->CurrentMid, server->conn_id,
361+
trace_smb3_reconnect(server->current_mid, server->conn_id,
362362
server->hostname);
363363
server->tcpStatus = CifsNeedReconnect;
364364

@@ -1242,7 +1242,7 @@ smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
12421242
spin_unlock(&server->req_lock);
12431243
wake_up(&server->request_q);
12441244

1245-
trace_smb3_hdr_credits(server->CurrentMid,
1245+
trace_smb3_hdr_credits(server->current_mid,
12461246
server->conn_id, server->hostname, scredits,
12471247
le16_to_cpu(shdr->CreditRequest), in_flight);
12481248
cifs_server_dbg(FYI, "%s: added %u credits total=%d\n",
@@ -1823,6 +1823,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
18231823
spin_lock_init(&tcp_ses->req_lock);
18241824
spin_lock_init(&tcp_ses->srv_lock);
18251825
spin_lock_init(&tcp_ses->mid_queue_lock);
1826+
spin_lock_init(&tcp_ses->mid_counter_lock);
18261827
INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
18271828
INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
18281829
INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);

fs/smb/client/smb1ops.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,9 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
169169
__u16 last_mid, cur_mid;
170170
bool collision, reconnect = false;
171171

172-
spin_lock(&server->mid_queue_lock);
173-
172+
spin_lock(&server->mid_counter_lock);
174173
/* mid is 16 bit only for CIFS/SMB */
175-
cur_mid = (__u16)((server->CurrentMid) & 0xffff);
174+
cur_mid = (__u16)((server->current_mid) & 0xffff);
176175
/* we do not want to loop forever */
177176
last_mid = cur_mid;
178177
cur_mid++;
@@ -198,6 +197,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
198197
cur_mid++;
199198

200199
num_mids = 0;
200+
spin_lock(&server->mid_queue_lock);
201201
list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
202202
++num_mids;
203203
if (mid_entry->mid == cur_mid &&
@@ -207,6 +207,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
207207
break;
208208
}
209209
}
210+
spin_unlock(&server->mid_queue_lock);
210211

211212
/*
212213
* if we have more than 32k mids in the list, then something
@@ -223,12 +224,12 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
223224

224225
if (!collision) {
225226
mid = (__u64)cur_mid;
226-
server->CurrentMid = mid;
227+
server->current_mid = mid;
227228
break;
228229
}
229230
cur_mid++;
230231
}
231-
spin_unlock(&server->mid_queue_lock);
232+
spin_unlock(&server->mid_counter_lock);
232233

233234
if (reconnect) {
234235
cifs_signal_cifsd_for_reconnect(server, false);

fs/smb/client/smb2ops.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ smb2_add_credits(struct TCP_Server_Info *server,
9191
if (*val > 65000) {
9292
*val = 65000; /* Don't get near 64K credits, avoid srv bugs */
9393
pr_warn_once("server overflowed SMB3 credits\n");
94-
trace_smb3_overflow_credits(server->CurrentMid,
94+
trace_smb3_overflow_credits(server->current_mid,
9595
server->conn_id, server->hostname, *val,
9696
add, server->in_flight);
9797
}
@@ -136,15 +136,15 @@ smb2_add_credits(struct TCP_Server_Info *server,
136136
wake_up(&server->request_q);
137137

138138
if (reconnect_detected) {
139-
trace_smb3_reconnect_detected(server->CurrentMid,
139+
trace_smb3_reconnect_detected(server->current_mid,
140140
server->conn_id, server->hostname, scredits, add, in_flight);
141141

142142
cifs_dbg(FYI, "trying to put %d credits from the old server instance %d\n",
143143
add, instance);
144144
}
145145

146146
if (reconnect_with_invalid_credits) {
147-
trace_smb3_reconnect_with_invalid_credits(server->CurrentMid,
147+
trace_smb3_reconnect_with_invalid_credits(server->current_mid,
148148
server->conn_id, server->hostname, scredits, add, in_flight);
149149
cifs_dbg(FYI, "Negotiate operation when server credits is non-zero. Optype: %d, server credits: %d, credits added: %d\n",
150150
optype, scredits, add);
@@ -176,7 +176,7 @@ smb2_add_credits(struct TCP_Server_Info *server,
176176
break;
177177
}
178178

179-
trace_smb3_add_credits(server->CurrentMid,
179+
trace_smb3_add_credits(server->current_mid,
180180
server->conn_id, server->hostname, scredits, add, in_flight);
181181
cifs_dbg(FYI, "%s: added %u credits total=%d\n", __func__, add, scredits);
182182
}
@@ -203,7 +203,7 @@ smb2_set_credits(struct TCP_Server_Info *server, const int val)
203203
in_flight = server->in_flight;
204204
spin_unlock(&server->req_lock);
205205

206-
trace_smb3_set_credits(server->CurrentMid,
206+
trace_smb3_set_credits(server->current_mid,
207207
server->conn_id, server->hostname, scredits, val, in_flight);
208208
cifs_dbg(FYI, "%s: set %u credits\n", __func__, val);
209209

@@ -288,7 +288,7 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
288288
in_flight = server->in_flight;
289289
spin_unlock(&server->req_lock);
290290

291-
trace_smb3_wait_credits(server->CurrentMid,
291+
trace_smb3_wait_credits(server->current_mid,
292292
server->conn_id, server->hostname, scredits, -(credits->value), in_flight);
293293
cifs_dbg(FYI, "%s: removed %u credits total=%d\n",
294294
__func__, credits->value, scredits);
@@ -316,7 +316,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
316316
server->credits, server->in_flight,
317317
new_val - credits->value,
318318
cifs_trace_rw_credits_no_adjust_up);
319-
trace_smb3_too_many_credits(server->CurrentMid,
319+
trace_smb3_too_many_credits(server->current_mid,
320320
server->conn_id, server->hostname, 0, credits->value - new_val, 0);
321321
cifs_server_dbg(VFS, "R=%x[%x] request has less credits (%d) than required (%d)",
322322
subreq->rreq->debug_id, subreq->subreq.debug_index,
@@ -338,7 +338,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
338338
server->credits, server->in_flight,
339339
new_val - credits->value,
340340
cifs_trace_rw_credits_old_session);
341-
trace_smb3_reconnect_detected(server->CurrentMid,
341+
trace_smb3_reconnect_detected(server->current_mid,
342342
server->conn_id, server->hostname, scredits,
343343
credits->value - new_val, in_flight);
344344
cifs_server_dbg(VFS, "R=%x[%x] trying to return %d credits to old session\n",
@@ -358,7 +358,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
358358
spin_unlock(&server->req_lock);
359359
wake_up(&server->request_q);
360360

361-
trace_smb3_adj_credits(server->CurrentMid,
361+
trace_smb3_adj_credits(server->current_mid,
362362
server->conn_id, server->hostname, scredits,
363363
credits->value - new_val, in_flight);
364364
cifs_dbg(FYI, "%s: adjust added %u credits total=%d\n",
@@ -374,19 +374,19 @@ smb2_get_next_mid(struct TCP_Server_Info *server)
374374
{
375375
__u64 mid;
376376
/* for SMB2 we need the current value */
377-
spin_lock(&server->mid_queue_lock);
378-
mid = server->CurrentMid++;
379-
spin_unlock(&server->mid_queue_lock);
377+
spin_lock(&server->mid_counter_lock);
378+
mid = server->current_mid++;
379+
spin_unlock(&server->mid_counter_lock);
380380
return mid;
381381
}
382382

383383
static void
384384
smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
385385
{
386-
spin_lock(&server->mid_queue_lock);
387-
if (server->CurrentMid >= val)
388-
server->CurrentMid -= val;
389-
spin_unlock(&server->mid_queue_lock);
386+
spin_lock(&server->mid_counter_lock);
387+
if (server->current_mid >= val)
388+
server->current_mid -= val;
389+
spin_unlock(&server->mid_counter_lock);
390390
}
391391

392392
static struct mid_q_entry *
@@ -460,9 +460,9 @@ smb2_negotiate(const unsigned int xid,
460460
{
461461
int rc;
462462

463-
spin_lock(&server->mid_queue_lock);
464-
server->CurrentMid = 0;
465-
spin_unlock(&server->mid_queue_lock);
463+
spin_lock(&server->mid_counter_lock);
464+
server->current_mid = 0;
465+
spin_unlock(&server->mid_counter_lock);
466466
rc = SMB2_negotiate(xid, ses, server);
467467
return rc;
468468
}
@@ -2498,7 +2498,7 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
24982498
spin_unlock(&server->req_lock);
24992499
wake_up(&server->request_q);
25002500

2501-
trace_smb3_pend_credits(server->CurrentMid,
2501+
trace_smb3_pend_credits(server->current_mid,
25022502
server->conn_id, server->hostname, scredits,
25032503
le16_to_cpu(shdr->CreditRequest), in_flight);
25042504
cifs_dbg(FYI, "%s: status pending add %u credits total=%d\n",

fs/smb/client/transport.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
397397
* socket so the server throws away the partial SMB
398398
*/
399399
cifs_signal_cifsd_for_reconnect(server, false);
400-
trace_smb3_partial_send_reconnect(server->CurrentMid,
400+
trace_smb3_partial_send_reconnect(server->current_mid,
401401
server->conn_id, server->hostname);
402402
}
403403
smbd_done:
@@ -509,7 +509,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
509509
in_flight = server->in_flight;
510510
spin_unlock(&server->req_lock);
511511

512-
trace_smb3_nblk_credits(server->CurrentMid,
512+
trace_smb3_nblk_credits(server->current_mid,
513513
server->conn_id, server->hostname, scredits, -1, in_flight);
514514
cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
515515
__func__, 1, scredits);
@@ -542,7 +542,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
542542
in_flight = server->in_flight;
543543
spin_unlock(&server->req_lock);
544544

545-
trace_smb3_credit_timeout(server->CurrentMid,
545+
trace_smb3_credit_timeout(server->current_mid,
546546
server->conn_id, server->hostname, scredits,
547547
num_credits, in_flight);
548548
cifs_server_dbg(VFS, "wait timed out after %d ms\n",
@@ -585,7 +585,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
585585
spin_unlock(&server->req_lock);
586586

587587
trace_smb3_credit_timeout(
588-
server->CurrentMid,
588+
server->current_mid,
589589
server->conn_id, server->hostname,
590590
scredits, num_credits, in_flight);
591591
cifs_server_dbg(VFS, "wait timed out after %d ms\n",
@@ -615,7 +615,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
615615
in_flight = server->in_flight;
616616
spin_unlock(&server->req_lock);
617617

618-
trace_smb3_waitff_credits(server->CurrentMid,
618+
trace_smb3_waitff_credits(server->current_mid,
619619
server->conn_id, server->hostname, scredits,
620620
-(num_credits), in_flight);
621621
cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
@@ -666,7 +666,7 @@ wait_for_compound_request(struct TCP_Server_Info *server, int num,
666666
*/
667667
if (server->in_flight == 0) {
668668
spin_unlock(&server->req_lock);
669-
trace_smb3_insufficient_credits(server->CurrentMid,
669+
trace_smb3_insufficient_credits(server->current_mid,
670670
server->conn_id, server->hostname, scredits,
671671
num, in_flight);
672672
cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=%d\n",

0 commit comments

Comments
 (0)