Lines Matching +full:tcon +full:- +full:channel
1 // SPDX-License-Identifier: LGPL-2.1
31 #include <keys/user-type.h>
71 * This should be called with server->srv_mutex held.
78 if (!server->hostname) in reconn_set_ipaddr_from_hostname()
79 return -EINVAL; in reconn_set_ipaddr_from_hostname()
82 if (server->hostname[0] == '\0') in reconn_set_ipaddr_from_hostname()
85 spin_lock(&server->srv_lock); in reconn_set_ipaddr_from_hostname()
86 ss = server->dstaddr; in reconn_set_ipaddr_from_hostname()
87 spin_unlock(&server->srv_lock); in reconn_set_ipaddr_from_hostname()
89 rc = dns_resolve_name(server->dns_dom, server->hostname, in reconn_set_ipaddr_from_hostname()
90 strlen(server->hostname), in reconn_set_ipaddr_from_hostname()
93 spin_lock(&server->srv_lock); in reconn_set_ipaddr_from_hostname()
94 memcpy(&server->dstaddr, &ss, sizeof(server->dstaddr)); in reconn_set_ipaddr_from_hostname()
95 spin_unlock(&server->srv_lock); in reconn_set_ipaddr_from_hostname()
104 struct cifs_tcon *tcon = container_of(work, in smb2_query_server_interfaces() local
107 struct TCP_Server_Info *server = tcon->ses->server; in smb2_query_server_interfaces()
112 if (!server->ops->query_server_interfaces) in smb2_query_server_interfaces()
116 rc = server->ops->query_server_interfaces(xid, tcon, false); in smb2_query_server_interfaces()
120 if (rc == -EOPNOTSUPP) in smb2_query_server_interfaces()
127 queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, in smb2_query_server_interfaces()
148 /* If server is a channel, select the primary channel */ in cifs_signal_cifsd_for_reconnect()
149 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; in cifs_signal_cifsd_for_reconnect()
151 /* if we need to signal just this channel */ in cifs_signal_cifsd_for_reconnect()
153 spin_lock(&server->srv_lock); in cifs_signal_cifsd_for_reconnect()
154 if (server->tcpStatus != CifsExiting) in cifs_signal_cifsd_for_reconnect()
155 server->tcpStatus = CifsNeedReconnect; in cifs_signal_cifsd_for_reconnect()
156 spin_unlock(&server->srv_lock); in cifs_signal_cifsd_for_reconnect()
161 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { in cifs_signal_cifsd_for_reconnect()
164 spin_lock(&ses->chan_lock); in cifs_signal_cifsd_for_reconnect()
165 for (i = 0; i < ses->chan_count; i++) { in cifs_signal_cifsd_for_reconnect()
166 if (!ses->chans[i].server) in cifs_signal_cifsd_for_reconnect()
169 spin_lock(&ses->chans[i].server->srv_lock); in cifs_signal_cifsd_for_reconnect()
170 if (ses->chans[i].server->tcpStatus != CifsExiting) in cifs_signal_cifsd_for_reconnect()
171 ses->chans[i].server->tcpStatus = CifsNeedReconnect; in cifs_signal_cifsd_for_reconnect()
172 spin_unlock(&ses->chans[i].server->srv_lock); in cifs_signal_cifsd_for_reconnect()
174 spin_unlock(&ses->chan_lock); in cifs_signal_cifsd_for_reconnect()
195 struct cifs_tcon *tcon; in cifs_mark_tcp_ses_conns_for_reconnect() local
203 /* If server is a channel, select the primary channel */ in cifs_mark_tcp_ses_conns_for_reconnect()
204 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; in cifs_mark_tcp_ses_conns_for_reconnect()
214 if (server->terminate) { in cifs_mark_tcp_ses_conns_for_reconnect()
220 list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { in cifs_mark_tcp_ses_conns_for_reconnect()
221 spin_lock(&ses->ses_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
222 if (ses->ses_status == SES_EXITING) { in cifs_mark_tcp_ses_conns_for_reconnect()
223 spin_unlock(&ses->ses_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
226 spin_unlock(&ses->ses_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
228 spin_lock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
231 spin_unlock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
236 spin_unlock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
238 spin_lock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
242 spin_unlock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
251 cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", in cifs_mark_tcp_ses_conns_for_reconnect()
252 __func__, ses->chans_need_reconnect); in cifs_mark_tcp_ses_conns_for_reconnect()
254 /* If all channels need reconnect, then tcon needs reconnect */ in cifs_mark_tcp_ses_conns_for_reconnect()
256 spin_unlock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
259 spin_unlock(&ses->chan_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
261 spin_lock(&ses->ses_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
262 ses->ses_status = SES_NEED_RECON; in cifs_mark_tcp_ses_conns_for_reconnect()
263 spin_unlock(&ses->ses_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
265 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { in cifs_mark_tcp_ses_conns_for_reconnect()
266 tcon->need_reconnect = true; in cifs_mark_tcp_ses_conns_for_reconnect()
267 spin_lock(&tcon->tc_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
268 tcon->status = TID_NEED_RECON; in cifs_mark_tcp_ses_conns_for_reconnect()
269 spin_unlock(&tcon->tc_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
271 cancel_delayed_work(&tcon->query_interfaces); in cifs_mark_tcp_ses_conns_for_reconnect()
273 if (ses->tcon_ipc) { in cifs_mark_tcp_ses_conns_for_reconnect()
274 ses->tcon_ipc->need_reconnect = true; in cifs_mark_tcp_ses_conns_for_reconnect()
275 spin_lock(&ses->tcon_ipc->tc_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
276 ses->tcon_ipc->status = TID_NEED_RECON; in cifs_mark_tcp_ses_conns_for_reconnect()
277 spin_unlock(&ses->tcon_ipc->tc_lock); in cifs_mark_tcp_ses_conns_for_reconnect()
289 server->maxBuf = 0; in cifs_abort_connection()
290 server->max_read = 0; in cifs_abort_connection()
295 if (server->ssocket) { in cifs_abort_connection()
296 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, in cifs_abort_connection()
297 server->ssocket->flags); in cifs_abort_connection()
298 kernel_sock_shutdown(server->ssocket, SHUT_WR); in cifs_abort_connection()
299 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", server->ssocket->state, in cifs_abort_connection()
300 server->ssocket->flags); in cifs_abort_connection()
301 sock_release(server->ssocket); in cifs_abort_connection()
302 server->ssocket = NULL; in cifs_abort_connection()
304 server->sequence_number = 0; in cifs_abort_connection()
305 server->session_estab = false; in cifs_abort_connection()
306 kfree_sensitive(server->session_key.response); in cifs_abort_connection()
307 server->session_key.response = NULL; in cifs_abort_connection()
308 server->session_key.len = 0; in cifs_abort_connection()
309 server->lstrp = jiffies; in cifs_abort_connection()
314 spin_lock(&server->mid_lock); in cifs_abort_connection()
315 list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { in cifs_abort_connection()
316 kref_get(&mid->refcount); in cifs_abort_connection()
317 if (mid->mid_state == MID_REQUEST_SUBMITTED) in cifs_abort_connection()
318 mid->mid_state = MID_RETRY_NEEDED; in cifs_abort_connection()
319 list_move(&mid->qhead, &retry_list); in cifs_abort_connection()
320 mid->mid_flags |= MID_DELETED; in cifs_abort_connection()
322 spin_unlock(&server->mid_lock); in cifs_abort_connection()
327 list_del_init(&mid->qhead); in cifs_abort_connection()
328 mid->callback(mid); in cifs_abort_connection()
341 spin_lock(&server->srv_lock); in cifs_tcp_ses_needs_reconnect()
342 server->nr_targets = num_targets; in cifs_tcp_ses_needs_reconnect()
343 if (server->tcpStatus == CifsExiting) { in cifs_tcp_ses_needs_reconnect()
345 spin_unlock(&server->srv_lock); in cifs_tcp_ses_needs_reconnect()
346 wake_up(&server->response_q); in cifs_tcp_ses_needs_reconnect()
351 trace_smb3_reconnect(server->CurrentMid, server->conn_id, in cifs_tcp_ses_needs_reconnect()
352 server->hostname); in cifs_tcp_ses_needs_reconnect()
353 server->tcpStatus = CifsNeedReconnect; in cifs_tcp_ses_needs_reconnect()
355 spin_unlock(&server->srv_lock); in cifs_tcp_ses_needs_reconnect()
365 * wake up waiters on reconnection? - (not needed currently)
368 * the smb session (and tcon) for reconnect as well. This value
369 * doesn't really matter for non-multichannel scenario.
389 /* resolve the hostname again to make sure that IP address is up-to-date */ in __cifs_reconnect()
405 spin_lock(&server->srv_lock); in __cifs_reconnect()
406 if (server->tcpStatus != CifsExiting) in __cifs_reconnect()
407 server->tcpStatus = CifsNeedNegotiate; in __cifs_reconnect()
408 spin_unlock(&server->srv_lock); in __cifs_reconnect()
411 mod_delayed_work(cifsiod_wq, &server->reconnect, 0); in __cifs_reconnect()
413 } while (server->tcpStatus == CifsNeedReconnect); in __cifs_reconnect()
415 spin_lock(&server->srv_lock); in __cifs_reconnect()
416 if (server->tcpStatus == CifsNeedNegotiate) in __cifs_reconnect()
417 mod_delayed_work(cifsiod_wq, &server->echo, 0); in __cifs_reconnect()
418 spin_unlock(&server->srv_lock); in __cifs_reconnect()
420 wake_up(&server->response_q); in __cifs_reconnect()
432 if (server->hostname != target) { in __reconnect_target_locked()
435 spin_lock(&server->srv_lock); in __reconnect_target_locked()
436 kfree(server->hostname); in __reconnect_target_locked()
437 server->hostname = hostname; in __reconnect_target_locked()
438 spin_unlock(&server->srv_lock); in __reconnect_target_locked()
443 server->hostname); in __reconnect_target_locked()
446 /* resolve the hostname again to make sure that IP address is up-to-date. */ in __reconnect_target_locked()
471 return __reconnect_target_locked(server, server->hostname); in reconnect_target_locked()
477 spin_lock(&server->srv_lock); in reconnect_target_locked()
478 if (server->tcpStatus != CifsNeedReconnect) { in reconnect_target_locked()
479 spin_unlock(&server->srv_lock); in reconnect_target_locked()
480 return -ECONNRESET; in reconnect_target_locked()
482 spin_unlock(&server->srv_lock); in reconnect_target_locked()
495 const char *ref_path = server->leaf_fullpath + 1; in reconnect_dfs_server()
504 * targets (server->nr_targets). It's also possible that the cached referral was cleared in reconnect_dfs_server()
539 * process waiting for reconnect will know it needs to re-establish session and tcon in reconnect_dfs_server()
544 spin_lock(&server->srv_lock); in reconnect_dfs_server()
545 if (server->tcpStatus != CifsExiting) in reconnect_dfs_server()
546 server->tcpStatus = CifsNeedNegotiate; in reconnect_dfs_server()
547 spin_unlock(&server->srv_lock); in reconnect_dfs_server()
550 mod_delayed_work(cifsiod_wq, &server->reconnect, 0); in reconnect_dfs_server()
551 } while (server->tcpStatus == CifsNeedReconnect); in reconnect_dfs_server()
557 spin_lock(&server->srv_lock); in reconnect_dfs_server()
558 if (server->tcpStatus == CifsNeedNegotiate) in reconnect_dfs_server()
559 mod_delayed_work(cifsiod_wq, &server->echo, 0); in reconnect_dfs_server()
560 spin_unlock(&server->srv_lock); in reconnect_dfs_server()
562 wake_up(&server->response_q); in reconnect_dfs_server()
568 if (!server->leaf_fullpath) in cifs_reconnect()
591 if (server->tcpStatus == CifsNeedReconnect || in cifs_echo_request()
592 server->tcpStatus == CifsExiting || in cifs_echo_request()
593 server->tcpStatus == CifsNew || in cifs_echo_request()
594 (server->ops->can_echo && !server->ops->can_echo(server)) || in cifs_echo_request()
595 time_before(jiffies, server->lstrp + server->echo_interval - HZ)) in cifs_echo_request()
598 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; in cifs_echo_request()
605 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval); in cifs_echo_request()
611 if (!server->bigbuf) { in allocate_buffers()
612 server->bigbuf = (char *)cifs_buf_get(); in allocate_buffers()
613 if (!server->bigbuf) { in allocate_buffers()
619 } else if (server->large_buf) { in allocate_buffers()
621 memset(server->bigbuf, 0, HEADER_SIZE(server)); in allocate_buffers()
624 if (!server->smallbuf) { in allocate_buffers()
625 server->smallbuf = (char *)cifs_small_buf_get(); in allocate_buffers()
626 if (!server->smallbuf) { in allocate_buffers()
635 memset(server->smallbuf, 0, HEADER_SIZE(server)); in allocate_buffers()
650 spin_lock(&server->srv_lock); in server_unresponsive()
651 if (server->tcpStatus == CifsInNegotiate && in server_unresponsive()
652 time_after(jiffies, server->lstrp + 20 * HZ)) { in server_unresponsive()
653 spin_unlock(&server->srv_lock); in server_unresponsive()
668 if ((server->tcpStatus == CifsGood || in server_unresponsive()
669 server->tcpStatus == CifsNeedNegotiate) && in server_unresponsive()
670 (!server->ops->can_echo || server->ops->can_echo(server)) && in server_unresponsive()
671 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { in server_unresponsive()
672 spin_unlock(&server->srv_lock); in server_unresponsive()
674 (3 * server->echo_interval) / HZ); in server_unresponsive()
678 spin_unlock(&server->srv_lock); in server_unresponsive()
688 spin_lock(&server->req_lock); in zero_credits()
689 val = server->credits + server->echo_credits + server->oplock_credits; in zero_credits()
690 if (server->in_flight == 0 && val == 0) { in zero_credits()
691 spin_unlock(&server->req_lock); in zero_credits()
694 spin_unlock(&server->req_lock); in zero_credits()
710 return -ECONNABORTED; in cifs_readv_from_socket()
714 return -ECONNABORTED; in cifs_readv_from_socket()
715 if (cifs_rdma_enabled(server) && server->smbd_conn) in cifs_readv_from_socket()
716 length = smbd_recv(server->smbd_conn, smb_msg); in cifs_readv_from_socket()
718 length = sock_recvmsg(server->ssocket, smb_msg, 0); in cifs_readv_from_socket()
720 spin_lock(&server->srv_lock); in cifs_readv_from_socket()
721 if (server->tcpStatus == CifsExiting) { in cifs_readv_from_socket()
722 spin_unlock(&server->srv_lock); in cifs_readv_from_socket()
723 return -ESHUTDOWN; in cifs_readv_from_socket()
726 if (server->tcpStatus == CifsNeedReconnect) { in cifs_readv_from_socket()
727 spin_unlock(&server->srv_lock); in cifs_readv_from_socket()
729 return -ECONNABORTED; in cifs_readv_from_socket()
731 spin_unlock(&server->srv_lock); in cifs_readv_from_socket()
733 if (length == -ERESTARTSYS || in cifs_readv_from_socket()
734 length == -EAGAIN || in cifs_readv_from_socket()
735 length == -EINTR) { in cifs_readv_from_socket()
749 return -ECONNABORTED; in cifs_readv_from_socket()
824 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); in is_smb_response()
839 mid->when_received = jiffies; in dequeue_mid()
841 spin_lock(&mid->server->mid_lock); in dequeue_mid()
843 mid->mid_state = MID_RESPONSE_RECEIVED; in dequeue_mid()
845 mid->mid_state = MID_RESPONSE_MALFORMED; in dequeue_mid()
850 if (mid->mid_flags & MID_DELETED) { in dequeue_mid()
851 spin_unlock(&mid->server->mid_lock); in dequeue_mid()
854 list_del_init(&mid->qhead); in dequeue_mid()
855 mid->mid_flags |= MID_DELETED; in dequeue_mid()
856 spin_unlock(&mid->server->mid_lock); in dequeue_mid()
871 return le16_to_cpu(shdr->CreditRequest); in smb2_get_credits_from_hdr()
878 if (server->ops->check_trans2 && in handle_mid()
879 server->ops->check_trans2(mid, server, buf, malformed)) in handle_mid()
881 mid->credits_received = smb2_get_credits_from_hdr(buf, server); in handle_mid()
882 mid->resp_buf = buf; in handle_mid()
883 mid->large_buf = server->large_buf; in handle_mid()
884 /* Was previous buf put in mpx struct for multi-rsp? */ in handle_mid()
885 if (!mid->multiRsp) { in handle_mid()
887 if (server->large_buf) in handle_mid()
888 server->bigbuf = NULL; in handle_mid()
890 server->smallbuf = NULL; in handle_mid()
898 bool srv_sign_required = server->sec_mode & server->vals->signing_required; in cifs_enable_signing()
899 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; in cifs_enable_signing()
921 return -EOPNOTSUPP; in cifs_enable_signing()
923 server->sign = true; in cifs_enable_signing()
930 return -EOPNOTSUPP; in cifs_enable_signing()
932 server->sign = true; in cifs_enable_signing()
935 if (cifs_rdma_enabled(server) && server->sign) in cifs_enable_signing()
947 spin_lock(&server->srv_lock); in clean_demultiplex_info()
948 list_del_init(&server->tcp_ses_list); in clean_demultiplex_info()
949 spin_unlock(&server->srv_lock); in clean_demultiplex_info()
951 cancel_delayed_work_sync(&server->echo); in clean_demultiplex_info()
953 spin_lock(&server->srv_lock); in clean_demultiplex_info()
954 server->tcpStatus = CifsExiting; in clean_demultiplex_info()
955 spin_unlock(&server->srv_lock); in clean_demultiplex_info()
956 wake_up_all(&server->response_q); in clean_demultiplex_info()
959 spin_lock(&server->req_lock); in clean_demultiplex_info()
960 if (server->credits <= 0) in clean_demultiplex_info()
961 server->credits = 1; in clean_demultiplex_info()
962 spin_unlock(&server->req_lock); in clean_demultiplex_info()
967 * same server - they now will see the session is in exit state and get in clean_demultiplex_info()
970 wake_up_all(&server->request_q); in clean_demultiplex_info()
975 if (server->ssocket) { in clean_demultiplex_info()
976 sock_release(server->ssocket); in clean_demultiplex_info()
977 server->ssocket = NULL; in clean_demultiplex_info()
980 if (!list_empty(&server->pending_mid_q)) { in clean_demultiplex_info()
985 spin_lock(&server->mid_lock); in clean_demultiplex_info()
986 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { in clean_demultiplex_info()
988 cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); in clean_demultiplex_info()
989 kref_get(&mid_entry->refcount); in clean_demultiplex_info()
990 mid_entry->mid_state = MID_SHUTDOWN; in clean_demultiplex_info()
991 list_move(&mid_entry->qhead, &dispose_list); in clean_demultiplex_info()
992 mid_entry->mid_flags |= MID_DELETED; in clean_demultiplex_info()
994 spin_unlock(&server->mid_lock); in clean_demultiplex_info()
999 cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid); in clean_demultiplex_info()
1000 list_del_init(&mid_entry->qhead); in clean_demultiplex_info()
1001 mid_entry->callback(mid_entry); in clean_demultiplex_info()
1008 if (!list_empty(&server->pending_mid_q)) { in clean_demultiplex_info()
1026 kfree(server->leaf_fullpath); in clean_demultiplex_info()
1027 kfree(server->hostname); in clean_demultiplex_info()
1039 char *buf = server->smallbuf; in standard_receive3()
1040 unsigned int pdu_length = server->pdu_size; in standard_receive3()
1043 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - in standard_receive3()
1047 return -ECONNABORTED; in standard_receive3()
1051 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { in standard_receive3()
1052 server->large_buf = true; in standard_receive3()
1053 memcpy(server->bigbuf, buf, server->total_read); in standard_receive3()
1054 buf = server->bigbuf; in standard_receive3()
1058 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, in standard_receive3()
1059 pdu_length - MID_HEADER_SIZE(server)); in standard_receive3()
1063 server->total_read += length; in standard_receive3()
1065 dump_smb(buf, server->total_read); in standard_receive3()
1073 char *buf = server->large_buf ? server->bigbuf : server->smallbuf; in cifs_handle_standard()
1084 rc = server->ops->check_message(buf, server->total_read, server); in cifs_handle_standard()
1087 min_t(unsigned int, server->total_read, 48)); in cifs_handle_standard()
1089 if (server->ops->is_session_expired && in cifs_handle_standard()
1090 server->ops->is_session_expired(buf)) { in cifs_handle_standard()
1092 return -1; in cifs_handle_standard()
1095 if (server->ops->is_status_pending && in cifs_handle_standard()
1096 server->ops->is_status_pending(buf, server)) in cifs_handle_standard()
1097 return -1; in cifs_handle_standard()
1118 if (shdr->CreditRequest) { in smb2_add_credits_from_hdr()
1119 spin_lock(&server->req_lock); in smb2_add_credits_from_hdr()
1120 server->credits += le16_to_cpu(shdr->CreditRequest); in smb2_add_credits_from_hdr()
1121 scredits = server->credits; in smb2_add_credits_from_hdr()
1122 in_flight = server->in_flight; in smb2_add_credits_from_hdr()
1123 spin_unlock(&server->req_lock); in smb2_add_credits_from_hdr()
1124 wake_up(&server->request_q); in smb2_add_credits_from_hdr()
1126 trace_smb3_hdr_credits(server->CurrentMid, in smb2_add_credits_from_hdr()
1127 server->conn_id, server->hostname, scredits, in smb2_add_credits_from_hdr()
1128 le16_to_cpu(shdr->CreditRequest), in_flight); in smb2_add_credits_from_hdr()
1130 __func__, le16_to_cpu(shdr->CreditRequest), in smb2_add_credits_from_hdr()
1159 while (server->tcpStatus != CifsExiting) { in cifs_demultiplex_thread()
1166 server->large_buf = false; in cifs_demultiplex_thread()
1167 buf = server->smallbuf; in cifs_demultiplex_thread()
1175 server->total_read = length; in cifs_demultiplex_thread()
1177 server->total_read = 0; in cifs_demultiplex_thread()
1180 * The right amount was read from socket - 4 bytes, in cifs_demultiplex_thread()
1191 server->pdu_size = pdu_length; in cifs_demultiplex_thread()
1194 if (server->pdu_size < MID_HEADER_SIZE(server)) { in cifs_demultiplex_thread()
1196 server->pdu_size); in cifs_demultiplex_thread()
1207 server->total_read += length; in cifs_demultiplex_thread()
1209 if (server->ops->next_header) { in cifs_demultiplex_thread()
1210 if (server->ops->next_header(server, buf, &next_offset)) { in cifs_demultiplex_thread()
1217 server->pdu_size = next_offset; in cifs_demultiplex_thread()
1224 if (server->ops->is_transform_hdr && in cifs_demultiplex_thread()
1225 server->ops->receive_transform && in cifs_demultiplex_thread()
1226 server->ops->is_transform_hdr(buf)) { in cifs_demultiplex_thread()
1227 length = server->ops->receive_transform(server, in cifs_demultiplex_thread()
1232 mids[0] = server->ops->find_mid(server, buf); in cifs_demultiplex_thread()
1236 if (!mids[0] || !mids[0]->receive) in cifs_demultiplex_thread()
1239 length = mids[0]->receive(server, mids[0]); in cifs_demultiplex_thread()
1249 if (server->ops->is_status_io_timeout && in cifs_demultiplex_thread()
1250 server->ops->is_status_io_timeout(buf)) { in cifs_demultiplex_thread()
1262 server->lstrp = jiffies; in cifs_demultiplex_thread()
1266 mids[i]->resp_buf_size = server->pdu_size; in cifs_demultiplex_thread()
1269 if (server->ops->is_network_name_deleted && in cifs_demultiplex_thread()
1270 server->ops->is_network_name_deleted(bufs[i], in cifs_demultiplex_thread()
1277 if (!mids[i]->multiRsp || mids[i]->multiEnd) in cifs_demultiplex_thread()
1278 mids[i]->callback(mids[i]); in cifs_demultiplex_thread()
1281 } else if (server->ops->is_oplock_break && in cifs_demultiplex_thread()
1282 server->ops->is_oplock_break(bufs[i], in cifs_demultiplex_thread()
1293 if (server->ops->dump_detail) in cifs_demultiplex_thread()
1294 server->ops->dump_detail(bufs[i], in cifs_demultiplex_thread()
1301 if (pdu_length > server->pdu_size) { in cifs_demultiplex_thread()
1304 pdu_length -= server->pdu_size; in cifs_demultiplex_thread()
1305 server->total_read = 0; in cifs_demultiplex_thread()
1306 server->large_buf = false; in cifs_demultiplex_thread()
1307 buf = server->smallbuf; in cifs_demultiplex_thread()
1317 /* buffer usually freed in free_mid - need to free it here on exit */ in cifs_demultiplex_thread()
1318 cifs_buf_release(server->bigbuf); in cifs_demultiplex_thread()
1319 if (server->smallbuf) /* no sense logging a debug message if NULL */ in cifs_demultiplex_thread()
1320 cifs_small_buf_release(server->smallbuf); in cifs_demultiplex_thread()
1322 task_to_wake = xchg(&server->tsk, NULL); in cifs_demultiplex_thread()
1325 /* if server->tsk was NULL then wait for a signal before exiting */ in cifs_demultiplex_thread()
1347 switch (srcaddr->sa_family) { in cifs_ipaddr_cmp()
1349 switch (rhs->sa_family) { in cifs_ipaddr_cmp()
1356 return -1; in cifs_ipaddr_cmp()
1359 switch (rhs->sa_family) { in cifs_ipaddr_cmp()
1361 return -1; in cifs_ipaddr_cmp()
1368 return -1; in cifs_ipaddr_cmp()
1372 switch (rhs->sa_family) { in cifs_ipaddr_cmp()
1375 return -1; in cifs_ipaddr_cmp()
1381 return -1; in cifs_ipaddr_cmp()
1385 return -1; /* don't expect to be here */ in cifs_ipaddr_cmp()
1396 switch (srcaddr->sa_family) { in cifs_match_ipaddr()
1398 return (rhs->sa_family == AF_UNSPEC); in cifs_match_ipaddr()
1403 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr); in cifs_match_ipaddr()
1409 return (ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr) in cifs_match_ipaddr()
1410 && saddr6->sin6_scope_id == vaddr6->sin6_scope_id); in cifs_match_ipaddr()
1420 * and if it fails - with 139 ports. It should be called only if address
1429 if (server->rdma) in match_port()
1432 switch (addr->sa_family) { in match_port()
1434 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; in match_port()
1435 port = ((struct sockaddr_in *) addr)->sin_port; in match_port()
1438 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port; in match_port()
1439 port = ((struct sockaddr_in6 *) addr)->sin6_port; in match_port()
1459 if (!cifs_match_ipaddr(addr, (struct sockaddr *)&server->dstaddr)) in match_server_address()
1469 * The select_sectype function should either return the ctx->sectype in match_security()
1473 if (server->ops->select_sectype(server, ctx->sectype) in match_security()
1480 * the server->sign had better be too. in match_security()
1482 if (ctx->sign && !server->sign) in match_security()
1493 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; in match_server()
1495 lockdep_assert_held(&server->srv_lock); in match_server()
1497 if (ctx->nosharesock) in match_server()
1501 if (server->nosharesock) in match_server()
1504 if (!match_super && (ctx->dfs_conn || server->dfs_conn)) in match_server()
1508 if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { in match_server()
1509 if (server->vals->protocol_id < SMB30_PROT_ID) in match_server()
1511 } else if (strcmp(ctx->vals->version_string, in match_server()
1513 if (server->vals->protocol_id < SMB21_PROT_ID) in match_server()
1515 } else if ((server->vals != ctx->vals) || (server->ops != ctx->ops)) in match_server()
1518 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) in match_server()
1521 if (!cifs_match_ipaddr((struct sockaddr *)&ctx->srcaddr, in match_server()
1522 (struct sockaddr *)&server->srcaddr)) in match_server()
1525 if (strcasecmp(server->hostname, ctx->server_hostname) || in match_server()
1533 if (server->echo_interval != ctx->echo_interval * HZ) in match_server()
1536 if (server->rdma != ctx->rdma) in match_server()
1539 if (server->ignore_signature != ctx->ignore_signature) in match_server()
1542 if (server->min_offload != ctx->min_offload) in match_server()
1545 if (server->retrans != ctx->retrans) in match_server()
1558 spin_lock(&server->srv_lock); in cifs_find_tcp_session()
1565 spin_unlock(&server->srv_lock); in cifs_find_tcp_session()
1568 spin_unlock(&server->srv_lock); in cifs_find_tcp_session()
1570 ++server->srv_count; in cifs_find_tcp_session()
1585 if (--server->srv_count > 0) { in cifs_put_tcp_session()
1591 WARN_ON(server->srv_count < 0); in cifs_put_tcp_session()
1593 list_del_init(&server->tcp_ses_list); in cifs_put_tcp_session()
1596 cancel_delayed_work_sync(&server->echo); in cifs_put_tcp_session()
1605 cancel_delayed_work(&server->reconnect); in cifs_put_tcp_session()
1607 cancel_delayed_work_sync(&server->reconnect); in cifs_put_tcp_session()
1609 /* For secondary channels, we pick up ref-count on the primary server */ in cifs_put_tcp_session()
1611 cifs_put_tcp_session(server->primary_server, from_reconnect); in cifs_put_tcp_session()
1613 spin_lock(&server->srv_lock); in cifs_put_tcp_session()
1614 server->tcpStatus = CifsExiting; in cifs_put_tcp_session()
1615 spin_unlock(&server->srv_lock); in cifs_put_tcp_session()
1619 kfree_sensitive(server->session_key.response); in cifs_put_tcp_session()
1620 server->session_key.response = NULL; in cifs_put_tcp_session()
1621 server->session_key.len = 0; in cifs_put_tcp_session()
1623 task = xchg(&server->tsk, NULL); in cifs_put_tcp_session()
1635 cifs_dbg(FYI, "UNC: %s\n", ctx->UNC); in cifs_get_tcp_session()
1644 rc = -ENOMEM; in cifs_get_tcp_session()
1648 tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL); in cifs_get_tcp_session()
1649 if (!tcp_ses->hostname) { in cifs_get_tcp_session()
1650 rc = -ENOMEM; in cifs_get_tcp_session()
1654 if (ctx->leaf_fullpath) { in cifs_get_tcp_session()
1655 tcp_ses->leaf_fullpath = kstrdup(ctx->leaf_fullpath, GFP_KERNEL); in cifs_get_tcp_session()
1656 if (!tcp_ses->leaf_fullpath) { in cifs_get_tcp_session()
1657 rc = -ENOMEM; in cifs_get_tcp_session()
1661 if (ctx->dns_dom) in cifs_get_tcp_session()
1662 strscpy(tcp_ses->dns_dom, ctx->dns_dom); in cifs_get_tcp_session()
1664 if (ctx->nosharesock) in cifs_get_tcp_session()
1665 tcp_ses->nosharesock = true; in cifs_get_tcp_session()
1666 tcp_ses->dfs_conn = ctx->dfs_conn; in cifs_get_tcp_session()
1668 tcp_ses->ops = ctx->ops; in cifs_get_tcp_session()
1669 tcp_ses->vals = ctx->vals; in cifs_get_tcp_session()
1670 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); in cifs_get_tcp_session()
1672 tcp_ses->sign = ctx->sign; in cifs_get_tcp_session()
1673 tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId); in cifs_get_tcp_session()
1674 tcp_ses->noblockcnt = ctx->rootfs; in cifs_get_tcp_session()
1675 tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs; in cifs_get_tcp_session()
1676 tcp_ses->noautotune = ctx->noautotune; in cifs_get_tcp_session()
1677 tcp_ses->tcp_nodelay = ctx->sockopt_tcp_nodelay; in cifs_get_tcp_session()
1678 tcp_ses->rdma = ctx->rdma; in cifs_get_tcp_session()
1679 tcp_ses->in_flight = 0; in cifs_get_tcp_session()
1680 tcp_ses->max_in_flight = 0; in cifs_get_tcp_session()
1681 tcp_ses->credits = 1; in cifs_get_tcp_session()
1684 ++primary_server->srv_count; in cifs_get_tcp_session()
1686 tcp_ses->primary_server = primary_server; in cifs_get_tcp_session()
1688 init_waitqueue_head(&tcp_ses->response_q); in cifs_get_tcp_session()
1689 init_waitqueue_head(&tcp_ses->request_q); in cifs_get_tcp_session()
1690 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); in cifs_get_tcp_session()
1691 mutex_init(&tcp_ses->_srv_mutex); in cifs_get_tcp_session()
1692 memcpy(tcp_ses->workstation_RFC1001_name, in cifs_get_tcp_session()
1693 ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); in cifs_get_tcp_session()
1694 memcpy(tcp_ses->server_RFC1001_name, in cifs_get_tcp_session()
1695 ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); in cifs_get_tcp_session()
1696 tcp_ses->session_estab = false; in cifs_get_tcp_session()
1697 tcp_ses->sequence_number = 0; in cifs_get_tcp_session()
1698 tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */ in cifs_get_tcp_session()
1699 tcp_ses->reconnect_instance = 1; in cifs_get_tcp_session()
1700 tcp_ses->lstrp = jiffies; in cifs_get_tcp_session()
1701 tcp_ses->compression.requested = ctx->compress; in cifs_get_tcp_session()
1702 spin_lock_init(&tcp_ses->req_lock); in cifs_get_tcp_session()
1703 spin_lock_init(&tcp_ses->srv_lock); in cifs_get_tcp_session()
1704 spin_lock_init(&tcp_ses->mid_lock); in cifs_get_tcp_session()
1705 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); in cifs_get_tcp_session()
1706 INIT_LIST_HEAD(&tcp_ses->smb_ses_list); in cifs_get_tcp_session()
1707 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); in cifs_get_tcp_session()
1708 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); in cifs_get_tcp_session()
1709 mutex_init(&tcp_ses->reconnect_mutex); in cifs_get_tcp_session()
1710 memcpy(&tcp_ses->srcaddr, &ctx->srcaddr, in cifs_get_tcp_session()
1711 sizeof(tcp_ses->srcaddr)); in cifs_get_tcp_session()
1712 memcpy(&tcp_ses->dstaddr, &ctx->dstaddr, in cifs_get_tcp_session()
1713 sizeof(tcp_ses->dstaddr)); in cifs_get_tcp_session()
1714 if (ctx->use_client_guid) in cifs_get_tcp_session()
1715 memcpy(tcp_ses->client_guid, ctx->client_guid, in cifs_get_tcp_session()
1718 generate_random_uuid(tcp_ses->client_guid); in cifs_get_tcp_session()
1724 tcp_ses->tcpStatus = CifsNew; in cifs_get_tcp_session()
1725 ++tcp_ses->srv_count; in cifs_get_tcp_session()
1727 if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN && in cifs_get_tcp_session()
1728 ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX) in cifs_get_tcp_session()
1729 tcp_ses->echo_interval = ctx->echo_interval * HZ; in cifs_get_tcp_session()
1731 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; in cifs_get_tcp_session()
1732 if (tcp_ses->rdma) { in cifs_get_tcp_session()
1735 rc = -ENOENT; in cifs_get_tcp_session()
1738 tcp_ses->smbd_conn = smbd_get_connection( in cifs_get_tcp_session()
1739 tcp_ses, (struct sockaddr *)&ctx->dstaddr); in cifs_get_tcp_session()
1740 if (tcp_ses->smbd_conn) { in cifs_get_tcp_session()
1745 rc = -ENOENT; in cifs_get_tcp_session()
1760 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread, in cifs_get_tcp_session()
1762 if (IS_ERR(tcp_ses->tsk)) { in cifs_get_tcp_session()
1763 rc = PTR_ERR(tcp_ses->tsk); in cifs_get_tcp_session()
1768 tcp_ses->min_offload = ctx->min_offload; in cifs_get_tcp_session()
1769 tcp_ses->retrans = ctx->retrans; in cifs_get_tcp_session()
1775 spin_lock(&tcp_ses->srv_lock); in cifs_get_tcp_session()
1776 tcp_ses->tcpStatus = CifsNeedNegotiate; in cifs_get_tcp_session()
1777 spin_unlock(&tcp_ses->srv_lock); in cifs_get_tcp_session()
1779 if ((ctx->max_credits < 20) || (ctx->max_credits > 60000)) in cifs_get_tcp_session()
1780 tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE; in cifs_get_tcp_session()
1782 tcp_ses->max_credits = ctx->max_credits; in cifs_get_tcp_session()
1784 tcp_ses->nr_targets = 1; in cifs_get_tcp_session()
1785 tcp_ses->ignore_signature = ctx->ignore_signature; in cifs_get_tcp_session()
1788 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); in cifs_get_tcp_session()
1792 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); in cifs_get_tcp_session()
1804 cifs_put_tcp_session(tcp_ses->primary_server, false); in cifs_get_tcp_session()
1805 kfree(tcp_ses->hostname); in cifs_get_tcp_session()
1806 kfree(tcp_ses->leaf_fullpath); in cifs_get_tcp_session()
1807 if (tcp_ses->ssocket) in cifs_get_tcp_session()
1808 sock_release(tcp_ses->ssocket); in cifs_get_tcp_session()
1819 struct TCP_Server_Info *server = ses->server; in match_session()
1822 if (!match_super && ctx->dfs_root_ses != ses->dfs_root_ses) in match_session()
1829 if (ses->chan_max < ctx->max_channels) in match_session()
1832 ctx_sec = server->ops->select_sectype(server, ctx->sectype); in match_session()
1833 ses_sec = server->ops->select_sectype(server, ses->sectype); in match_session()
1841 if (!uid_eq(ctx->cred_uid, ses->cred_uid)) in match_session()
1848 if (ses->user_name == NULL) { in match_session()
1849 if (!ctx->nullauth) in match_session()
1855 if (strncmp(ses->user_name, in match_session()
1856 ctx->username ? ctx->username : "", in match_session()
1859 if ((ctx->username && strlen(ctx->username) != 0) && in match_session()
1860 ses->password != NULL) { in match_session()
1868 if (ses->password2 != NULL && ctx->password2 != NULL) { in match_session()
1869 if (!((strncmp(ses->password, ctx->password ? in match_session()
1870 ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0 && in match_session()
1871 strncmp(ses->password2, ctx->password2, in match_session()
1873 (strncmp(ses->password, ctx->password2, in match_session()
1875 strncmp(ses->password2, ctx->password ? in match_session()
1876 ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0))) in match_session()
1879 } else if ((ses->password2 == NULL && ctx->password2 != NULL) || in match_session()
1880 (ses->password2 != NULL && ctx->password2 == NULL)) { in match_session()
1884 if (strncmp(ses->password, ctx->password ? in match_session()
1885 ctx->password : "", CIFS_MAX_PASSWORD_LEN)) in match_session()
1891 if (strcmp(ctx->local_nls->charset, ses->local_nls->charset)) in match_session()
1898 * cifs_setup_ipc - helper to setup the IPC tcon for the session
1904 * tcon_ipc. The IPC tcon has the same lifetime as the session.
1910 struct cifs_tcon *tcon; in cifs_setup_ipc() local
1913 struct TCP_Server_Info *server = ses->server; in cifs_setup_ipc()
1919 if (ctx->seal) { in cifs_setup_ipc()
1920 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) in cifs_setup_ipc()
1925 return -EOPNOTSUPP; in cifs_setup_ipc()
1930 tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc); in cifs_setup_ipc()
1931 if (tcon == NULL) in cifs_setup_ipc()
1932 return -ENOMEM; in cifs_setup_ipc()
1934 spin_lock(&server->srv_lock); in cifs_setup_ipc()
1935 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); in cifs_setup_ipc()
1936 spin_unlock(&server->srv_lock); in cifs_setup_ipc()
1939 tcon->ses = ses; in cifs_setup_ipc()
1940 tcon->ipc = true; in cifs_setup_ipc()
1941 tcon->seal = seal; in cifs_setup_ipc()
1942 rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls); in cifs_setup_ipc()
1947 tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail); in cifs_setup_ipc()
1951 cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid); in cifs_setup_ipc()
1953 spin_lock(&tcon->tc_lock); in cifs_setup_ipc()
1954 tcon->status = TID_GOOD; in cifs_setup_ipc()
1955 spin_unlock(&tcon->tc_lock); in cifs_setup_ipc()
1956 ses->tcon_ipc = tcon; in cifs_setup_ipc()
1967 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { in cifs_find_smb_ses()
1968 spin_lock(&ses->ses_lock); in cifs_find_smb_ses()
1969 if (ses->ses_status == SES_EXITING) { in cifs_find_smb_ses()
1970 spin_unlock(&ses->ses_lock); in cifs_find_smb_ses()
1973 spin_lock(&ses->chan_lock); in cifs_find_smb_ses()
1975 spin_unlock(&ses->chan_lock); in cifs_find_smb_ses()
1976 spin_unlock(&ses->ses_lock); in cifs_find_smb_ses()
1980 spin_unlock(&ses->chan_lock); in cifs_find_smb_ses()
1981 spin_unlock(&ses->ses_lock); in cifs_find_smb_ses()
1991 struct TCP_Server_Info *server = ses->server; in __cifs_put_smb_ses()
1992 struct cifs_tcon *tcon; in __cifs_put_smb_ses() local
1999 spin_lock(&ses->ses_lock); in __cifs_put_smb_ses()
2001 __func__, ses->Suid, ses->ses_count, ses->ses_status, in __cifs_put_smb_ses()
2002 ses->tcon_ipc ? ses->tcon_ipc->tree_name : "none"); in __cifs_put_smb_ses()
2003 if (ses->ses_status == SES_EXITING || --ses->ses_count > 0) { in __cifs_put_smb_ses()
2004 spin_unlock(&ses->ses_lock); in __cifs_put_smb_ses()
2009 WARN_ON(ses->ses_count < 0); in __cifs_put_smb_ses()
2011 spin_lock(&ses->chan_lock); in __cifs_put_smb_ses()
2013 spin_unlock(&ses->chan_lock); in __cifs_put_smb_ses()
2015 do_logoff = ses->ses_status == SES_GOOD && server->ops->logoff; in __cifs_put_smb_ses()
2016 ses->ses_status = SES_EXITING; in __cifs_put_smb_ses()
2017 tcon = ses->tcon_ipc; in __cifs_put_smb_ses()
2018 ses->tcon_ipc = NULL; in __cifs_put_smb_ses()
2019 spin_unlock(&ses->ses_lock); in __cifs_put_smb_ses()
2027 * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an in __cifs_put_smb_ses()
2030 tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc); in __cifs_put_smb_ses()
2033 rc = server->ops->logoff(xid, ses); in __cifs_put_smb_ses()
2040 list_del_init(&ses->smb_ses_list); in __cifs_put_smb_ses()
2044 for (i = 1; i < ses->chan_count; i++) { in __cifs_put_smb_ses()
2045 if (ses->chans[i].iface) { in __cifs_put_smb_ses()
2046 kref_put(&ses->chans[i].iface->refcount, release_iface); in __cifs_put_smb_ses()
2047 ses->chans[i].iface = NULL; in __cifs_put_smb_ses()
2049 cifs_put_tcp_session(ses->chans[i].server, 0); in __cifs_put_smb_ses()
2050 ses->chans[i].server = NULL; in __cifs_put_smb_ses()
2053 /* we now account for primary channel in iface->refcount */ in __cifs_put_smb_ses()
2054 if (ses->chans[0].iface) { in __cifs_put_smb_ses()
2055 kref_put(&ses->chans[0].iface->refcount, release_iface); in __cifs_put_smb_ses()
2056 ses->chans[0].server = NULL; in __cifs_put_smb_ses()
2078 struct TCP_Server_Info *server = ses->server; in cifs_set_cifscreds()
2085 return -ENOMEM; in cifs_set_cifscreds()
2088 switch (server->dstaddr.ss_family) { in cifs_set_cifscreds()
2090 sa = (struct sockaddr_in *)&server->dstaddr; in cifs_set_cifscreds()
2091 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); in cifs_set_cifscreds()
2094 sa6 = (struct sockaddr_in6 *)&server->dstaddr; in cifs_set_cifscreds()
2095 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); in cifs_set_cifscreds()
2099 server->dstaddr.ss_family); in cifs_set_cifscreds()
2100 rc = -EINVAL; in cifs_set_cifscreds()
2107 if (!ses->domainName) { in cifs_set_cifscreds()
2114 sprintf(desc, "cifs:d:%s", ses->domainName); in cifs_set_cifscreds()
2124 down_read(&key->sem); in cifs_set_cifscreds()
2127 rc = upayload ? PTR_ERR(upayload) : -EINVAL; in cifs_set_cifscreds()
2132 payload = upayload->data; in cifs_set_cifscreds()
2133 delim = strnchr(payload, upayload->datalen, ':'); in cifs_set_cifscreds()
2137 upayload->datalen); in cifs_set_cifscreds()
2138 rc = -EINVAL; in cifs_set_cifscreds()
2142 len = delim - payload; in cifs_set_cifscreds()
2146 rc = -EINVAL; in cifs_set_cifscreds()
2150 ctx->username = kstrndup(payload, len, GFP_KERNEL); in cifs_set_cifscreds()
2151 if (!ctx->username) { in cifs_set_cifscreds()
2154 rc = -ENOMEM; in cifs_set_cifscreds()
2157 cifs_dbg(FYI, "%s: username=%s\n", __func__, ctx->username); in cifs_set_cifscreds()
2159 len = key->datalen - (len + 1); in cifs_set_cifscreds()
2162 rc = -EINVAL; in cifs_set_cifscreds()
2163 kfree(ctx->username); in cifs_set_cifscreds()
2164 ctx->username = NULL; in cifs_set_cifscreds()
2170 ctx->password = kstrndup(delim, len, GFP_KERNEL); in cifs_set_cifscreds()
2171 if (!ctx->password) { in cifs_set_cifscreds()
2174 rc = -ENOMEM; in cifs_set_cifscreds()
2175 kfree(ctx->username); in cifs_set_cifscreds()
2176 ctx->username = NULL; in cifs_set_cifscreds()
2184 if (is_domain && ses->domainName) { in cifs_set_cifscreds()
2185 ctx->domainname = kstrdup(ses->domainName, GFP_KERNEL); in cifs_set_cifscreds()
2186 if (!ctx->domainname) { in cifs_set_cifscreds()
2189 rc = -ENOMEM; in cifs_set_cifscreds()
2190 kfree(ctx->username); in cifs_set_cifscreds()
2191 ctx->username = NULL; in cifs_set_cifscreds()
2192 kfree_sensitive(ctx->password); in cifs_set_cifscreds()
2193 /* no need to free ctx->password2 since not allocated in this path */ in cifs_set_cifscreds()
2194 ctx->password = NULL; in cifs_set_cifscreds()
2199 strscpy(ctx->workstation_name, ses->workstation_name, sizeof(ctx->workstation_name)); in cifs_set_cifscreds()
2202 up_read(&key->sem); in cifs_set_cifscreds()
2214 return -ENOSYS; in cifs_set_cifscreds()
2219 * cifs_get_smb_ses - get a session matching @ctx data from @server
2230 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; in cifs_get_smb_ses()
2231 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; in cifs_get_smb_ses()
2243 ses->ses_status); in cifs_get_smb_ses()
2245 spin_lock(&ses->chan_lock); in cifs_get_smb_ses()
2247 spin_unlock(&ses->chan_lock); in cifs_get_smb_ses()
2250 mutex_lock(&ses->session_mutex); in cifs_get_smb_ses()
2255 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
2256 /* problem -- put our ses reference */ in cifs_get_smb_ses()
2263 ctx->local_nls); in cifs_get_smb_ses()
2265 if (((rc == -EACCES) || (rc == -EKEYEXPIRED) || in cifs_get_smb_ses()
2266 (rc == -EKEYREVOKED)) && !retries && ses->password2) { in cifs_get_smb_ses()
2269 swap(ses->password, ses->password2); in cifs_get_smb_ses()
2272 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
2273 /* problem -- put our reference */ in cifs_get_smb_ses()
2278 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
2280 spin_lock(&ses->chan_lock); in cifs_get_smb_ses()
2282 spin_unlock(&ses->chan_lock); in cifs_get_smb_ses()
2290 rc = -ENOMEM; in cifs_get_smb_ses()
2298 ses->server = server; in cifs_get_smb_ses()
2299 if (server->dstaddr.ss_family == AF_INET6) in cifs_get_smb_ses()
2300 sprintf(ses->ip_addr, "%pI6", &addr6->sin6_addr); in cifs_get_smb_ses()
2302 sprintf(ses->ip_addr, "%pI4", &addr->sin_addr); in cifs_get_smb_ses()
2304 if (ctx->username) { in cifs_get_smb_ses()
2305 ses->user_name = kstrdup(ctx->username, GFP_KERNEL); in cifs_get_smb_ses()
2306 if (!ses->user_name) in cifs_get_smb_ses()
2310 /* ctx->password freed at unmount */ in cifs_get_smb_ses()
2311 if (ctx->password) { in cifs_get_smb_ses()
2312 ses->password = kstrdup(ctx->password, GFP_KERNEL); in cifs_get_smb_ses()
2313 if (!ses->password) in cifs_get_smb_ses()
2316 /* ctx->password freed at unmount */ in cifs_get_smb_ses()
2317 if (ctx->password2) { in cifs_get_smb_ses()
2318 ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); in cifs_get_smb_ses()
2319 if (!ses->password2) in cifs_get_smb_ses()
2322 if (ctx->domainname) { in cifs_get_smb_ses()
2323 ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL); in cifs_get_smb_ses()
2324 if (!ses->domainName) in cifs_get_smb_ses()
2327 len = strnlen(ctx->domainname, CIFS_MAX_DOMAINNAME_LEN); in cifs_get_smb_ses()
2328 if (!cifs_netbios_name(ctx->domainname, len)) { in cifs_get_smb_ses()
2329 ses->dns_dom = kstrndup(ctx->domainname, in cifs_get_smb_ses()
2331 if (!ses->dns_dom) in cifs_get_smb_ses()
2336 strscpy(ses->workstation_name, ctx->workstation_name, sizeof(ses->workstation_name)); in cifs_get_smb_ses()
2338 if (ctx->domainauto) in cifs_get_smb_ses()
2339 ses->domainAuto = ctx->domainauto; in cifs_get_smb_ses()
2340 ses->cred_uid = ctx->cred_uid; in cifs_get_smb_ses()
2341 ses->linux_uid = ctx->linux_uid; in cifs_get_smb_ses()
2343 ses->sectype = ctx->sectype; in cifs_get_smb_ses()
2344 ses->sign = ctx->sign; in cifs_get_smb_ses()
2351 switch (ctx->upcall_target) { in cifs_get_smb_ses()
2354 ses->upcall_target = UPTARGET_APP; in cifs_get_smb_ses()
2357 ses->upcall_target = UPTARGET_MOUNT; in cifs_get_smb_ses()
2361 ses->upcall_target = UPTARGET_APP; in cifs_get_smb_ses()
2365 ses->local_nls = load_nls(ctx->local_nls->charset); in cifs_get_smb_ses()
2367 /* add server as first channel */ in cifs_get_smb_ses()
2368 spin_lock(&ses->chan_lock); in cifs_get_smb_ses()
2369 ses->chans[0].server = server; in cifs_get_smb_ses()
2370 ses->chan_count = 1; in cifs_get_smb_ses()
2371 ses->chan_max = ctx->multichannel ? ctx->max_channels:1; in cifs_get_smb_ses()
2372 ses->chans_need_reconnect = 1; in cifs_get_smb_ses()
2373 spin_unlock(&ses->chan_lock); in cifs_get_smb_ses()
2376 mutex_lock(&ses->session_mutex); in cifs_get_smb_ses()
2379 rc = cifs_setup_session(xid, ses, server, ctx->local_nls); in cifs_get_smb_ses()
2380 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
2382 /* each channel uses a different signing key */ in cifs_get_smb_ses()
2383 spin_lock(&ses->chan_lock); in cifs_get_smb_ses()
2384 memcpy(ses->chans[0].signkey, ses->smb3signingkey, in cifs_get_smb_ses()
2385 sizeof(ses->smb3signingkey)); in cifs_get_smb_ses()
2386 spin_unlock(&ses->chan_lock); in cifs_get_smb_ses()
2389 if (((rc == -EACCES) || (rc == -EKEYEXPIRED) || in cifs_get_smb_ses()
2390 (rc == -EKEYREVOKED)) && !retries && ses->password2) { in cifs_get_smb_ses()
2393 swap(ses->password, ses->password2); in cifs_get_smb_ses()
2400 * success, put it on the list and add it as first channel in cifs_get_smb_ses()
2405 ses->dfs_root_ses = ctx->dfs_root_ses; in cifs_get_smb_ses()
2406 list_add(&ses->smb_ses_list, &server->smb_ses_list); in cifs_get_smb_ses()
2422 static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) in match_tcon() argument
2424 struct TCP_Server_Info *server = tcon->ses->server; in match_tcon()
2426 if (tcon->status == TID_EXITING) in match_tcon()
2429 if (tcon->origin_fullpath) { in match_tcon()
2430 if (!ctx->source || in match_tcon()
2431 !dfs_src_pathname_equal(ctx->source, in match_tcon()
2432 tcon->origin_fullpath)) in match_tcon()
2434 } else if (!server->leaf_fullpath && in match_tcon()
2435 strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE)) { in match_tcon()
2438 if (tcon->seal != ctx->seal) in match_tcon()
2440 if (tcon->snapshot_time != ctx->snapshot_time) in match_tcon()
2442 if (tcon->handle_timeout != ctx->handle_timeout) in match_tcon()
2444 if (tcon->no_lease != ctx->no_lease) in match_tcon()
2446 if (tcon->nodelete != ctx->nodelete) in match_tcon()
2448 if (tcon->posix_extensions != ctx->linux_ext) in match_tcon()
2456 struct cifs_tcon *tcon; in cifs_find_tcon() local
2459 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { in cifs_find_tcon()
2460 spin_lock(&tcon->tc_lock); in cifs_find_tcon()
2461 if (!match_tcon(tcon, ctx)) { in cifs_find_tcon()
2462 spin_unlock(&tcon->tc_lock); in cifs_find_tcon()
2465 ++tcon->tc_count; in cifs_find_tcon()
2466 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, in cifs_find_tcon()
2468 spin_unlock(&tcon->tc_lock); in cifs_find_tcon()
2470 return tcon; in cifs_find_tcon()
2477 cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) in cifs_put_tcon() argument
2484 * IPC tcon share the lifetime of their session and are in cifs_put_tcon()
2487 if (tcon == NULL || tcon->ipc) in cifs_put_tcon()
2490 ses = tcon->ses; in cifs_put_tcon()
2491 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); in cifs_put_tcon()
2493 spin_lock(&tcon->tc_lock); in cifs_put_tcon()
2494 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace); in cifs_put_tcon()
2495 if (--tcon->tc_count > 0) { in cifs_put_tcon()
2496 spin_unlock(&tcon->tc_lock); in cifs_put_tcon()
2502 WARN_ON(tcon->tc_count < 0); in cifs_put_tcon()
2504 list_del_init(&tcon->tcon_list); in cifs_put_tcon()
2505 tcon->status = TID_EXITING; in cifs_put_tcon()
2506 spin_unlock(&tcon->tc_lock); in cifs_put_tcon()
2510 cancel_delayed_work_sync(&tcon->query_interfaces); in cifs_put_tcon()
2512 cancel_delayed_work_sync(&tcon->dfs_cache_work); in cifs_put_tcon()
2513 list_replace_init(&tcon->dfs_ses_list, &ses_list); in cifs_put_tcon()
2516 if (tcon->use_witness) { in cifs_put_tcon()
2519 rc = cifs_swn_unregister(tcon); in cifs_put_tcon()
2527 if (ses->server->ops->tree_disconnect) in cifs_put_tcon()
2528 ses->server->ops->tree_disconnect(xid, tcon); in cifs_put_tcon()
2531 cifs_fscache_release_super_cookie(tcon); in cifs_put_tcon()
2532 tconInfoFree(tcon, netfs_trace_tcon_ref_free); in cifs_put_tcon()
2540 * cifs_get_tcon - get a tcon matching @ctx data from @ses
2544 * - tcon refcount is the number of mount points using the tcon.
2545 * - ses refcount is the number of tcon using the session.
2553 * a) a new tcon already allocated with refcount=1 (1 mount point) and
2554 * its session refcount incremented (1 new tcon). This +1 was
2557 * b) an existing tcon with refcount+1 (add a mount point to it) and
2558 * identical ses refcount (no new tcon). Because of (1) we need to
2564 struct cifs_tcon *tcon; in cifs_get_tcon() local
2568 tcon = cifs_find_tcon(ses, ctx); in cifs_get_tcon()
2569 if (tcon) { in cifs_get_tcon()
2571 * tcon has refcount already incremented but we need to in cifs_get_tcon()
2576 return tcon; in cifs_get_tcon()
2579 if (!ses->server->ops->tree_connect) { in cifs_get_tcon()
2580 rc = -ENOSYS; in cifs_get_tcon()
2584 if (ses->server->dialect >= SMB20_PROT_ID && in cifs_get_tcon()
2585 (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)) in cifs_get_tcon()
2586 nohandlecache = ctx->nohandlecache || !dir_cache_timeout; in cifs_get_tcon()
2589 tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new); in cifs_get_tcon()
2590 if (tcon == NULL) { in cifs_get_tcon()
2591 rc = -ENOMEM; in cifs_get_tcon()
2594 tcon->nohandlecache = nohandlecache; in cifs_get_tcon()
2596 if (ctx->snapshot_time) { in cifs_get_tcon()
2597 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2600 rc = -EOPNOTSUPP; in cifs_get_tcon()
2603 tcon->snapshot_time = ctx->snapshot_time; in cifs_get_tcon()
2606 if (ctx->handle_timeout) { in cifs_get_tcon()
2607 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2610 rc = -EOPNOTSUPP; in cifs_get_tcon()
2613 tcon->handle_timeout = ctx->handle_timeout; in cifs_get_tcon()
2616 tcon->ses = ses; in cifs_get_tcon()
2617 if (ctx->password) { in cifs_get_tcon()
2618 tcon->password = kstrdup(ctx->password, GFP_KERNEL); in cifs_get_tcon()
2619 if (!tcon->password) { in cifs_get_tcon()
2620 rc = -ENOMEM; in cifs_get_tcon()
2625 if (ctx->seal) { in cifs_get_tcon()
2626 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2629 rc = -EOPNOTSUPP; in cifs_get_tcon()
2631 } else if (tcon->ses->server->capabilities & in cifs_get_tcon()
2633 tcon->seal = true; in cifs_get_tcon()
2636 rc = -EOPNOTSUPP; in cifs_get_tcon()
2641 if (ctx->linux_ext) { in cifs_get_tcon()
2642 if (ses->server->posix_ext_supported) { in cifs_get_tcon()
2643 tcon->posix_extensions = true; in cifs_get_tcon()
2645 } else if ((ses->server->vals->protocol_id == SMB311_PROT_ID) || in cifs_get_tcon()
2646 (strcmp(ses->server->vals->version_string, in cifs_get_tcon()
2648 (strcmp(ses->server->vals->version_string, in cifs_get_tcon()
2651 rc = -EOPNOTSUPP; in cifs_get_tcon()
2653 } else if (ses->server->vals->protocol_id == SMB10_PROT_ID) in cifs_get_tcon()
2658 rc = -EOPNOTSUPP; in cifs_get_tcon()
2663 rc = -EOPNOTSUPP; in cifs_get_tcon()
2669 rc = ses->server->ops->tree_connect(xid, ses, ctx->UNC, tcon, in cifs_get_tcon()
2670 ctx->local_nls); in cifs_get_tcon()
2672 cifs_dbg(FYI, "Tcon rc = %d\n", rc); in cifs_get_tcon()
2676 tcon->use_persistent = false; in cifs_get_tcon()
2678 if (ctx->persistent) { in cifs_get_tcon()
2679 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2682 rc = -EOPNOTSUPP; in cifs_get_tcon()
2684 } else if (ses->server->capabilities & in cifs_get_tcon()
2686 tcon->use_persistent = true; in cifs_get_tcon()
2690 rc = -EOPNOTSUPP; in cifs_get_tcon()
2693 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) in cifs_get_tcon()
2694 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) in cifs_get_tcon()
2695 && (ctx->nopersistent == false)) { in cifs_get_tcon()
2697 tcon->use_persistent = true; in cifs_get_tcon()
2698 } else if (ctx->resilient) { in cifs_get_tcon()
2699 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2702 rc = -EOPNOTSUPP; in cifs_get_tcon()
2705 tcon->use_resilient = true; in cifs_get_tcon()
2708 tcon->use_witness = false; in cifs_get_tcon()
2709 if (IS_ENABLED(CONFIG_CIFS_SWN_UPCALL) && ctx->witness) { in cifs_get_tcon()
2710 if (ses->server->vals->protocol_id >= SMB30_PROT_ID) { in cifs_get_tcon()
2711 if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) { in cifs_get_tcon()
2716 tcon->use_witness = true; in cifs_get_tcon()
2718 rc = cifs_swn_register(tcon); in cifs_get_tcon()
2724 /* TODO: try to extend for non-cluster uses (eg multichannel) */ in cifs_get_tcon()
2726 rc = -EOPNOTSUPP; in cifs_get_tcon()
2731 rc = -EOPNOTSUPP; in cifs_get_tcon()
2737 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) { in cifs_get_tcon()
2738 if (ctx->cache_ro) in cifs_get_tcon()
2740 else if (ctx->cache_rw) in cifs_get_tcon()
2744 if (ctx->no_lease) { in cifs_get_tcon()
2745 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
2748 rc = -EOPNOTSUPP; in cifs_get_tcon()
2751 tcon->no_lease = ctx->no_lease; in cifs_get_tcon()
2759 tcon->retry = ctx->retry; in cifs_get_tcon()
2760 tcon->nocase = ctx->nocase; in cifs_get_tcon()
2761 tcon->broken_sparse_sup = ctx->no_sparse; in cifs_get_tcon()
2762 tcon->max_cached_dirs = ctx->max_cached_dirs; in cifs_get_tcon()
2763 tcon->nodelete = ctx->nodelete; in cifs_get_tcon()
2764 tcon->local_lease = ctx->local_lease; in cifs_get_tcon()
2765 INIT_LIST_HEAD(&tcon->pending_opens); in cifs_get_tcon()
2766 tcon->status = TID_GOOD; in cifs_get_tcon()
2768 INIT_DELAYED_WORK(&tcon->query_interfaces, in cifs_get_tcon()
2770 if (ses->server->dialect >= SMB30_PROT_ID && in cifs_get_tcon()
2771 (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { in cifs_get_tcon()
2773 queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, in cifs_get_tcon()
2777 INIT_DELAYED_WORK(&tcon->dfs_cache_work, dfs_cache_refresh); in cifs_get_tcon()
2780 list_add(&tcon->tcon_list, &ses->tcon_list); in cifs_get_tcon()
2783 return tcon; in cifs_get_tcon()
2786 tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail); in cifs_get_tcon()
2796 if (!atomic_dec_and_test(&tlink->tl_count) || in cifs_put_tlink()
2797 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) { in cifs_put_tlink()
2798 tlink->tl_time = jiffies; in cifs_put_tlink()
2811 struct cifs_sb_info *new = mnt_data->cifs_sb; in compare_mount_options()
2812 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK; in compare_mount_options()
2813 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK; in compare_mount_options()
2815 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) in compare_mount_options()
2818 if (old->mnt_cifs_serverino_autodisabled) in compare_mount_options()
2828 if (new->ctx->wsize && new->ctx->wsize < old->ctx->wsize) in compare_mount_options()
2831 if (new->ctx->rsize && new->ctx->rsize < old->ctx->rsize) in compare_mount_options()
2834 if (!uid_eq(old->ctx->linux_uid, new->ctx->linux_uid) || in compare_mount_options()
2835 !gid_eq(old->ctx->linux_gid, new->ctx->linux_gid)) in compare_mount_options()
2838 if (old->ctx->file_mode != new->ctx->file_mode || in compare_mount_options()
2839 old->ctx->dir_mode != new->ctx->dir_mode) in compare_mount_options()
2842 if (strcmp(old->local_nls->charset, new->local_nls->charset)) in compare_mount_options()
2845 if (old->ctx->acregmax != new->ctx->acregmax) in compare_mount_options()
2847 if (old->ctx->acdirmax != new->ctx->acdirmax) in compare_mount_options()
2849 if (old->ctx->closetimeo != new->ctx->closetimeo) in compare_mount_options()
2851 if (old->ctx->reparse_type != new->ctx->reparse_type) in compare_mount_options()
2853 if (old->ctx->nonativesocket != new->ctx->nonativesocket) in compare_mount_options()
2855 if (old->ctx->symlink_type != new->ctx->symlink_type) in compare_mount_options()
2862 struct cifs_tcon *tcon, in match_prepath() argument
2865 struct smb3_fs_context *ctx = mnt_data->ctx; in match_prepath()
2867 struct cifs_sb_info *new = mnt_data->cifs_sb; in match_prepath()
2868 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && in match_prepath()
2869 old->prepath; in match_prepath()
2870 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && in match_prepath()
2871 new->prepath; in match_prepath()
2873 if (tcon->origin_fullpath && in match_prepath()
2874 dfs_src_pathname_equal(tcon->origin_fullpath, ctx->source)) in match_prepath()
2877 if (old_set && new_set && !strcmp(new->prepath, old->prepath)) in match_prepath()
2893 struct cifs_tcon *tcon; in cifs_match_super() local
2901 if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) { in cifs_match_super()
2913 tcon = tlink_tcon(tlink); in cifs_match_super()
2914 ses = tcon->ses; in cifs_match_super()
2915 tcp_srv = ses->server; in cifs_match_super()
2917 ctx = mnt_data->ctx; in cifs_match_super()
2919 spin_lock(&tcp_srv->srv_lock); in cifs_match_super()
2920 spin_lock(&ses->ses_lock); in cifs_match_super()
2921 spin_lock(&ses->chan_lock); in cifs_match_super()
2922 spin_lock(&tcon->tc_lock); in cifs_match_super()
2925 !match_tcon(tcon, ctx) || in cifs_match_super()
2926 !match_prepath(sb, tcon, mnt_data)) { in cifs_match_super()
2933 spin_unlock(&tcon->tc_lock); in cifs_match_super()
2934 spin_unlock(&ses->chan_lock); in cifs_match_super()
2935 spin_unlock(&ses->ses_lock); in cifs_match_super()
2936 spin_unlock(&tcp_srv->srv_lock); in cifs_match_super()
2950 struct sock *sk = sock->sk; in cifs_reclassify_socket4()
2953 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", in cifs_reclassify_socket4()
2954 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); in cifs_reclassify_socket4()
2960 struct sock *sk = sock->sk; in cifs_reclassify_socket6()
2963 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", in cifs_reclassify_socket6()
2964 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); in cifs_reclassify_socket6()
2997 if (server->srcaddr.ss_family != AF_UNSPEC) { in bind_socket()
2999 struct socket *socket = server->ssocket; in bind_socket()
3002 (struct sockaddr *) &server->srcaddr, in bind_socket()
3003 sizeof(server->srcaddr)); in bind_socket()
3008 saddr4 = (struct sockaddr_in *)&server->srcaddr; in bind_socket()
3009 saddr6 = (struct sockaddr_in6 *)&server->srcaddr; in bind_socket()
3010 if (saddr6->sin6_family == AF_INET6) in bind_socket()
3012 &saddr6->sin6_addr, rc); in bind_socket()
3015 &saddr4->sin_addr.s_addr, rc); in bind_socket()
3027 * negprot - BB check reconnection in case where second in ip_rfc1001_connect()
3036 if (server->server_RFC1001_name[0] != 0) in ip_rfc1001_connect()
3038 server->server_RFC1001_name, in ip_rfc1001_connect()
3048 if (server->workstation_RFC1001_name[0] != 0) in ip_rfc1001_connect()
3050 server->workstation_RFC1001_name, in ip_rfc1001_connect()
3061 len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req); in ip_rfc1001_connect()
3063 smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len); in ip_rfc1001_connect()
3085 saddr = (struct sockaddr *) &server->dstaddr; in generic_ip_connect()
3087 if (server->dstaddr.ss_family == AF_INET6) { in generic_ip_connect()
3088 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr; in generic_ip_connect()
3090 sport = ipv6->sin6_port; in generic_ip_connect()
3093 cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr, in generic_ip_connect()
3096 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr; in generic_ip_connect()
3098 sport = ipv4->sin_port; in generic_ip_connect()
3101 cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr, in generic_ip_connect()
3105 if (server->ssocket) { in generic_ip_connect()
3106 socket = server->ssocket; in generic_ip_connect()
3112 IPPROTO_TCP, &server->ssocket, 1); in generic_ip_connect()
3118 sk = server->ssocket->sk; in generic_ip_connect()
3119 __netns_tracker_free(net, &sk->ns_tracker, false); in generic_ip_connect()
3120 sk->sk_net_refcnt = 1; in generic_ip_connect()
3121 get_net_track(net, &sk->ns_tracker, GFP_KERNEL); in generic_ip_connect()
3126 socket = server->ssocket; in generic_ip_connect()
3127 socket->sk->sk_allocation = GFP_NOFS; in generic_ip_connect()
3128 socket->sk->sk_use_task_frag = false; in generic_ip_connect()
3144 socket->sk->sk_rcvtimeo = 7 * HZ; in generic_ip_connect()
3145 socket->sk->sk_sndtimeo = 5 * HZ; in generic_ip_connect()
3148 if (server->noautotune) { in generic_ip_connect()
3149 if (socket->sk->sk_sndbuf < (200 * 1024)) in generic_ip_connect()
3150 socket->sk->sk_sndbuf = 200 * 1024; in generic_ip_connect()
3151 if (socket->sk->sk_rcvbuf < (140 * 1024)) in generic_ip_connect()
3152 socket->sk->sk_rcvbuf = 140 * 1024; in generic_ip_connect()
3155 if (server->tcp_nodelay) in generic_ip_connect()
3156 tcp_sock_set_nodelay(socket->sk); in generic_ip_connect()
3159 socket->sk->sk_sndbuf, in generic_ip_connect()
3160 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); in generic_ip_connect()
3163 server->noblockcnt ? O_NONBLOCK : 0); in generic_ip_connect()
3167 * reconnect failover - if possible. in generic_ip_connect()
3169 if (server->noblockcnt && rc == -EINPROGRESS) in generic_ip_connect()
3173 trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc); in generic_ip_connect()
3175 server->ssocket = NULL; in generic_ip_connect()
3178 trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr); in generic_ip_connect()
3189 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; in ip_connect()
3190 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; in ip_connect()
3192 if (server->dstaddr.ss_family == AF_INET6) in ip_connect()
3193 sport = &addr6->sin6_port; in ip_connect()
3195 sport = &addr->sin_port; in ip_connect()
3215 void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, in reset_cifs_unix_caps() argument
3223 * Perhaps we could add a backpointer to array of sb from tcon in reset_cifs_unix_caps()
3225 * sb as NFS - then we only have one backpointer to sb. in reset_cifs_unix_caps()
3229 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); in reset_cifs_unix_caps()
3231 if (ctx && ctx->no_linux_ext) { in reset_cifs_unix_caps()
3232 tcon->fsUnixInfo.Capability = 0; in reset_cifs_unix_caps()
3233 tcon->unix_ext = 0; /* Unix Extensions disabled */ in reset_cifs_unix_caps()
3237 tcon->unix_ext = 1; /* Unix Extensions supported */ in reset_cifs_unix_caps()
3239 if (!tcon->unix_ext) { in reset_cifs_unix_caps()
3244 if (!CIFSSMBQFSUnixInfo(xid, tcon)) { in reset_cifs_unix_caps()
3245 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); in reset_cifs_unix_caps()
3270 cifs_dbg(VFS, "per-share encryption not supported yet\n"); in reset_cifs_unix_caps()
3273 if (ctx && ctx->no_psx_acl) in reset_cifs_unix_caps()
3278 cifs_sb->mnt_cifs_flags |= in reset_cifs_unix_caps()
3282 if (ctx && ctx->posix_paths == 0) in reset_cifs_unix_caps()
3287 cifs_sb->mnt_cifs_flags |= in reset_cifs_unix_caps()
3312 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { in reset_cifs_unix_caps()
3325 struct smb3_fs_context *ctx = cifs_sb->ctx; in cifs_setup_cifs_sb()
3327 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); in cifs_setup_cifs_sb()
3329 spin_lock_init(&cifs_sb->tlink_tree_lock); in cifs_setup_cifs_sb()
3330 cifs_sb->tlink_tree = RB_ROOT; in cifs_setup_cifs_sb()
3333 ctx->file_mode, ctx->dir_mode); in cifs_setup_cifs_sb()
3336 if (ctx->iocharset == NULL) { in cifs_setup_cifs_sb()
3338 cifs_sb->local_nls = load_nls_default(); in cifs_setup_cifs_sb()
3340 cifs_sb->local_nls = load_nls(ctx->iocharset); in cifs_setup_cifs_sb()
3341 if (cifs_sb->local_nls == NULL) { in cifs_setup_cifs_sb()
3343 ctx->iocharset); in cifs_setup_cifs_sb()
3344 return -ELIBACC; in cifs_setup_cifs_sb()
3347 ctx->local_nls = cifs_sb->local_nls; in cifs_setup_cifs_sb()
3351 if (ctx->direct_io) in cifs_setup_cifs_sb()
3353 if (ctx->cache_ro) { in cifs_setup_cifs_sb()
3355 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; in cifs_setup_cifs_sb()
3356 } else if (ctx->cache_rw) { in cifs_setup_cifs_sb()
3358 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE | in cifs_setup_cifs_sb()
3362 if ((ctx->cifs_acl) && (ctx->dynperm)) in cifs_setup_cifs_sb()
3365 if (ctx->prepath) { in cifs_setup_cifs_sb()
3366 cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL); in cifs_setup_cifs_sb()
3367 if (cifs_sb->prepath == NULL) in cifs_setup_cifs_sb()
3368 return -ENOMEM; in cifs_setup_cifs_sb()
3369 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; in cifs_setup_cifs_sb()
3380 if (mnt_ctx->tcon) in cifs_mount_put_conns()
3381 cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx); in cifs_mount_put_conns()
3382 else if (mnt_ctx->ses) in cifs_mount_put_conns()
3383 cifs_put_smb_ses(mnt_ctx->ses); in cifs_mount_put_conns()
3384 else if (mnt_ctx->server) in cifs_mount_put_conns()
3385 cifs_put_tcp_session(mnt_ctx->server, 0); in cifs_mount_put_conns()
3386 mnt_ctx->ses = NULL; in cifs_mount_put_conns()
3387 mnt_ctx->tcon = NULL; in cifs_mount_put_conns()
3388 mnt_ctx->server = NULL; in cifs_mount_put_conns()
3389 mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS; in cifs_mount_put_conns()
3390 free_xid(mnt_ctx->xid); in cifs_mount_put_conns()
3403 if (WARN_ON_ONCE(!mnt_ctx || !mnt_ctx->fs_ctx)) { in cifs_mount_get_session()
3404 rc = -EINVAL; in cifs_mount_get_session()
3407 ctx = mnt_ctx->fs_ctx; in cifs_mount_get_session()
3425 if ((ctx->persistent == true) && (!(ses->server->capabilities & in cifs_mount_get_session()
3428 rc = -EOPNOTSUPP; in cifs_mount_get_session()
3432 mnt_ctx->xid = xid; in cifs_mount_get_session()
3433 mnt_ctx->server = server; in cifs_mount_get_session()
3434 mnt_ctx->ses = ses; in cifs_mount_get_session()
3435 mnt_ctx->tcon = NULL; in cifs_mount_get_session()
3445 struct cifs_tcon *tcon = NULL; in cifs_mount_get_tcon() local
3448 if (WARN_ON_ONCE(!mnt_ctx || !mnt_ctx->server || !mnt_ctx->ses || !mnt_ctx->fs_ctx || in cifs_mount_get_tcon()
3449 !mnt_ctx->cifs_sb)) { in cifs_mount_get_tcon()
3450 rc = -EINVAL; in cifs_mount_get_tcon()
3453 server = mnt_ctx->server; in cifs_mount_get_tcon()
3454 ctx = mnt_ctx->fs_ctx; in cifs_mount_get_tcon()
3455 cifs_sb = mnt_ctx->cifs_sb; in cifs_mount_get_tcon()
3457 /* search for existing tcon to this server share */ in cifs_mount_get_tcon()
3458 tcon = cifs_get_tcon(mnt_ctx->ses, ctx); in cifs_mount_get_tcon()
3459 if (IS_ERR(tcon)) { in cifs_mount_get_tcon()
3460 rc = PTR_ERR(tcon); in cifs_mount_get_tcon()
3461 tcon = NULL; in cifs_mount_get_tcon()
3466 if (tcon->posix_extensions) in cifs_mount_get_tcon()
3467 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; in cifs_mount_get_tcon()
3471 if (cap_unix(tcon->ses)) { in cifs_mount_get_tcon()
3476 reset_cifs_unix_caps(mnt_ctx->xid, tcon, cifs_sb, ctx); in cifs_mount_get_tcon()
3477 spin_lock(&tcon->ses->server->srv_lock); in cifs_mount_get_tcon()
3478 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && in cifs_mount_get_tcon()
3479 (le64_to_cpu(tcon->fsUnixInfo.Capability) & in cifs_mount_get_tcon()
3481 spin_unlock(&tcon->ses->server->srv_lock); in cifs_mount_get_tcon()
3482 rc = -EACCES; in cifs_mount_get_tcon()
3485 spin_unlock(&tcon->ses->server->srv_lock); in cifs_mount_get_tcon()
3488 tcon->unix_ext = 0; /* server does not support them */ in cifs_mount_get_tcon()
3490 /* do not care if a following call succeed - informational */ in cifs_mount_get_tcon()
3491 if (!tcon->pipe && server->ops->qfs_tcon) { in cifs_mount_get_tcon()
3492 server->ops->qfs_tcon(mnt_ctx->xid, tcon, cifs_sb); in cifs_mount_get_tcon()
3493 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { in cifs_mount_get_tcon()
3494 if (tcon->fsDevInfo.DeviceCharacteristics & in cifs_mount_get_tcon()
3497 else if ((cifs_sb->mnt_cifs_flags & in cifs_mount_get_tcon()
3509 if ((cifs_sb->ctx->wsize == 0) || in cifs_mount_get_tcon()
3510 (cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx))) { in cifs_mount_get_tcon()
3511 cifs_sb->ctx->wsize = in cifs_mount_get_tcon()
3512 round_down(server->ops->negotiate_wsize(tcon, ctx), PAGE_SIZE); in cifs_mount_get_tcon()
3517 if (cifs_sb->ctx->wsize == 0) { in cifs_mount_get_tcon()
3518 cifs_sb->ctx->wsize = PAGE_SIZE; in cifs_mount_get_tcon()
3522 if ((cifs_sb->ctx->rsize == 0) || in cifs_mount_get_tcon()
3523 (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx))) in cifs_mount_get_tcon()
3524 cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx); in cifs_mount_get_tcon()
3531 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) in cifs_mount_get_tcon()
3532 cifs_fscache_get_super_cookie(tcon); in cifs_mount_get_tcon()
3535 mnt_ctx->tcon = tcon; in cifs_mount_get_tcon()
3540 struct cifs_tcon *tcon) in mount_setup_tlink() argument
3544 /* hang the tcon off of the superblock */ in mount_setup_tlink()
3547 return -ENOMEM; in mount_setup_tlink()
3549 tlink->tl_uid = ses->linux_uid; in mount_setup_tlink()
3550 tlink->tl_tcon = tcon; in mount_setup_tlink()
3551 tlink->tl_time = jiffies; in mount_setup_tlink()
3552 set_bit(TCON_LINK_MASTER, &tlink->tl_flags); in mount_setup_tlink()
3553 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in mount_setup_tlink()
3555 cifs_sb->master_tlink = tlink; in mount_setup_tlink()
3556 spin_lock(&cifs_sb->tlink_tree_lock); in mount_setup_tlink()
3557 tlink_rb_insert(&cifs_sb->tlink_tree, tlink); in mount_setup_tlink()
3558 spin_unlock(&cifs_sb->tlink_tree_lock); in mount_setup_tlink()
3560 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, in mount_setup_tlink()
3568 struct cifs_tcon *tcon, in cifs_are_all_path_components_accessible() argument
3581 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, ""); in cifs_are_all_path_components_accessible()
3600 * temporarily null-terminate the path at the end of in cifs_are_all_path_components_accessible()
3605 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, in cifs_are_all_path_components_accessible()
3615 * Return -EREMOTE if it is, otherwise 0 or -errno.
3620 struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; in cifs_is_path_remote()
3621 struct TCP_Server_Info *server = mnt_ctx->server; in cifs_is_path_remote()
3622 unsigned int xid = mnt_ctx->xid; in cifs_is_path_remote()
3623 struct cifs_tcon *tcon = mnt_ctx->tcon; in cifs_is_path_remote() local
3624 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; in cifs_is_path_remote()
3627 if (!server->ops->is_path_accessible) in cifs_is_path_remote()
3628 return -EOPNOTSUPP; in cifs_is_path_remote()
3631 * cifs_build_path_to_root works only when we have a valid tcon in cifs_is_path_remote()
3633 full_path = cifs_build_path_to_root(ctx, cifs_sb, tcon, in cifs_is_path_remote()
3634 tcon->Flags & SMB_SHARE_IS_IN_DFS); in cifs_is_path_remote()
3636 return -ENOMEM; in cifs_is_path_remote()
3640 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, in cifs_is_path_remote()
3642 if (rc != 0 && rc != -EREMOTE) in cifs_is_path_remote()
3645 if (rc != -EREMOTE) { in cifs_is_path_remote()
3646 rc = cifs_are_all_path_components_accessible(server, xid, tcon, in cifs_is_path_remote()
3647 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); in cifs_is_path_remote()
3650 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; in cifs_is_path_remote()
3669 if (!ctx->dfs_conn) in cifs_mount()
3681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; in cifs_mount()
3682 kfree(cifs_sb->prepath); in cifs_mount()
3683 cifs_sb->prepath = ctx->prepath; in cifs_mount()
3684 ctx->prepath = NULL; in cifs_mount()
3688 rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); in cifs_mount()
3716 rc = -EHOSTDOWN; in cifs_mount()
3718 rc = -EACCES; in cifs_mount()
3719 else if (WARN_ON(!mnt_ctx.tcon)) in cifs_mount()
3720 rc = -ENOENT; in cifs_mount()
3726 if (rc == -EREMOTE) in cifs_mount()
3727 rc = -EOPNOTSUPP; in cifs_mount()
3731 rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); in cifs_mount()
3750 const char *tree, struct cifs_tcon *tcon, in CIFSTCon() argument
3763 return -EIO; in CIFSTCon()
3767 return -ENOMEM; in CIFSTCon()
3774 smb_buffer->Mid = get_next_mid(ses->server); in CIFSTCon()
3775 smb_buffer->Uid = ses->Suid; in CIFSTCon()
3779 pSMB->AndXCommand = 0xFF; in CIFSTCon()
3780 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); in CIFSTCon()
3781 bcc_ptr = &pSMB->Password[0]; in CIFSTCon()
3783 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ in CIFSTCon()
3788 if (ses->server->sign) in CIFSTCon()
3789 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; in CIFSTCon()
3791 if (ses->capabilities & CAP_STATUS32) in CIFSTCon()
3792 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; in CIFSTCon()
3794 if (ses->capabilities & CAP_DFS) in CIFSTCon()
3795 smb_buffer->Flags2 |= SMBFLG2_DFS; in CIFSTCon()
3797 if (ses->capabilities & CAP_UNICODE) { in CIFSTCon()
3798 smb_buffer->Flags2 |= SMBFLG2_UNICODE; in CIFSTCon()
3812 count = bcc_ptr - &pSMB->Password[0]; in CIFSTCon()
3813 be32_add_cpu(&pSMB->hdr.smb_buf_length, count); in CIFSTCon()
3814 pSMB->ByteCount = cpu_to_le16(count); in CIFSTCon()
3823 tcon->tid = smb_buffer_response->Tid; in CIFSTCon()
3826 length = strnlen(bcc_ptr, bytes_left - 2); in CIFSTCon()
3827 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) in CIFSTCon()
3838 tcon->ipc = true; in CIFSTCon()
3839 tcon->pipe = true; in CIFSTCon()
3848 bytes_left -= (length + 1); in CIFSTCon()
3849 strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name)); in CIFSTCon()
3851 /* mostly informational -- no need to fail on error here */ in CIFSTCon()
3852 kfree(tcon->nativeFileSystem); in CIFSTCon()
3853 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, in CIFSTCon()
3857 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem); in CIFSTCon()
3859 if ((smb_buffer_response->WordCount == 3) || in CIFSTCon()
3860 (smb_buffer_response->WordCount == 7)) in CIFSTCon()
3862 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); in CIFSTCon()
3864 tcon->Flags = 0; in CIFSTCon()
3865 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags); in CIFSTCon()
3872 * need_reconnect when tcon was successful but needed to be in CIFSTCon()
3875 if (tcon->need_reconnect && tcon->unix_ext) { in CIFSTCon()
3876 cifs_dbg(FYI, "resetting caps for %s\n", tcon->tree_name); in CIFSTCon()
3877 tcon->need_reconnect = false; in CIFSTCon()
3878 reset_cifs_unix_caps(xid, tcon, NULL, NULL); in CIFSTCon()
3890 unload_nls(cifs_sb->local_nls); in delayed_free()
3891 smb3_cleanup_fs_context(cifs_sb->ctx); in delayed_free()
3898 struct rb_root *root = &cifs_sb->tlink_tree; in cifs_umount()
3902 cancel_delayed_work_sync(&cifs_sb->prune_tlinks); in cifs_umount()
3904 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_umount()
3908 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in cifs_umount()
3911 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_umount()
3913 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_umount()
3915 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_umount()
3917 kfree(cifs_sb->prepath); in cifs_umount()
3918 call_rcu(&cifs_sb->rcu, delayed_free); in cifs_umount()
3927 if (!server->ops->need_neg || !server->ops->negotiate) in cifs_negotiate_protocol()
3928 return -ENOSYS; in cifs_negotiate_protocol()
3931 spin_lock(&server->srv_lock); in cifs_negotiate_protocol()
3932 if (server->tcpStatus != CifsGood && in cifs_negotiate_protocol()
3933 server->tcpStatus != CifsNew && in cifs_negotiate_protocol()
3934 server->tcpStatus != CifsNeedNegotiate) { in cifs_negotiate_protocol()
3935 spin_unlock(&server->srv_lock); in cifs_negotiate_protocol()
3936 return -EHOSTDOWN; in cifs_negotiate_protocol()
3939 if (!server->ops->need_neg(server) && in cifs_negotiate_protocol()
3940 server->tcpStatus == CifsGood) { in cifs_negotiate_protocol()
3941 spin_unlock(&server->srv_lock); in cifs_negotiate_protocol()
3945 server->tcpStatus = CifsInNegotiate; in cifs_negotiate_protocol()
3946 spin_unlock(&server->srv_lock); in cifs_negotiate_protocol()
3948 rc = server->ops->negotiate(xid, ses, server); in cifs_negotiate_protocol()
3950 spin_lock(&server->srv_lock); in cifs_negotiate_protocol()
3951 if (server->tcpStatus == CifsInNegotiate) in cifs_negotiate_protocol()
3952 server->tcpStatus = CifsGood; in cifs_negotiate_protocol()
3954 rc = -EHOSTDOWN; in cifs_negotiate_protocol()
3955 spin_unlock(&server->srv_lock); in cifs_negotiate_protocol()
3957 spin_lock(&server->srv_lock); in cifs_negotiate_protocol()
3958 if (server->tcpStatus == CifsInNegotiate) in cifs_negotiate_protocol()
3959 server->tcpStatus = CifsNeedNegotiate; in cifs_negotiate_protocol()
3960 spin_unlock(&server->srv_lock); in cifs_negotiate_protocol()
3971 int rc = -ENOSYS; in cifs_setup_session()
3972 struct TCP_Server_Info *pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; in cifs_setup_session()
3973 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr; in cifs_setup_session()
3974 struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr; in cifs_setup_session()
3977 spin_lock(&ses->ses_lock); in cifs_setup_session()
3978 cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", in cifs_setup_session()
3979 __func__, ses->chans_need_reconnect); in cifs_setup_session()
3981 if (ses->ses_status != SES_GOOD && in cifs_setup_session()
3982 ses->ses_status != SES_NEW && in cifs_setup_session()
3983 ses->ses_status != SES_NEED_RECON) { in cifs_setup_session()
3984 spin_unlock(&ses->ses_lock); in cifs_setup_session()
3985 return -EHOSTDOWN; in cifs_setup_session()
3989 spin_lock(&ses->chan_lock); in cifs_setup_session()
3991 if (ses->ses_status == SES_NEED_RECON) in cifs_setup_session()
3992 ses->ses_status = SES_GOOD; in cifs_setup_session()
3993 spin_unlock(&ses->chan_lock); in cifs_setup_session()
3994 spin_unlock(&ses->ses_lock); in cifs_setup_session()
4000 spin_unlock(&ses->chan_lock); in cifs_setup_session()
4003 ses->ses_status = SES_IN_SETUP; in cifs_setup_session()
4006 ses->iface_last_update = 0; in cifs_setup_session()
4008 spin_unlock(&ses->ses_lock); in cifs_setup_session()
4012 if (server->dstaddr.ss_family == AF_INET6) in cifs_setup_session()
4013 scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI6", &addr6->sin6_addr); in cifs_setup_session()
4015 scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI4", &addr->sin_addr); in cifs_setup_session()
4019 ses->capabilities = server->capabilities; in cifs_setup_session()
4021 ses->capabilities &= (~server->vals->cap_unix); in cifs_setup_session()
4023 if (ses->auth_key.response) { in cifs_setup_session()
4025 ses->auth_key.response); in cifs_setup_session()
4026 kfree_sensitive(ses->auth_key.response); in cifs_setup_session()
4027 ses->auth_key.response = NULL; in cifs_setup_session()
4028 ses->auth_key.len = 0; in cifs_setup_session()
4033 server->sec_mode, server->capabilities, server->timeAdj); in cifs_setup_session()
4035 if (server->ops->sess_setup) in cifs_setup_session()
4036 rc = server->ops->sess_setup(xid, ses, server, nls_info); in cifs_setup_session()
4040 spin_lock(&ses->ses_lock); in cifs_setup_session()
4041 if (ses->ses_status == SES_IN_SETUP) in cifs_setup_session()
4042 ses->ses_status = SES_NEED_RECON; in cifs_setup_session()
4043 spin_lock(&ses->chan_lock); in cifs_setup_session()
4045 spin_unlock(&ses->chan_lock); in cifs_setup_session()
4046 spin_unlock(&ses->ses_lock); in cifs_setup_session()
4048 spin_lock(&ses->ses_lock); in cifs_setup_session()
4049 if (ses->ses_status == SES_IN_SETUP) in cifs_setup_session()
4050 ses->ses_status = SES_GOOD; in cifs_setup_session()
4051 spin_lock(&ses->chan_lock); in cifs_setup_session()
4054 spin_unlock(&ses->chan_lock); in cifs_setup_session()
4055 spin_unlock(&ses->ses_lock); in cifs_setup_session()
4064 ctx->sectype = ses->sectype; in cifs_set_vol_auth()
4067 if (ctx->sectype == Kerberos) in cifs_set_vol_auth()
4079 struct cifs_tcon *tcon = NULL; in cifs_construct_tcon() local
4085 return ERR_PTR(-ENOMEM); in cifs_construct_tcon()
4087 ctx->local_nls = cifs_sb->local_nls; in cifs_construct_tcon()
4088 ctx->linux_uid = fsuid; in cifs_construct_tcon()
4089 ctx->cred_uid = fsuid; in cifs_construct_tcon()
4090 ctx->UNC = master_tcon->tree_name; in cifs_construct_tcon()
4091 ctx->retry = master_tcon->retry; in cifs_construct_tcon()
4092 ctx->nocase = master_tcon->nocase; in cifs_construct_tcon()
4093 ctx->nohandlecache = master_tcon->nohandlecache; in cifs_construct_tcon()
4094 ctx->local_lease = master_tcon->local_lease; in cifs_construct_tcon()
4095 ctx->no_lease = master_tcon->no_lease; in cifs_construct_tcon()
4096 ctx->resilient = master_tcon->use_resilient; in cifs_construct_tcon()
4097 ctx->persistent = master_tcon->use_persistent; in cifs_construct_tcon()
4098 ctx->handle_timeout = master_tcon->handle_timeout; in cifs_construct_tcon()
4099 ctx->no_linux_ext = !master_tcon->unix_ext; in cifs_construct_tcon()
4100 ctx->linux_ext = master_tcon->posix_extensions; in cifs_construct_tcon()
4101 ctx->sectype = master_tcon->ses->sectype; in cifs_construct_tcon()
4102 ctx->sign = master_tcon->ses->sign; in cifs_construct_tcon()
4103 ctx->seal = master_tcon->seal; in cifs_construct_tcon()
4104 ctx->witness = master_tcon->use_witness; in cifs_construct_tcon()
4105 ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses; in cifs_construct_tcon()
4107 rc = cifs_set_vol_auth(ctx, master_tcon->ses); in cifs_construct_tcon()
4109 tcon = ERR_PTR(rc); in cifs_construct_tcon()
4115 ++master_tcon->ses->server->srv_count; in cifs_construct_tcon()
4118 ses = cifs_get_smb_ses(master_tcon->ses->server, ctx); in cifs_construct_tcon()
4120 tcon = ERR_CAST(ses); in cifs_construct_tcon()
4121 cifs_put_tcp_session(master_tcon->ses->server, 0); in cifs_construct_tcon()
4126 spin_lock(&master_tcon->tc_lock); in cifs_construct_tcon()
4127 if (master_tcon->origin_fullpath) { in cifs_construct_tcon()
4128 spin_unlock(&master_tcon->tc_lock); in cifs_construct_tcon()
4129 origin_fullpath = dfs_get_path(cifs_sb, cifs_sb->ctx->source); in cifs_construct_tcon()
4131 tcon = ERR_CAST(origin_fullpath); in cifs_construct_tcon()
4137 spin_unlock(&master_tcon->tc_lock); in cifs_construct_tcon()
4141 tcon = cifs_get_tcon(ses, ctx); in cifs_construct_tcon()
4142 if (IS_ERR(tcon)) { in cifs_construct_tcon()
4149 spin_lock(&tcon->tc_lock); in cifs_construct_tcon()
4150 tcon->origin_fullpath = origin_fullpath; in cifs_construct_tcon()
4151 spin_unlock(&tcon->tc_lock); in cifs_construct_tcon()
4153 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work, in cifs_construct_tcon()
4160 reset_cifs_unix_caps(0, tcon, NULL, ctx); in cifs_construct_tcon()
4164 kfree(ctx->username); in cifs_construct_tcon()
4165 kfree_sensitive(ctx->password); in cifs_construct_tcon()
4169 return tcon; in cifs_construct_tcon()
4182 struct rb_node *node = root->rb_node; in tlink_rb_search()
4188 if (uid_gt(tlink->tl_uid, uid)) in tlink_rb_search()
4189 node = node->rb_left; in tlink_rb_search()
4190 else if (uid_lt(tlink->tl_uid, uid)) in tlink_rb_search()
4191 node = node->rb_right; in tlink_rb_search()
4202 struct rb_node **new = &(root->rb_node), *parent = NULL; in tlink_rb_insert()
4209 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid)) in tlink_rb_insert()
4210 new = &((*new)->rb_left); in tlink_rb_insert()
4212 new = &((*new)->rb_right); in tlink_rb_insert()
4215 rb_link_node(&new_tlink->tl_rbnode, parent, new); in tlink_rb_insert()
4216 rb_insert_color(&new_tlink->tl_rbnode, root); in tlink_rb_insert()
4220 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4224 * the master tcon for the mount.
4226 * First, search the rbtree for an existing tcon for this fsuid. If one
4245 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) in cifs_sb_tlink()
4248 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
4249 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); in cifs_sb_tlink()
4252 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
4257 return ERR_PTR(-ENOMEM); in cifs_sb_tlink()
4258 newtlink->tl_uid = fsuid; in cifs_sb_tlink()
4259 newtlink->tl_tcon = ERR_PTR(-EACCES); in cifs_sb_tlink()
4260 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags); in cifs_sb_tlink()
4261 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags); in cifs_sb_tlink()
4264 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
4266 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); in cifs_sb_tlink()
4269 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
4274 tlink_rb_insert(&cifs_sb->tlink_tree, tlink); in cifs_sb_tlink()
4275 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
4278 err = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, in cifs_sb_tlink()
4282 return ERR_PTR(-ERESTARTSYS); in cifs_sb_tlink()
4286 if (!IS_ERR(tlink->tl_tcon)) in cifs_sb_tlink()
4290 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) { in cifs_sb_tlink()
4291 err = PTR_ERR(tlink->tl_tcon); in cifs_sb_tlink()
4296 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags)) in cifs_sb_tlink()
4300 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid); in cifs_sb_tlink()
4301 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags); in cifs_sb_tlink()
4302 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING); in cifs_sb_tlink()
4304 if (IS_ERR(tlink->tl_tcon)) { in cifs_sb_tlink()
4305 err = PTR_ERR(tlink->tl_tcon); in cifs_sb_tlink()
4306 if (err == -ENOKEY) in cifs_sb_tlink()
4307 err = -EACCES; in cifs_sb_tlink()
4324 struct rb_root *root = &cifs_sb->tlink_tree; in cifs_prune_tlinks()
4333 * umounts. Because this function is non-reentrant and is canceled in cifs_prune_tlinks()
4336 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
4343 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) || in cifs_prune_tlinks()
4344 atomic_read(&tlink->tl_count) != 0 || in cifs_prune_tlinks()
4345 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies)) in cifs_prune_tlinks()
4349 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in cifs_prune_tlinks()
4352 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
4354 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
4356 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
4358 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, in cifs_prune_tlinks()
4363 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon) in cifs_tree_connect() argument
4365 const struct smb_version_operations *ops = tcon->ses->server->ops; in cifs_tree_connect()
4369 spin_lock(&tcon->tc_lock); in cifs_tree_connect()
4371 /* if tcon is marked for needing reconnect, update state */ in cifs_tree_connect()
4372 if (tcon->need_reconnect) in cifs_tree_connect()
4373 tcon->status = TID_NEED_TCON; in cifs_tree_connect()
4375 if (tcon->status == TID_GOOD) { in cifs_tree_connect()
4376 spin_unlock(&tcon->tc_lock); in cifs_tree_connect()
4380 if (tcon->status != TID_NEW && in cifs_tree_connect()
4381 tcon->status != TID_NEED_TCON) { in cifs_tree_connect()
4382 spin_unlock(&tcon->tc_lock); in cifs_tree_connect()
4383 return -EHOSTDOWN; in cifs_tree_connect()
4386 tcon->status = TID_IN_TCON; in cifs_tree_connect()
4387 spin_unlock(&tcon->tc_lock); in cifs_tree_connect()
4389 rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, in cifs_tree_connect()
4390 tcon, tcon->ses->local_nls); in cifs_tree_connect()
4392 spin_lock(&tcon->tc_lock); in cifs_tree_connect()
4393 if (tcon->status == TID_IN_TCON) in cifs_tree_connect()
4394 tcon->status = TID_NEED_TCON; in cifs_tree_connect()
4395 spin_unlock(&tcon->tc_lock); in cifs_tree_connect()
4397 spin_lock(&tcon->tc_lock); in cifs_tree_connect()
4398 if (tcon->status == TID_IN_TCON) in cifs_tree_connect()
4399 tcon->status = TID_GOOD; in cifs_tree_connect()
4400 tcon->need_reconnect = false; in cifs_tree_connect()
4401 spin_unlock(&tcon->tc_lock); in cifs_tree_connect()