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