Skip to content

Commit 183eea2

Browse files
sprasad-microsoftsmfrench
authored andcommitted
cifs: reconnect only the connection and not smb session where possible
With the new per-channel bitmask for reconnect, we have an option to reconnect the tcp session associated with the channel without reconnecting the smb session. i.e. if there are still channels to operate on, we can continue to use the smb session and tcon. However, there are cases where it makes sense to reconnect the smb session even when there are active channels underneath. For example for SMB session expiry. With this patch, we'll have an option to do either, and use the correct option for specific cases. Signed-off-by: Shyam Prasad N <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 2e0fa29 commit 183eea2

File tree

5 files changed

+52
-35
lines changed

5 files changed

+52
-35
lines changed

fs/cifs/cifsglob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,8 @@ struct cifs_ses {
973973
((1UL << (ses)->chan_count) - 1)
974974
#define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \
975975
((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses))
976+
#define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \
977+
((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses))
976978
#define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \
977979
test_bit((index), &(ses)->chans_need_reconnect)
978980

fs/cifs/cifsproto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
131131
struct smb_hdr *in_buf ,
132132
struct smb_hdr *out_buf,
133133
int *bytes_returned);
134-
extern int cifs_reconnect(struct TCP_Server_Info *server);
134+
extern int cifs_reconnect(struct TCP_Server_Info *server,
135+
bool mark_smb_session);
135136
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
136137
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
137138
extern bool backup_cred(struct cifs_sb_info *);

fs/cifs/cifssmb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
14391439

14401440
if (server->ops->is_session_expired &&
14411441
server->ops->is_session_expired(buf)) {
1442-
cifs_reconnect(server);
1442+
cifs_reconnect(server, true);
14431443
return -1;
14441444
}
14451445

fs/cifs/connect.c

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,11 @@ static void cifs_resolve_server(struct work_struct *work)
166166
* Mark all sessions and tcons for reconnect.
167167
*
168168
* @server needs to be previously set to CifsNeedReconnect.
169+
*
169170
*/
170-
static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server)
171+
static void
172+
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
173+
bool mark_smb_session)
171174
{
172175
unsigned int num_sessions = 0;
173176
struct cifs_ses *ses;
@@ -193,13 +196,16 @@ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server
193196
spin_lock(&cifs_tcp_ses_lock);
194197
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
195198
spin_lock(&ses->chan_lock);
196-
if (cifs_chan_needs_reconnect(ses, server))
199+
if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server))
197200
goto next_session;
198201

199-
cifs_chan_set_need_reconnect(ses, server);
202+
if (mark_smb_session)
203+
CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
204+
else
205+
cifs_chan_set_need_reconnect(ses, server);
200206

201207
/* If all channels need reconnect, then tcon needs reconnect */
202-
if (!CIFS_ALL_CHANS_NEED_RECONNECT(ses))
208+
if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses))
203209
goto next_session;
204210

205211
num_sessions++;
@@ -271,16 +277,16 @@ static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server
271277

272278
static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets)
273279
{
274-
spin_lock(&GlobalMid_Lock);
280+
spin_lock(&cifs_tcp_ses_lock);
275281
server->nr_targets = num_targets;
276282
if (server->tcpStatus == CifsExiting) {
277283
/* the demux thread will exit normally next time through the loop */
278-
spin_unlock(&GlobalMid_Lock);
284+
spin_unlock(&cifs_tcp_ses_lock);
279285
wake_up(&server->response_q);
280286
return false;
281287
}
282288
server->tcpStatus = CifsNeedReconnect;
283-
spin_unlock(&GlobalMid_Lock);
289+
spin_unlock(&cifs_tcp_ses_lock);
284290
return true;
285291
}
286292

@@ -291,15 +297,21 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num
291297
* mark all smb sessions as reconnecting for tcp session
292298
* reconnect tcp session
293299
* wake up waiters on reconnection? - (not needed currently)
300+
*
301+
* if mark_smb_session is passed as true, unconditionally mark
302+
* the smb session (and tcon) for reconnect as well. This value
303+
* doesn't really matter for non-multichannel scenario.
304+
*
294305
*/
295-
static int __cifs_reconnect(struct TCP_Server_Info *server)
306+
static int __cifs_reconnect(struct TCP_Server_Info *server,
307+
bool mark_smb_session)
296308
{
297309
int rc = 0;
298310

299311
if (!cifs_tcp_ses_needs_reconnect(server, 1))
300312
return 0;
301313

302-
cifs_mark_tcp_ses_conns_for_reconnect(server);
314+
cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
303315

304316
do {
305317
try_to_freeze();
@@ -322,10 +334,10 @@ static int __cifs_reconnect(struct TCP_Server_Info *server)
322334
} else {
323335
atomic_inc(&tcpSesReconnectCount);
324336
set_credits(server, 1);
325-
spin_lock(&GlobalMid_Lock);
337+
spin_lock(&cifs_tcp_ses_lock);
326338
if (server->tcpStatus != CifsExiting)
327339
server->tcpStatus = CifsNeedNegotiate;
328-
spin_unlock(&GlobalMid_Lock);
340+
spin_unlock(&cifs_tcp_ses_lock);
329341
cifs_swn_reset_server_dstaddr(server);
330342
mutex_unlock(&server->srv_mutex);
331343
}
@@ -394,7 +406,9 @@ static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_
394406
return rc;
395407
}
396408

