cifs: connect individual channel servers to primary channel server

Today, we don't have any way to get the smb session for any
of the secondary channels. Introducing a pointer to the primary
server from server struct of any secondary channel. The value will
be NULL for the server of the primary channel. This will enable us
to get the smb session for any channel.

This will be needed for some of the changes that I'm planning
to make soon.

Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by Shyam Prasad N and committed by Steve French 0f2b305a 724244cd

+36 -14
+2 -1
fs/cifs/cifs_debug.c
··· 271 271 c = 0; 272 272 spin_lock(&cifs_tcp_ses_lock); 273 273 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 274 - if (server->is_channel) 274 + /* channel info will be printed as a part of sessions below */ 275 + if (CIFS_SERVER_IS_CHAN(server)) 275 276 continue; 276 277 277 278 c++;
+9 -1
fs/cifs/cifsglob.h
··· 690 690 */ 691 691 int nr_targets; 692 692 bool noblockcnt; /* use non-blocking connect() */ 693 - bool is_channel; /* if a session channel */ 693 + 694 + /* 695 + * If this is a session channel, 696 + * primary_server holds the ref-counted 697 + * pointer to primary channel connection for the session. 698 + */ 699 + #define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server) 700 + struct TCP_Server_Info *primary_server; 701 + 694 702 #ifdef CONFIG_CIFS_SWN_UPCALL 695 703 bool use_swn_dstaddr; 696 704 struct sockaddr_storage swn_dstaddr;
+3 -2
fs/cifs/cifsproto.h
··· 269 269 270 270 extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, 271 271 const char *path); 272 - 273 - extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); 272 + extern struct TCP_Server_Info * 273 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 274 + struct TCP_Server_Info *primary_server); 274 275 extern void cifs_put_tcp_session(struct TCP_Server_Info *server, 275 276 int from_reconnect); 276 277 extern void cifs_put_tcon(struct cifs_tcon *tcon);
+20 -4
fs/cifs/connect.c
··· 173 173 struct cifs_tcon *tcon; 174 174 struct mid_q_entry *mid, *nmid; 175 175 struct list_head retry_list; 176 + struct TCP_Server_Info *pserver; 176 177 177 178 server->maxBuf = 0; 178 179 server->max_read = 0; ··· 185 184 * are not used until reconnected. 186 185 */ 187 186 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); 187 + 188 + /* If server is a channel, select the primary channel */ 189 + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; 190 + 188 191 spin_lock(&cifs_tcp_ses_lock); 189 - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 192 + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { 190 193 ses->need_reconnect = true; 191 194 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) 192 195 tcon->need_reconnect = true; ··· 1343 1338 * Skip ses channels since they're only handled in lower layers 1344 1339 * (e.g. cifs_send_recv). 1345 1340 */ 1346 - if (server->is_channel || !match_server(server, ctx)) 1341 + if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) 1347 1342 continue; 1348 1343 1349 1344 ++server->srv_count; ··· 1373 1368 1374 1369 list_del_init(&server->tcp_ses_list); 1375 1370 spin_unlock(&cifs_tcp_ses_lock); 1371 + 1372 + /* For secondary channels, we pick up ref-count on the primary server */ 1373 + if (CIFS_SERVER_IS_CHAN(server)) 1374 + cifs_put_tcp_session(server->primary_server, from_reconnect); 1376 1375 1377 1376 cancel_delayed_work_sync(&server->echo); 1378 1377 cancel_delayed_work_sync(&server->resolve); ··· 1410 1401 } 1411 1402 1412 1403 struct TCP_Server_Info * 1413 - cifs_get_tcp_session(struct smb3_fs_context *ctx) 1404 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 1405 + struct TCP_Server_Info *primary_server) 1414 1406 { 1415 1407 struct TCP_Server_Info *tcp_ses = NULL; 1416 1408 int rc; ··· 1448 1438 tcp_ses->in_flight = 0; 1449 1439 tcp_ses->max_in_flight = 0; 1450 1440 tcp_ses->credits = 1; 1441 + if (primary_server) { 1442 + ++primary_server->srv_count; 1443 + tcp_ses->primary_server = primary_server; 1444 + } 1451 1445 init_waitqueue_head(&tcp_ses->response_q); 1452 1446 init_waitqueue_head(&tcp_ses->request_q); 1453 1447 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); ··· 1573 1559 1574 1560 out_err: 1575 1561 if (tcp_ses) { 1562 + if (CIFS_SERVER_IS_CHAN(tcp_ses)) 1563 + cifs_put_tcp_session(tcp_ses->primary_server, false); 1576 1564 kfree(tcp_ses->hostname); 1577 1565 if (tcp_ses->ssocket) 1578 1566 sock_release(tcp_ses->ssocket); ··· 2976 2960 xid = get_xid(); 2977 2961 2978 2962 /* get a reference to a tcp session */ 2979 - server = cifs_get_tcp_session(ctx); 2963 + server = cifs_get_tcp_session(ctx, NULL); 2980 2964 if (IS_ERR(server)) { 2981 2965 rc = PTR_ERR(server); 2982 2966 server = NULL;
+1 -5
fs/cifs/sess.c
··· 258 258 SMB2_CLIENT_GUID_SIZE); 259 259 ctx.use_client_guid = true; 260 260 261 - chan_server = cifs_get_tcp_session(&ctx); 261 + chan_server = cifs_get_tcp_session(&ctx, ses->server); 262 262 263 263 mutex_lock(&ses->session_mutex); 264 264 spin_lock(&ses->chan_lock); ··· 271 271 goto out; 272 272 } 273 273 spin_unlock(&ses->chan_lock); 274 - 275 - spin_lock(&cifs_tcp_ses_lock); 276 - chan->server->is_channel = true; 277 - spin_unlock(&cifs_tcp_ses_lock); 278 274 279 275 /* 280 276 * We need to allocate the server crypto now as we will need
+1 -1
fs/cifs/smb2pdu.c
··· 257 257 /* 258 258 * If we are reconnecting an extra channel, bind 259 259 */ 260 - if (server->is_channel) { 260 + if (CIFS_SERVER_IS_CHAN(server)) { 261 261 ses->binding = true; 262 262 ses->binding_chan = cifs_ses_find_chan(ses, server); 263 263 }