397-
static int reconnect_dfs_server(struct TCP_Server_Info *server)
409+
static int
410+
reconnect_dfs_server(struct TCP_Server_Info *server,
411+
bool mark_smb_session)
398412
{
399413
int rc = 0;
400414
const char *refpath = server->current_fullpath + 1;
@@ -418,7 +432,7 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
418432
if (!cifs_tcp_ses_needs_reconnect(server, num_targets))
419433
return 0;
420434

421-
cifs_mark_tcp_ses_conns_for_reconnect(server);
435+
cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
422436

423437
do {
424438
try_to_freeze();
@@ -439,10 +453,10 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
439453
*/
440454
atomic_inc(&tcpSesReconnectCount);
441455
set_credits(server, 1);
442-
spin_lock(&GlobalMid_Lock);
456+
spin_lock(&cifs_tcp_ses_lock);
443457
if (server->tcpStatus != CifsExiting)
444458
server->tcpStatus = CifsNeedNegotiate;
445-
spin_unlock(&GlobalMid_Lock);
459+
spin_unlock(&cifs_tcp_ses_lock);
446460
cifs_swn_reset_server_dstaddr(server);
447461
mutex_unlock(&server->srv_mutex);
448462
} while (server->tcpStatus == CifsNeedReconnect);
@@ -460,22 +474,22 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
460474
return rc;
461475
}
462476

463-
int cifs_reconnect(struct TCP_Server_Info *server)
477+
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
464478
{
465479
/* If tcp session is not an dfs connection, then reconnect to last target server */
466480
spin_lock(&cifs_tcp_ses_lock);
467481
if (!server->is_dfs_conn || !server->origin_fullpath || !server->leaf_fullpath) {
468482
spin_unlock(&cifs_tcp_ses_lock);
469-
return __cifs_reconnect(server);
483+
return __cifs_reconnect(server, mark_smb_session);
470484
}
471485
spin_unlock(&cifs_tcp_ses_lock);
472486

473-
return reconnect_dfs_server(server);
487+
return reconnect_dfs_server(server, mark_smb_session);
474488
}
475489
#else
476-
int cifs_reconnect(struct TCP_Server_Info *server)
490+
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
477491
{
478-
return __cifs_reconnect(server);
492+
return __cifs_reconnect(server, mark_smb_session);
479493
}
480494
#endif
481495

@@ -563,7 +577,7 @@ server_unresponsive(struct TCP_Server_Info *server)
563577
time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
564578
cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
565579
(3 * server->echo_interval) / HZ);
566-
cifs_reconnect(server);
580+
cifs_reconnect(server, false);
567581
return true;
568582
}
569583

@@ -599,7 +613,7 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
599613

600614
/* reconnect if no credits and no requests in flight */
601615
if (zero_credits(server)) {
602-
cifs_reconnect(server);
616+
cifs_reconnect(server, false);
603617
return -ECONNABORTED;
604618
}
605619

@@ -614,7 +628,7 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
614628
return -ESHUTDOWN;
615629

616630
if (server->tcpStatus == CifsNeedReconnect) {
617-
cifs_reconnect(server);
631+
cifs_reconnect(server, false);
618632
return -ECONNABORTED;
619633
}
620634

@@ -633,7 +647,7 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
633647

634648
if (length <= 0) {
635649
cifs_dbg(FYI, "Received no data or error: %d\n", length);
636-
cifs_reconnect(server);
650+
cifs_reconnect(server, false);
637651
return -ECONNABORTED;
638652
}
639653
}
@@ -712,11 +726,11 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
712726
* initialize frame).
713727
*/
714728
cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
715-
cifs_reconnect(server);
729+
cifs_reconnect(server, true);
716730
break;
717731
default:
718732
cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
719-
cifs_reconnect(server);
733+
cifs_reconnect(server, true);
720734
}
721735

722736
return false;
@@ -889,7 +903,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
889903
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
890904
server->vals->header_preamble_size) {
891905
cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
892-
cifs_reconnect(server);
906+
cifs_reconnect(server, true);
893907
return -ECONNABORTED;
894908
}
895909

@@ -936,7 +950,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
936950

937951
if (server->ops->is_session_expired &&
938952
server->ops->is_session_expired(buf)) {
939-
cifs_reconnect(server);
953+
cifs_reconnect(server, true);
940954
return -1;
941955
}
942956

@@ -1040,7 +1054,7 @@ cifs_demultiplex_thread(void *p)
10401054
server->vals->header_preamble_size) {
10411055
cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
10421056
server->pdu_size);
1043-
cifs_reconnect(server);
1057+
cifs_reconnect(server, true);
10441058
continue;
10451059
}
10461060

@@ -1092,7 +1106,7 @@ cifs_demultiplex_thread(void *p)
10921106
server->ops->is_status_io_timeout(buf)) {
10931107
num_io_timeout++;
10941108
if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
1095-
cifs_reconnect(server);
1109+
cifs_reconnect(server, false);
10961110
num_io_timeout = 0;
10971111
continue;
10981112
}

fs/cifs/smb2ops.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4810,7 +4810,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
48104810
if (server->ops->is_session_expired &&
48114811
server->ops->is_session_expired(buf)) {
48124812
if (!is_offloaded)
4813-
cifs_reconnect(server);
4813+
cifs_reconnect(server, true);
48144814
return -1;
48154815
}
48164816

@@ -5223,13 +5223,13 @@ smb3_receive_transform(struct TCP_Server_Info *server,
52235223
sizeof(struct smb2_hdr)) {
52245224
cifs_server_dbg(VFS, "Transform message is too small (%u)\n",
52255225
pdu_length);
5226-
cifs_reconnect(server);
5226+
cifs_reconnect(server, true);
52275227
return -ECONNABORTED;
52285228
}
52295229

52305230
if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
52315231
cifs_server_dbg(VFS, "Transform message is broken\n");
5232-
cifs_reconnect(server);
5232+
cifs_reconnect(server, true);
52335233
return -ECONNABORTED;
52345234
}
52355235

0 commit comments

Comments
 (0)