Lines Matching +full:tcon +full:- +full:channel
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44 #include <keys/user-type.h>
293 * This should be called with server->srv_mutex held.
302 if (!server->hostname) in reconn_set_ipaddr()
303 return -EINVAL; in reconn_set_ipaddr()
305 len = strlen(server->hostname) + 3; in reconn_set_ipaddr()
310 return -ENOMEM; in reconn_set_ipaddr()
312 scnprintf(unc, len, "\\\\%s", server->hostname); in reconn_set_ipaddr()
319 __func__, server->hostname, rc); in reconn_set_ipaddr()
324 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, in reconn_set_ipaddr()
329 return !rc ? -1 : 0; in reconn_set_ipaddr()
339 /* These functions must be called with server->srv_mutex held */
347 if (!cifs_sb || !cifs_sb->origin_fullpath) in reconn_set_next_dfs_target()
358 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath); in reconn_set_next_dfs_target()
362 kfree(server->hostname); in reconn_set_next_dfs_target()
364 server->hostname = extract_hostname(name); in reconn_set_next_dfs_target()
365 if (IS_ERR(server->hostname)) { in reconn_set_next_dfs_target()
368 __func__, PTR_ERR(server->hostname)); in reconn_set_next_dfs_target()
375 if (!cifs_sb->origin_fullpath) in reconn_setup_dfs_targets()
376 return -EOPNOTSUPP; in reconn_setup_dfs_targets()
377 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl); in reconn_setup_dfs_targets()
387 * wake up waiters on reconnection? - (not needed currently)
395 struct cifs_tcon *tcon; in cifs_reconnect() local
406 server->nr_targets = 1; in cifs_reconnect()
420 if (rc != -EOPNOTSUPP) { in cifs_reconnect()
425 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); in cifs_reconnect()
429 server->nr_targets); in cifs_reconnect()
432 if (server->tcpStatus == CifsExiting) { in cifs_reconnect()
440 wake_up(&server->response_q); in cifs_reconnect()
443 server->tcpStatus = CifsNeedReconnect; in cifs_reconnect()
445 server->maxBuf = 0; in cifs_reconnect()
446 server->max_read = 0; in cifs_reconnect()
449 trace_smb3_reconnect(server->CurrentMid, server->hostname); in cifs_reconnect()
456 list_for_each(tmp, &server->smb_ses_list) { in cifs_reconnect()
458 ses->need_reconnect = true; in cifs_reconnect()
459 list_for_each(tmp2, &ses->tcon_list) { in cifs_reconnect()
460 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); in cifs_reconnect()
461 tcon->need_reconnect = true; in cifs_reconnect()
463 if (ses->tcon_ipc) in cifs_reconnect()
464 ses->tcon_ipc->need_reconnect = true; in cifs_reconnect()
470 mutex_lock(&server->srv_mutex); in cifs_reconnect()
471 if (server->ssocket) { in cifs_reconnect()
473 server->ssocket->state, server->ssocket->flags); in cifs_reconnect()
474 kernel_sock_shutdown(server->ssocket, SHUT_WR); in cifs_reconnect()
476 server->ssocket->state, server->ssocket->flags); in cifs_reconnect()
477 sock_release(server->ssocket); in cifs_reconnect()
478 server->ssocket = NULL; in cifs_reconnect()
480 server->sequence_number = 0; in cifs_reconnect()
481 server->session_estab = false; in cifs_reconnect()
482 kfree(server->session_key.response); in cifs_reconnect()
483 server->session_key.response = NULL; in cifs_reconnect()
484 server->session_key.len = 0; in cifs_reconnect()
485 server->lstrp = jiffies; in cifs_reconnect()
491 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { in cifs_reconnect()
493 kref_get(&mid_entry->refcount); in cifs_reconnect()
494 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) in cifs_reconnect()
495 mid_entry->mid_state = MID_RETRY_NEEDED; in cifs_reconnect()
496 list_move(&mid_entry->qhead, &retry_list); in cifs_reconnect()
497 mid_entry->mid_flags |= MID_DELETED; in cifs_reconnect()
500 mutex_unlock(&server->srv_mutex); in cifs_reconnect()
505 list_del_init(&mid_entry->qhead); in cifs_reconnect()
506 mid_entry->callback(mid_entry); in cifs_reconnect()
511 mutex_lock(&server->srv_mutex); in cifs_reconnect()
513 mutex_unlock(&server->srv_mutex); in cifs_reconnect()
519 mutex_lock(&server->srv_mutex); in cifs_reconnect()
540 mutex_unlock(&server->srv_mutex); in cifs_reconnect()
546 if (server->tcpStatus != CifsExiting) in cifs_reconnect()
547 server->tcpStatus = CifsNeedNegotiate; in cifs_reconnect()
549 mutex_unlock(&server->srv_mutex); in cifs_reconnect()
551 } while (server->tcpStatus == CifsNeedReconnect); in cifs_reconnect()
555 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, in cifs_reconnect()
561 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server); in cifs_reconnect()
572 if (server->tcpStatus == CifsNeedNegotiate) in cifs_reconnect()
573 mod_delayed_work(cifsiod_wq, &server->echo, 0); in cifs_reconnect()
575 wake_up(&server->response_q); in cifs_reconnect()
591 if (server->tcpStatus == CifsNeedNegotiate) in cifs_echo_request()
594 echo_interval = server->echo_interval; in cifs_echo_request()
601 if (server->tcpStatus == CifsNeedReconnect || in cifs_echo_request()
602 server->tcpStatus == CifsExiting || in cifs_echo_request()
603 server->tcpStatus == CifsNew || in cifs_echo_request()
604 (server->ops->can_echo && !server->ops->can_echo(server)) || in cifs_echo_request()
605 time_before(jiffies, server->lstrp + echo_interval - HZ)) in cifs_echo_request()
608 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; in cifs_echo_request()
611 server->hostname); in cifs_echo_request()
614 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval); in cifs_echo_request()
620 if (!server->bigbuf) { in allocate_buffers()
621 server->bigbuf = (char *)cifs_buf_get(); in allocate_buffers()
622 if (!server->bigbuf) { in allocate_buffers()
628 } else if (server->large_buf) { in allocate_buffers()
630 memset(server->bigbuf, 0, HEADER_SIZE(server)); in allocate_buffers()
633 if (!server->smallbuf) { in allocate_buffers()
634 server->smallbuf = (char *)cifs_small_buf_get(); in allocate_buffers()
635 if (!server->smallbuf) { in allocate_buffers()
644 memset(server->smallbuf, 0, HEADER_SIZE(server)); in allocate_buffers()
664 if ((server->tcpStatus == CifsGood || in server_unresponsive()
665 server->tcpStatus == CifsNeedNegotiate) && in server_unresponsive()
666 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { in server_unresponsive()
668 (3 * server->echo_interval) / HZ); in server_unresponsive()
681 spin_lock(&server->req_lock); in zero_credits()
682 val = server->credits + server->echo_credits + server->oplock_credits; in zero_credits()
683 if (server->in_flight == 0 && val == 0) { in zero_credits()
684 spin_unlock(&server->req_lock); in zero_credits()
687 spin_unlock(&server->req_lock); in zero_credits()
697 smb_msg->msg_control = NULL; in cifs_readv_from_socket()
698 smb_msg->msg_controllen = 0; in cifs_readv_from_socket()
706 return -ECONNABORTED; in cifs_readv_from_socket()
710 return -ECONNABORTED; in cifs_readv_from_socket()
711 if (cifs_rdma_enabled(server) && server->smbd_conn) in cifs_readv_from_socket()
712 length = smbd_recv(server->smbd_conn, smb_msg); in cifs_readv_from_socket()
714 length = sock_recvmsg(server->ssocket, smb_msg, 0); in cifs_readv_from_socket()
716 if (server->tcpStatus == CifsExiting) in cifs_readv_from_socket()
717 return -ESHUTDOWN; in cifs_readv_from_socket()
719 if (server->tcpStatus == CifsNeedReconnect) { in cifs_readv_from_socket()
721 return -ECONNABORTED; in cifs_readv_from_socket()
724 if (length == -ERESTARTSYS || in cifs_readv_from_socket()
725 length == -EAGAIN || in cifs_readv_from_socket()
726 length == -EINTR) { in cifs_readv_from_socket()
740 return -ECONNABORTED; in cifs_readv_from_socket()
800 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); in is_smb_response()
815 mid->when_received = jiffies; in dequeue_mid()
819 mid->mid_state = MID_RESPONSE_RECEIVED; in dequeue_mid()
821 mid->mid_state = MID_RESPONSE_MALFORMED; in dequeue_mid()
826 if (mid->mid_flags & MID_DELETED) in dequeue_mid()
829 list_del_init(&mid->qhead); in dequeue_mid()
830 mid->mid_flags |= MID_DELETED; in dequeue_mid()
843 if (server->vals->header_preamble_size) in smb2_get_credits_from_hdr()
846 return le16_to_cpu(shdr->CreditRequest); in smb2_get_credits_from_hdr()
853 if (server->ops->check_trans2 && in handle_mid()
854 server->ops->check_trans2(mid, server, buf, malformed)) in handle_mid()
856 mid->credits_received = smb2_get_credits_from_hdr(buf, server); in handle_mid()
857 mid->resp_buf = buf; in handle_mid()
858 mid->large_buf = server->large_buf; in handle_mid()
859 /* Was previous buf put in mpx struct for multi-rsp? */ in handle_mid()
860 if (!mid->multiRsp) { in handle_mid()
862 if (server->large_buf) in handle_mid()
863 server->bigbuf = NULL; in handle_mid()
865 server->smallbuf = NULL; in handle_mid()
876 list_del_init(&server->tcp_ses_list); in clean_demultiplex_info()
879 cancel_delayed_work_sync(&server->echo); in clean_demultiplex_info()
882 server->tcpStatus = CifsExiting; in clean_demultiplex_info()
884 wake_up_all(&server->response_q); in clean_demultiplex_info()
887 spin_lock(&server->req_lock); in clean_demultiplex_info()
888 if (server->credits <= 0) in clean_demultiplex_info()
889 server->credits = 1; in clean_demultiplex_info()
890 spin_unlock(&server->req_lock); in clean_demultiplex_info()
895 * same server - they now will see the session is in exit state and get in clean_demultiplex_info()
898 wake_up_all(&server->request_q); in clean_demultiplex_info()
903 if (server->ssocket) { in clean_demultiplex_info()
904 sock_release(server->ssocket); in clean_demultiplex_info()
905 server->ssocket = NULL; in clean_demultiplex_info()
908 if (!list_empty(&server->pending_mid_q)) { in clean_demultiplex_info()
915 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { in clean_demultiplex_info()
917 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid); in clean_demultiplex_info()
918 kref_get(&mid_entry->refcount); in clean_demultiplex_info()
919 mid_entry->mid_state = MID_SHUTDOWN; in clean_demultiplex_info()
920 list_move(&mid_entry->qhead, &dispose_list); in clean_demultiplex_info()
921 mid_entry->mid_flags |= MID_DELETED; in clean_demultiplex_info()
928 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid); in clean_demultiplex_info()
929 list_del_init(&mid_entry->qhead); in clean_demultiplex_info()
930 mid_entry->callback(mid_entry); in clean_demultiplex_info()
937 if (!list_empty(&server->pending_mid_q)) { in clean_demultiplex_info()
954 kfree(server->hostname); in clean_demultiplex_info()
966 char *buf = server->smallbuf; in standard_receive3()
967 unsigned int pdu_length = server->pdu_size; in standard_receive3()
970 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - in standard_receive3()
971 server->vals->header_preamble_size) { in standard_receive3()
974 return -ECONNABORTED; in standard_receive3()
978 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { in standard_receive3()
979 server->large_buf = true; in standard_receive3()
980 memcpy(server->bigbuf, buf, server->total_read); in standard_receive3()
981 buf = server->bigbuf; in standard_receive3()
985 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, in standard_receive3()
986 pdu_length - HEADER_SIZE(server) + 1 in standard_receive3()
987 + server->vals->header_preamble_size); in standard_receive3()
991 server->total_read += length; in standard_receive3()
993 dump_smb(buf, server->total_read); in standard_receive3()
1001 char *buf = server->large_buf ? server->bigbuf : server->smallbuf; in cifs_handle_standard()
1013 length = server->ops->check_message(buf, server->total_read, server); in cifs_handle_standard()
1016 min_t(unsigned int, server->total_read, 48)); in cifs_handle_standard()
1018 if (server->ops->is_session_expired && in cifs_handle_standard()
1019 server->ops->is_session_expired(buf)) { in cifs_handle_standard()
1021 return -1; in cifs_handle_standard()
1024 if (server->ops->is_status_pending && in cifs_handle_standard()
1025 server->ops->is_status_pending(buf, server)) in cifs_handle_standard()
1026 return -1; in cifs_handle_standard()
1043 if (server->vals->header_preamble_size) in smb2_add_credits_from_hdr()
1046 if (shdr->CreditRequest) { in smb2_add_credits_from_hdr()
1047 spin_lock(&server->req_lock); in smb2_add_credits_from_hdr()
1048 server->credits += le16_to_cpu(shdr->CreditRequest); in smb2_add_credits_from_hdr()
1049 spin_unlock(&server->req_lock); in smb2_add_credits_from_hdr()
1050 wake_up(&server->request_q); in smb2_add_credits_from_hdr()
1077 while (server->tcpStatus != CifsExiting) { in cifs_demultiplex_thread()
1084 server->large_buf = false; in cifs_demultiplex_thread()
1085 buf = server->smallbuf; in cifs_demultiplex_thread()
1092 if (server->vals->header_preamble_size == 0) in cifs_demultiplex_thread()
1093 server->total_read = 0; in cifs_demultiplex_thread()
1095 server->total_read = length; in cifs_demultiplex_thread()
1098 * The right amount was read from socket - 4 bytes, in cifs_demultiplex_thread()
1107 server->pdu_size = pdu_length; in cifs_demultiplex_thread()
1110 if (server->pdu_size < HEADER_SIZE(server) - 1 - in cifs_demultiplex_thread()
1111 server->vals->header_preamble_size) { in cifs_demultiplex_thread()
1113 server->pdu_size); in cifs_demultiplex_thread()
1120 buf + server->vals->header_preamble_size, in cifs_demultiplex_thread()
1121 HEADER_SIZE(server) - 1 in cifs_demultiplex_thread()
1122 - server->vals->header_preamble_size); in cifs_demultiplex_thread()
1125 server->total_read += length; in cifs_demultiplex_thread()
1127 if (server->ops->next_header) { in cifs_demultiplex_thread()
1128 next_offset = server->ops->next_header(buf); in cifs_demultiplex_thread()
1130 server->pdu_size = next_offset; in cifs_demultiplex_thread()
1137 if (server->ops->is_transform_hdr && in cifs_demultiplex_thread()
1138 server->ops->receive_transform && in cifs_demultiplex_thread()
1139 server->ops->is_transform_hdr(buf)) { in cifs_demultiplex_thread()
1140 length = server->ops->receive_transform(server, in cifs_demultiplex_thread()
1145 mids[0] = server->ops->find_mid(server, buf); in cifs_demultiplex_thread()
1149 if (!mids[0] || !mids[0]->receive) in cifs_demultiplex_thread()
1152 length = mids[0]->receive(server, mids[0]); in cifs_demultiplex_thread()
1162 if (server->ops->is_status_io_timeout && in cifs_demultiplex_thread()
1163 server->ops->is_status_io_timeout(buf)) { in cifs_demultiplex_thread()
1172 server->lstrp = jiffies; in cifs_demultiplex_thread()
1176 mids[i]->resp_buf_size = server->pdu_size; in cifs_demultiplex_thread()
1178 if (!mids[i]->multiRsp || mids[i]->multiEnd) in cifs_demultiplex_thread()
1179 mids[i]->callback(mids[i]); in cifs_demultiplex_thread()
1182 } else if (server->ops->is_oplock_break && in cifs_demultiplex_thread()
1183 server->ops->is_oplock_break(bufs[i], in cifs_demultiplex_thread()
1194 if (server->ops->dump_detail) in cifs_demultiplex_thread()
1195 server->ops->dump_detail(bufs[i], in cifs_demultiplex_thread()
1202 if (pdu_length > server->pdu_size) { in cifs_demultiplex_thread()
1205 pdu_length -= server->pdu_size; in cifs_demultiplex_thread()
1206 server->total_read = 0; in cifs_demultiplex_thread()
1207 server->large_buf = false; in cifs_demultiplex_thread()
1208 buf = server->smallbuf; in cifs_demultiplex_thread()
1213 /* buffer usually freed in free_mid - need to free it here on exit */ in cifs_demultiplex_thread()
1214 cifs_buf_release(server->bigbuf); in cifs_demultiplex_thread()
1215 if (server->smallbuf) /* no sense logging a debug message if NULL */ in cifs_demultiplex_thread()
1216 cifs_small_buf_release(server->smallbuf); in cifs_demultiplex_thread()
1218 task_to_wake = xchg(&server->tsk, NULL); in cifs_demultiplex_thread()
1221 /* if server->tsk was NULL then wait for a signal before exiting */ in cifs_demultiplex_thread()
1246 return ERR_PTR(-EINVAL); in extract_hostname()
1250 return ERR_PTR(-EINVAL); in extract_hostname()
1255 return ERR_PTR(-EINVAL); in extract_hostname()
1257 len = delim - src; in extract_hostname()
1260 return ERR_PTR(-ENOMEM); in extract_hostname()
1275 return -ENOMEM; in get_option_ul()
1294 return -EINVAL; in get_option_uid()
1312 return -EINVAL; in get_option_gid()
1319 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1331 return -EINVAL; in cifs_parse_devname()
1337 return -EINVAL; in cifs_parse_devname()
1342 return -EINVAL; in cifs_parse_devname()
1352 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL); in cifs_parse_devname()
1353 if (!vol->UNC) in cifs_parse_devname()
1354 return -ENOMEM; in cifs_parse_devname()
1356 convert_delimiter(vol->UNC, '\\'); in cifs_parse_devname()
1366 vol->prepath = kstrdup(pos, GFP_KERNEL); in cifs_parse_devname()
1367 if (!vol->prepath) in cifs_parse_devname()
1368 return -ENOMEM; in cifs_parse_devname()
1381 short int override_uid = -1; in cifs_parse_mount_options()
1382 short int override_gid = -1; in cifs_parse_mount_options()
1387 char *nodename = utsname()->nodename; in cifs_parse_mount_options()
1394 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr; in cifs_parse_mount_options()
1400 /* ensure we always start with zeroed-out smb_vol */ in cifs_parse_mount_options()
1408 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); in cifs_parse_mount_options()
1410 vol->source_rfc1001_name[i] = toupper(nodename[i]); in cifs_parse_mount_options()
1412 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0; in cifs_parse_mount_options()
1415 vol->target_rfc1001_name[0] = 0; in cifs_parse_mount_options()
1416 vol->cred_uid = current_uid(); in cifs_parse_mount_options()
1417 vol->linux_uid = current_uid(); in cifs_parse_mount_options()
1418 vol->linux_gid = current_gid(); in cifs_parse_mount_options()
1419 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */ in cifs_parse_mount_options()
1426 vol->remap = true; in cifs_parse_mount_options()
1429 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; in cifs_parse_mount_options()
1431 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ in cifs_parse_mount_options()
1433 vol->posix_paths = 1; in cifs_parse_mount_options()
1435 vol->server_ino = 1; in cifs_parse_mount_options()
1438 vol->strict_io = true; in cifs_parse_mount_options()
1440 vol->actimeo = CIFS_DEF_ACTIMEO; in cifs_parse_mount_options()
1443 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ in cifs_parse_mount_options()
1446 vol->ops = &smb30_operations; in cifs_parse_mount_options()
1447 vol->vals = &smbdefault_values; in cifs_parse_mount_options()
1449 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; in cifs_parse_mount_options()
1452 vol->multichannel = false; in cifs_parse_mount_options()
1453 vol->max_channels = 1; in cifs_parse_mount_options()
1473 vol->backupuid_specified = false; /* no backup intent for a user */ in cifs_parse_mount_options()
1474 vol->backupgid_specified = false; /* no backup intent for a group */ in cifs_parse_mount_options()
1479 case -ENOMEM: in cifs_parse_mount_options()
1482 case -EINVAL: in cifs_parse_mount_options()
1508 vol->no_xattr = 0; in cifs_parse_mount_options()
1511 vol->no_xattr = 1; in cifs_parse_mount_options()
1526 vol->noblocksnd = 1; in cifs_parse_mount_options()
1529 vol->noautotune = 1; in cifs_parse_mount_options()
1532 vol->no_lease = 1; in cifs_parse_mount_options()
1535 vol->retry = 1; in cifs_parse_mount_options()
1538 vol->retry = 0; in cifs_parse_mount_options()
1541 vol->noperm = 0; in cifs_parse_mount_options()
1544 vol->noperm = 1; in cifs_parse_mount_options()
1547 vol->nodelete = 1; in cifs_parse_mount_options()
1550 vol->sfu_remap = true; in cifs_parse_mount_options()
1551 vol->remap = false; /* disable SFM mapping */ in cifs_parse_mount_options()
1554 vol->sfu_remap = false; in cifs_parse_mount_options()
1557 vol->remap = true; in cifs_parse_mount_options()
1558 vol->sfu_remap = false; /* disable SFU mapping */ in cifs_parse_mount_options()
1561 vol->remap = false; in cifs_parse_mount_options()
1564 vol->sfu_emul = 1; in cifs_parse_mount_options()
1567 vol->sfu_emul = 0; in cifs_parse_mount_options()
1570 vol->nodfs = 1; in cifs_parse_mount_options()
1574 vol->rootfs = true; in cifs_parse_mount_options()
1578 vol->posix_paths = 1; in cifs_parse_mount_options()
1581 vol->posix_paths = 0; in cifs_parse_mount_options()
1584 if (vol->linux_ext) in cifs_parse_mount_options()
1587 vol->no_linux_ext = 1; in cifs_parse_mount_options()
1590 if (vol->no_linux_ext) in cifs_parse_mount_options()
1593 vol->linux_ext = 1; in cifs_parse_mount_options()
1596 vol->nocase = 1; in cifs_parse_mount_options()
1599 vol->nobrl = 0; in cifs_parse_mount_options()
1602 vol->nobrl = 1; in cifs_parse_mount_options()
1608 if (vol->file_mode == in cifs_parse_mount_options()
1610 vol->file_mode = S_IALLUGO; in cifs_parse_mount_options()
1613 vol->nohandlecache = 1; in cifs_parse_mount_options()
1616 vol->nohandlecache = 0; in cifs_parse_mount_options()
1619 vol->mand_lock = 1; in cifs_parse_mount_options()
1622 vol->setuids = 1; in cifs_parse_mount_options()
1625 vol->setuids = 0; in cifs_parse_mount_options()
1628 vol->setuidfromacl = 1; in cifs_parse_mount_options()
1631 vol->dynperm = true; in cifs_parse_mount_options()
1634 vol->dynperm = false; in cifs_parse_mount_options()
1637 vol->retry = 0; in cifs_parse_mount_options()
1640 vol->retry = 1; in cifs_parse_mount_options()
1643 vol->intr = 0; in cifs_parse_mount_options()
1646 vol->intr = 1; in cifs_parse_mount_options()
1649 vol->nostrictsync = 1; in cifs_parse_mount_options()
1652 vol->nostrictsync = 0; in cifs_parse_mount_options()
1655 vol->server_ino = 1; in cifs_parse_mount_options()
1658 vol->server_ino = 0; in cifs_parse_mount_options()
1661 vol->rwpidforward = 1; in cifs_parse_mount_options()
1664 vol->mode_ace = 1; in cifs_parse_mount_options()
1667 vol->cifs_acl = 1; in cifs_parse_mount_options()
1670 vol->cifs_acl = 0; in cifs_parse_mount_options()
1673 vol->no_psx_acl = 0; in cifs_parse_mount_options()
1676 vol->no_psx_acl = 1; in cifs_parse_mount_options()
1679 vol->local_lease = 1; in cifs_parse_mount_options()
1682 vol->sign = true; in cifs_parse_mount_options()
1685 vol->sign = true; in cifs_parse_mount_options()
1686 vol->ignore_signature = true; in cifs_parse_mount_options()
1691 * or per-smb connection option in the protocol in cifs_parse_mount_options()
1692 * vol->secFlg |= CIFSSEC_MUST_SEAL; in cifs_parse_mount_options()
1694 vol->seal = 1; in cifs_parse_mount_options()
1701 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n"); in cifs_parse_mount_options()
1704 vol->fsc = true; in cifs_parse_mount_options()
1707 vol->mfsymlinks = true; in cifs_parse_mount_options()
1710 vol->multiuser = true; in cifs_parse_mount_options()
1716 vol->nosharesock = true; in cifs_parse_mount_options()
1719 vol->nopersistent = true; in cifs_parse_mount_options()
1720 if (vol->persistent) { in cifs_parse_mount_options()
1727 vol->persistent = true; in cifs_parse_mount_options()
1728 if ((vol->nopersistent) || (vol->resilient)) { in cifs_parse_mount_options()
1735 vol->resilient = true; in cifs_parse_mount_options()
1736 if (vol->persistent) { in cifs_parse_mount_options()
1743 vol->resilient = false; /* already the default */ in cifs_parse_mount_options()
1746 vol->domainauto = true; in cifs_parse_mount_options()
1749 vol->rdma = true; in cifs_parse_mount_options()
1752 vol->multichannel = true; in cifs_parse_mount_options()
1754 if (vol->max_channels < 2) in cifs_parse_mount_options()
1755 vol->max_channels = 2; in cifs_parse_mount_options()
1758 vol->multichannel = false; in cifs_parse_mount_options()
1759 vol->max_channels = 1; in cifs_parse_mount_options()
1762 vol->compression = UNKNOWN_TYPE; in cifs_parse_mount_options()
1769 if (get_option_uid(args, &vol->backupuid)) { in cifs_parse_mount_options()
1774 vol->backupuid_specified = true; in cifs_parse_mount_options()
1777 if (get_option_gid(args, &vol->backupgid)) { in cifs_parse_mount_options()
1782 vol->backupgid_specified = true; in cifs_parse_mount_options()
1785 if (get_option_uid(args, &vol->linux_uid)) { in cifs_parse_mount_options()
1793 if (get_option_uid(args, &vol->cred_uid)) { in cifs_parse_mount_options()
1800 if (get_option_gid(args, &vol->linux_gid)) { in cifs_parse_mount_options()
1813 vol->file_mode = option; in cifs_parse_mount_options()
1821 vol->dir_mode = option; in cifs_parse_mount_options()
1837 vol->min_offload = option; in cifs_parse_mount_options()
1857 vol->bsize = option; in cifs_parse_mount_options()
1865 vol->rsize = option; in cifs_parse_mount_options()
1873 vol->wsize = option; in cifs_parse_mount_options()
1881 vol->actimeo = HZ * option; in cifs_parse_mount_options()
1882 if (vol->actimeo > CIFS_MAX_ACTIMEO) { in cifs_parse_mount_options()
1893 vol->handle_timeout = option; in cifs_parse_mount_options()
1894 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { in cifs_parse_mount_options()
1905 vol->echo_interval = option; in cifs_parse_mount_options()
1913 vol->snapshot_time = option; in cifs_parse_mount_options()
1922 vol->max_credits = option; in cifs_parse_mount_options()
1927 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n", in cifs_parse_mount_options()
1931 vol->max_channels = option; in cifs_parse_mount_options()
1938 vol->nullauth = 1; in cifs_parse_mount_options()
1939 vol->username = NULL; in cifs_parse_mount_options()
1952 kfree(vol->username); in cifs_parse_mount_options()
1953 vol->username = kstrdup(string, GFP_KERNEL); in cifs_parse_mount_options()
1954 if (!vol->username) in cifs_parse_mount_options()
1971 kfree_sensitive(vol->password); in cifs_parse_mount_options()
1972 vol->password = NULL; in cifs_parse_mount_options()
2009 kfree_sensitive(vol->password); in cifs_parse_mount_options()
2012 vol->password = kzalloc(temp_len+1, GFP_KERNEL); in cifs_parse_mount_options()
2013 if (vol->password == NULL) { in cifs_parse_mount_options()
2019 vol->password[j] = value[i]; in cifs_parse_mount_options()
2025 vol->password[j] = '\0'; in cifs_parse_mount_options()
2054 kfree(vol->domainname); in cifs_parse_mount_options()
2055 vol->domainname = kstrdup(string, GFP_KERNEL); in cifs_parse_mount_options()
2056 if (!vol->domainname) { in cifs_parse_mount_options()
2068 (struct sockaddr *)&vol->srcaddr, in cifs_parse_mount_options()
2086 kfree(vol->iocharset); in cifs_parse_mount_options()
2087 vol->iocharset = kstrdup(string, in cifs_parse_mount_options()
2089 if (!vol->iocharset) { in cifs_parse_mount_options()
2104 memset(vol->source_rfc1001_name, 0x20, in cifs_parse_mount_options()
2115 vol->source_rfc1001_name[i] = string[i]; in cifs_parse_mount_options()
2130 memset(vol->target_rfc1001_name, 0x20, in cifs_parse_mount_options()
2142 vol->target_rfc1001_name[i] = string[i]; in cifs_parse_mount_options()
2213 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) { in cifs_parse_mount_options()
2220 if (vol->multiuser) { in cifs_parse_mount_options()
2225 if (!vol->UNC) { in cifs_parse_mount_options()
2231 if (!strchr(vol->UNC + 3, '\\')) { in cifs_parse_mount_options()
2242 slash = strchr(&vol->UNC[2], '\\'); in cifs_parse_mount_options()
2243 len = slash - &vol->UNC[2]; in cifs_parse_mount_options()
2244 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) { in cifs_parse_mount_options()
2254 vol->override_uid = override_uid; in cifs_parse_mount_options()
2259 vol->override_gid = override_gid; in cifs_parse_mount_options()
2284 switch (srcaddr->sa_family) { in cifs_match_ipaddr()
2286 return (rhs->sa_family == AF_UNSPEC); in cifs_match_ipaddr()
2290 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr); in cifs_match_ipaddr()
2295 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); in cifs_match_ipaddr()
2305 * and if it fails - with 139 ports. It should be called only if address
2314 if (server->rdma) in match_port()
2317 switch (addr->sa_family) { in match_port()
2319 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; in match_port()
2320 port = ((struct sockaddr_in *) addr)->sin_port; in match_port()
2323 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port; in match_port()
2324 port = ((struct sockaddr_in6 *) addr)->sin6_port; in match_port()
2346 switch (addr->sa_family) { in match_address()
2350 (struct sockaddr_in *)&server->dstaddr; in match_address()
2352 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr) in match_address()
2359 (struct sockaddr_in6 *)&server->dstaddr; in match_address()
2361 if (!ipv6_addr_equal(&addr6->sin6_addr, in match_address()
2362 &srv_addr6->sin6_addr)) in match_address()
2364 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id) in match_address()
2373 if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr)) in match_address()
2383 * The select_sectype function should either return the vol->sectype in match_security()
2387 if (server->ops->select_sectype(server, vol->sectype) in match_security()
2394 * the server->sign had better be too. in match_security()
2396 if (vol->sign && !server->sign) in match_security()
2404 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; in match_server()
2406 if (vol->nosharesock) in match_server()
2410 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { in match_server()
2411 if (server->vals->protocol_id < SMB30_PROT_ID) in match_server()
2413 } else if (strcmp(vol->vals->version_string, in match_server()
2415 if (server->vals->protocol_id < SMB21_PROT_ID) in match_server()
2417 } else if ((server->vals != vol->vals) || (server->ops != vol->ops)) in match_server()
2420 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) in match_server()
2424 (struct sockaddr *)&vol->srcaddr)) in match_server()
2433 if (server->echo_interval != vol->echo_interval * HZ) in match_server()
2436 if (server->rdma != vol->rdma) in match_server()
2439 if (server->ignore_signature != vol->ignore_signature) in match_server()
2442 if (server->min_offload != vol->min_offload) in match_server()
2459 if (server->is_channel || !match_server(server, vol)) in cifs_find_tcp_session()
2462 ++server->srv_count; in cifs_find_tcp_session()
2477 if (--server->srv_count > 0) { in cifs_put_tcp_session()
2484 list_del_init(&server->tcp_ses_list); in cifs_put_tcp_session()
2487 cancel_delayed_work_sync(&server->echo); in cifs_put_tcp_session()
2496 cancel_delayed_work(&server->reconnect); in cifs_put_tcp_session()
2498 cancel_delayed_work_sync(&server->reconnect); in cifs_put_tcp_session()
2501 server->tcpStatus = CifsExiting; in cifs_put_tcp_session()
2507 kfree(server->session_key.response); in cifs_put_tcp_session()
2508 server->session_key.response = NULL; in cifs_put_tcp_session()
2509 server->session_key.len = 0; in cifs_put_tcp_session()
2511 task = xchg(&server->tsk, NULL); in cifs_put_tcp_session()
2522 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC); in cifs_get_tcp_session()
2531 rc = -ENOMEM; in cifs_get_tcp_session()
2535 tcp_ses->ops = volume_info->ops; in cifs_get_tcp_session()
2536 tcp_ses->vals = volume_info->vals; in cifs_get_tcp_session()
2537 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); in cifs_get_tcp_session()
2538 tcp_ses->hostname = extract_hostname(volume_info->UNC); in cifs_get_tcp_session()
2539 if (IS_ERR(tcp_ses->hostname)) { in cifs_get_tcp_session()
2540 rc = PTR_ERR(tcp_ses->hostname); in cifs_get_tcp_session()
2544 tcp_ses->noblockcnt = volume_info->rootfs; in cifs_get_tcp_session()
2545 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs; in cifs_get_tcp_session()
2546 tcp_ses->noautotune = volume_info->noautotune; in cifs_get_tcp_session()
2547 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; in cifs_get_tcp_session()
2548 tcp_ses->rdma = volume_info->rdma; in cifs_get_tcp_session()
2549 tcp_ses->in_flight = 0; in cifs_get_tcp_session()
2550 tcp_ses->max_in_flight = 0; in cifs_get_tcp_session()
2551 tcp_ses->credits = 1; in cifs_get_tcp_session()
2552 init_waitqueue_head(&tcp_ses->response_q); in cifs_get_tcp_session()
2553 init_waitqueue_head(&tcp_ses->request_q); in cifs_get_tcp_session()
2554 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); in cifs_get_tcp_session()
2555 mutex_init(&tcp_ses->srv_mutex); in cifs_get_tcp_session()
2556 memcpy(tcp_ses->workstation_RFC1001_name, in cifs_get_tcp_session()
2557 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); in cifs_get_tcp_session()
2558 memcpy(tcp_ses->server_RFC1001_name, in cifs_get_tcp_session()
2559 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); in cifs_get_tcp_session()
2560 tcp_ses->session_estab = false; in cifs_get_tcp_session()
2561 tcp_ses->sequence_number = 0; in cifs_get_tcp_session()
2562 tcp_ses->reconnect_instance = 1; in cifs_get_tcp_session()
2563 tcp_ses->lstrp = jiffies; in cifs_get_tcp_session()
2564 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression); in cifs_get_tcp_session()
2565 spin_lock_init(&tcp_ses->req_lock); in cifs_get_tcp_session()
2566 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); in cifs_get_tcp_session()
2567 INIT_LIST_HEAD(&tcp_ses->smb_ses_list); in cifs_get_tcp_session()
2568 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); in cifs_get_tcp_session()
2569 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); in cifs_get_tcp_session()
2570 mutex_init(&tcp_ses->reconnect_mutex); in cifs_get_tcp_session()
2571 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr, in cifs_get_tcp_session()
2572 sizeof(tcp_ses->srcaddr)); in cifs_get_tcp_session()
2573 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, in cifs_get_tcp_session()
2574 sizeof(tcp_ses->dstaddr)); in cifs_get_tcp_session()
2575 if (volume_info->use_client_guid) in cifs_get_tcp_session()
2576 memcpy(tcp_ses->client_guid, volume_info->client_guid, in cifs_get_tcp_session()
2579 generate_random_uuid(tcp_ses->client_guid); in cifs_get_tcp_session()
2585 tcp_ses->tcpStatus = CifsNew; in cifs_get_tcp_session()
2586 ++tcp_ses->srv_count; in cifs_get_tcp_session()
2588 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN && in cifs_get_tcp_session()
2589 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX) in cifs_get_tcp_session()
2590 tcp_ses->echo_interval = volume_info->echo_interval * HZ; in cifs_get_tcp_session()
2592 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; in cifs_get_tcp_session()
2593 if (tcp_ses->rdma) { in cifs_get_tcp_session()
2596 rc = -ENOENT; in cifs_get_tcp_session()
2599 tcp_ses->smbd_conn = smbd_get_connection( in cifs_get_tcp_session()
2600 tcp_ses, (struct sockaddr *)&volume_info->dstaddr); in cifs_get_tcp_session()
2601 if (tcp_ses->smbd_conn) { in cifs_get_tcp_session()
2606 rc = -ENOENT; in cifs_get_tcp_session()
2621 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread, in cifs_get_tcp_session()
2623 if (IS_ERR(tcp_ses->tsk)) { in cifs_get_tcp_session()
2624 rc = PTR_ERR(tcp_ses->tsk); in cifs_get_tcp_session()
2629 tcp_ses->min_offload = volume_info->min_offload; in cifs_get_tcp_session()
2630 tcp_ses->tcpStatus = CifsNeedNegotiate; in cifs_get_tcp_session()
2632 tcp_ses->nr_targets = 1; in cifs_get_tcp_session()
2633 tcp_ses->ignore_signature = volume_info->ignore_signature; in cifs_get_tcp_session()
2636 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); in cifs_get_tcp_session()
2642 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); in cifs_get_tcp_session()
2653 if (!IS_ERR(tcp_ses->hostname)) in cifs_get_tcp_session()
2654 kfree(tcp_ses->hostname); in cifs_get_tcp_session()
2655 if (tcp_ses->ssocket) in cifs_get_tcp_session()
2656 sock_release(tcp_ses->ssocket); in cifs_get_tcp_session()
2664 if (vol->sectype != Unspecified && in match_session()
2665 vol->sectype != ses->sectype) in match_session()
2672 if (ses->chan_max < vol->max_channels) in match_session()
2675 switch (ses->sectype) { in match_session()
2677 if (!uid_eq(vol->cred_uid, ses->cred_uid)) in match_session()
2682 if (ses->user_name == NULL) { in match_session()
2683 if (!vol->nullauth) in match_session()
2689 if (strncmp(ses->user_name, in match_session()
2690 vol->username ? vol->username : "", in match_session()
2693 if ((vol->username && strlen(vol->username) != 0) && in match_session()
2694 ses->password != NULL && in match_session()
2695 strncmp(ses->password, in match_session()
2696 vol->password ? vol->password : "", in match_session()
2704 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2707 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2713 struct cifs_tcon *tcon; in cifs_setup_ipc() local
2717 struct TCP_Server_Info *server = ses->server; in cifs_setup_ipc()
2723 if (volume_info->seal) { in cifs_setup_ipc()
2724 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) in cifs_setup_ipc()
2729 return -EOPNOTSUPP; in cifs_setup_ipc()
2733 tcon = tconInfoAlloc(); in cifs_setup_ipc()
2734 if (tcon == NULL) in cifs_setup_ipc()
2735 return -ENOMEM; in cifs_setup_ipc()
2737 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); in cifs_setup_ipc()
2743 tcon->ses = ses; in cifs_setup_ipc()
2744 tcon->ipc = true; in cifs_setup_ipc()
2745 tcon->seal = seal; in cifs_setup_ipc()
2746 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); in cifs_setup_ipc()
2751 tconInfoFree(tcon); in cifs_setup_ipc()
2755 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid); in cifs_setup_ipc()
2757 ses->tcon_ipc = tcon; in cifs_setup_ipc()
2764 * cifs_free_ipc - helper to release the session IPC tcon
2772 struct cifs_tcon *tcon = ses->tcon_ipc; in cifs_free_ipc() local
2774 if (tcon == NULL) in cifs_free_ipc()
2777 if (ses->server->ops->tree_disconnect) { in cifs_free_ipc()
2779 rc = ses->server->ops->tree_disconnect(xid, tcon); in cifs_free_ipc()
2784 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc); in cifs_free_ipc()
2786 tconInfoFree(tcon); in cifs_free_ipc()
2787 ses->tcon_ipc = NULL; in cifs_free_ipc()
2797 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { in cifs_find_smb_ses()
2798 if (ses->status == CifsExiting) in cifs_find_smb_ses()
2802 ++ses->ses_count; in cifs_find_smb_ses()
2813 struct TCP_Server_Info *server = ses->server; in cifs_put_smb_ses()
2815 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); in cifs_put_smb_ses()
2818 if (ses->status == CifsExiting) { in cifs_put_smb_ses()
2822 if (--ses->ses_count > 0) { in cifs_put_smb_ses()
2826 if (ses->status == CifsGood) in cifs_put_smb_ses()
2827 ses->status = CifsExiting; in cifs_put_smb_ses()
2832 if (ses->status == CifsExiting && server->ops->logoff) { in cifs_put_smb_ses()
2834 rc = server->ops->logoff(xid, ses); in cifs_put_smb_ses()
2842 list_del_init(&ses->smb_ses_list); in cifs_put_smb_ses()
2846 if (ses->chan_count > 1) { in cifs_put_smb_ses()
2849 for (i = 1; i < ses->chan_count; i++) in cifs_put_smb_ses()
2850 cifs_put_tcp_session(ses->chans[i].server, 0); in cifs_put_smb_ses()
2872 struct TCP_Server_Info *server = ses->server; in cifs_set_cifscreds()
2879 return -ENOMEM; in cifs_set_cifscreds()
2882 switch (server->dstaddr.ss_family) { in cifs_set_cifscreds()
2884 sa = (struct sockaddr_in *)&server->dstaddr; in cifs_set_cifscreds()
2885 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); in cifs_set_cifscreds()
2888 sa6 = (struct sockaddr_in6 *)&server->dstaddr; in cifs_set_cifscreds()
2889 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); in cifs_set_cifscreds()
2893 server->dstaddr.ss_family); in cifs_set_cifscreds()
2894 rc = -EINVAL; in cifs_set_cifscreds()
2901 if (!ses->domainName) { in cifs_set_cifscreds()
2908 sprintf(desc, "cifs:d:%s", ses->domainName); in cifs_set_cifscreds()
2918 down_read(&key->sem); in cifs_set_cifscreds()
2921 rc = upayload ? PTR_ERR(upayload) : -EINVAL; in cifs_set_cifscreds()
2926 payload = upayload->data; in cifs_set_cifscreds()
2927 delim = strnchr(payload, upayload->datalen, ':'); in cifs_set_cifscreds()
2931 upayload->datalen); in cifs_set_cifscreds()
2932 rc = -EINVAL; in cifs_set_cifscreds()
2936 len = delim - payload; in cifs_set_cifscreds()
2940 rc = -EINVAL; in cifs_set_cifscreds()
2944 vol->username = kstrndup(payload, len, GFP_KERNEL); in cifs_set_cifscreds()
2945 if (!vol->username) { in cifs_set_cifscreds()
2948 rc = -ENOMEM; in cifs_set_cifscreds()
2951 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username); in cifs_set_cifscreds()
2953 len = key->datalen - (len + 1); in cifs_set_cifscreds()
2956 rc = -EINVAL; in cifs_set_cifscreds()
2957 kfree(vol->username); in cifs_set_cifscreds()
2958 vol->username = NULL; in cifs_set_cifscreds()
2963 vol->password = kstrndup(delim, len, GFP_KERNEL); in cifs_set_cifscreds()
2964 if (!vol->password) { in cifs_set_cifscreds()
2967 rc = -ENOMEM; in cifs_set_cifscreds()
2968 kfree(vol->username); in cifs_set_cifscreds()
2969 vol->username = NULL; in cifs_set_cifscreds()
2977 if (is_domain && ses->domainName) { in cifs_set_cifscreds()
2978 vol->domainname = kstrndup(ses->domainName, in cifs_set_cifscreds()
2979 strlen(ses->domainName), in cifs_set_cifscreds()
2981 if (!vol->domainname) { in cifs_set_cifscreds()
2984 rc = -ENOMEM; in cifs_set_cifscreds()
2985 kfree(vol->username); in cifs_set_cifscreds()
2986 vol->username = NULL; in cifs_set_cifscreds()
2987 kfree_sensitive(vol->password); in cifs_set_cifscreds()
2988 vol->password = NULL; in cifs_set_cifscreds()
2994 up_read(&key->sem); in cifs_set_cifscreds()
3006 return -ENOSYS; in cifs_set_cifscreds()
3011 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3020 int rc = -ENOMEM; in cifs_get_smb_ses()
3023 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; in cifs_get_smb_ses()
3024 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; in cifs_get_smb_ses()
3031 ses->status); in cifs_get_smb_ses()
3033 mutex_lock(&ses->session_mutex); in cifs_get_smb_ses()
3036 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
3037 /* problem -- put our ses reference */ in cifs_get_smb_ses()
3042 if (ses->need_reconnect) { in cifs_get_smb_ses()
3045 volume_info->local_nls); in cifs_get_smb_ses()
3047 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
3048 /* problem -- put our reference */ in cifs_get_smb_ses()
3054 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
3068 ses->server = server; in cifs_get_smb_ses()
3069 if (server->dstaddr.ss_family == AF_INET6) in cifs_get_smb_ses()
3070 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr); in cifs_get_smb_ses()
3072 sprintf(ses->serverName, "%pI4", &addr->sin_addr); in cifs_get_smb_ses()
3074 if (volume_info->username) { in cifs_get_smb_ses()
3075 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL); in cifs_get_smb_ses()
3076 if (!ses->user_name) in cifs_get_smb_ses()
3080 /* volume_info->password freed at unmount */ in cifs_get_smb_ses()
3081 if (volume_info->password) { in cifs_get_smb_ses()
3082 ses->password = kstrdup(volume_info->password, GFP_KERNEL); in cifs_get_smb_ses()
3083 if (!ses->password) in cifs_get_smb_ses()
3086 if (volume_info->domainname) { in cifs_get_smb_ses()
3087 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL); in cifs_get_smb_ses()
3088 if (!ses->domainName) in cifs_get_smb_ses()
3091 if (volume_info->domainauto) in cifs_get_smb_ses()
3092 ses->domainAuto = volume_info->domainauto; in cifs_get_smb_ses()
3093 ses->cred_uid = volume_info->cred_uid; in cifs_get_smb_ses()
3094 ses->linux_uid = volume_info->linux_uid; in cifs_get_smb_ses()
3096 ses->sectype = volume_info->sectype; in cifs_get_smb_ses()
3097 ses->sign = volume_info->sign; in cifs_get_smb_ses()
3098 mutex_lock(&ses->session_mutex); in cifs_get_smb_ses()
3100 /* add server as first channel */ in cifs_get_smb_ses()
3101 ses->chans[0].server = server; in cifs_get_smb_ses()
3102 ses->chan_count = 1; in cifs_get_smb_ses()
3103 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1; in cifs_get_smb_ses()
3107 rc = cifs_setup_session(xid, ses, volume_info->local_nls); in cifs_get_smb_ses()
3109 /* each channel uses a different signing key */ in cifs_get_smb_ses()
3110 memcpy(ses->chans[0].signkey, ses->smb3signingkey, in cifs_get_smb_ses()
3111 sizeof(ses->smb3signingkey)); in cifs_get_smb_ses()
3113 mutex_unlock(&ses->session_mutex); in cifs_get_smb_ses()
3117 /* success, put it on the list and add it as first channel */ in cifs_get_smb_ses()
3119 list_add(&ses->smb_ses_list, &server->smb_ses_list); in cifs_get_smb_ses()
3134 static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) in match_tcon() argument
3136 if (tcon->tidStatus == CifsExiting) in match_tcon()
3138 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE)) in match_tcon()
3140 if (tcon->seal != volume_info->seal) in match_tcon()
3142 if (tcon->snapshot_time != volume_info->snapshot_time) in match_tcon()
3144 if (tcon->handle_timeout != volume_info->handle_timeout) in match_tcon()
3146 if (tcon->no_lease != volume_info->no_lease) in match_tcon()
3148 if (tcon->nodelete != volume_info->nodelete) in match_tcon()
3157 struct cifs_tcon *tcon; in cifs_find_tcon() local
3160 list_for_each(tmp, &ses->tcon_list) { in cifs_find_tcon()
3161 tcon = list_entry(tmp, struct cifs_tcon, tcon_list); in cifs_find_tcon()
3163 if (tcon->dfs_path) in cifs_find_tcon()
3166 if (!match_tcon(tcon, volume_info)) in cifs_find_tcon()
3168 ++tcon->tc_count; in cifs_find_tcon()
3170 return tcon; in cifs_find_tcon()
3177 cifs_put_tcon(struct cifs_tcon *tcon) in cifs_put_tcon() argument
3183 * IPC tcon share the lifetime of their session and are in cifs_put_tcon()
3186 if (tcon == NULL || tcon->ipc) in cifs_put_tcon()
3189 ses = tcon->ses; in cifs_put_tcon()
3190 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); in cifs_put_tcon()
3192 if (--tcon->tc_count > 0) { in cifs_put_tcon()
3197 list_del_init(&tcon->tcon_list); in cifs_put_tcon()
3201 if (ses->server->ops->tree_disconnect) in cifs_put_tcon()
3202 ses->server->ops->tree_disconnect(xid, tcon); in cifs_put_tcon()
3205 cifs_fscache_release_super_cookie(tcon); in cifs_put_tcon()
3206 tconInfoFree(tcon); in cifs_put_tcon()
3211 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3213 * - tcon refcount is the number of mount points using the tcon.
3214 * - ses refcount is the number of tcon using the session.
3222 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3223 * its session refcount incremented (1 new tcon). This +1 was
3226 * b) an existing tcon with refcount+1 (add a mount point to it) and
3227 * identical ses refcount (no new tcon). Because of (1) we need to
3234 struct cifs_tcon *tcon; in cifs_get_tcon() local
3236 tcon = cifs_find_tcon(ses, volume_info); in cifs_get_tcon()
3237 if (tcon) { in cifs_get_tcon()
3239 * tcon has refcount already incremented but we need to in cifs_get_tcon()
3244 return tcon; in cifs_get_tcon()
3247 if (!ses->server->ops->tree_connect) { in cifs_get_tcon()
3248 rc = -ENOSYS; in cifs_get_tcon()
3252 tcon = tconInfoAlloc(); in cifs_get_tcon()
3253 if (tcon == NULL) { in cifs_get_tcon()
3254 rc = -ENOMEM; in cifs_get_tcon()
3258 if (volume_info->snapshot_time) { in cifs_get_tcon()
3259 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3262 rc = -EOPNOTSUPP; in cifs_get_tcon()
3265 tcon->snapshot_time = volume_info->snapshot_time; in cifs_get_tcon()
3268 if (volume_info->handle_timeout) { in cifs_get_tcon()
3269 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3272 rc = -EOPNOTSUPP; in cifs_get_tcon()
3275 tcon->handle_timeout = volume_info->handle_timeout; in cifs_get_tcon()
3278 tcon->ses = ses; in cifs_get_tcon()
3279 if (volume_info->password) { in cifs_get_tcon()
3280 tcon->password = kstrdup(volume_info->password, GFP_KERNEL); in cifs_get_tcon()
3281 if (!tcon->password) { in cifs_get_tcon()
3282 rc = -ENOMEM; in cifs_get_tcon()
3287 if (volume_info->seal) { in cifs_get_tcon()
3288 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3291 rc = -EOPNOTSUPP; in cifs_get_tcon()
3293 } else if (tcon->ses->server->capabilities & in cifs_get_tcon()
3295 tcon->seal = true; in cifs_get_tcon()
3298 rc = -EOPNOTSUPP; in cifs_get_tcon()
3303 if (volume_info->linux_ext) { in cifs_get_tcon()
3304 if (ses->server->posix_ext_supported) { in cifs_get_tcon()
3305 tcon->posix_extensions = true; in cifs_get_tcon()
3309 rc = -EOPNOTSUPP; in cifs_get_tcon()
3315 * BB Do we need to wrap session_mutex around this TCon call and Unix in cifs_get_tcon()
3319 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon, in cifs_get_tcon()
3320 volume_info->local_nls); in cifs_get_tcon()
3322 cifs_dbg(FYI, "Tcon rc = %d\n", rc); in cifs_get_tcon()
3326 tcon->use_persistent = false; in cifs_get_tcon()
3328 if (volume_info->persistent) { in cifs_get_tcon()
3329 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3332 rc = -EOPNOTSUPP; in cifs_get_tcon()
3334 } else if (ses->server->capabilities & in cifs_get_tcon()
3336 tcon->use_persistent = true; in cifs_get_tcon()
3340 rc = -EOPNOTSUPP; in cifs_get_tcon()
3343 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) in cifs_get_tcon()
3344 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) in cifs_get_tcon()
3345 && (volume_info->nopersistent == false)) { in cifs_get_tcon()
3347 tcon->use_persistent = true; in cifs_get_tcon()
3348 } else if (volume_info->resilient) { in cifs_get_tcon()
3349 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3352 rc = -EOPNOTSUPP; in cifs_get_tcon()
3355 tcon->use_resilient = true; in cifs_get_tcon()
3359 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) { in cifs_get_tcon()
3360 if (volume_info->cache_ro) in cifs_get_tcon()
3362 else if (volume_info->cache_rw) in cifs_get_tcon()
3366 if (volume_info->no_lease) { in cifs_get_tcon()
3367 if (ses->server->vals->protocol_id == 0) { in cifs_get_tcon()
3370 rc = -EOPNOTSUPP; in cifs_get_tcon()
3373 tcon->no_lease = volume_info->no_lease; in cifs_get_tcon()
3381 tcon->retry = volume_info->retry; in cifs_get_tcon()
3382 tcon->nocase = volume_info->nocase; in cifs_get_tcon()
3383 if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) in cifs_get_tcon()
3384 tcon->nohandlecache = volume_info->nohandlecache; in cifs_get_tcon()
3386 tcon->nohandlecache = 1; in cifs_get_tcon()
3387 tcon->nodelete = volume_info->nodelete; in cifs_get_tcon()
3388 tcon->local_lease = volume_info->local_lease; in cifs_get_tcon()
3389 INIT_LIST_HEAD(&tcon->pending_opens); in cifs_get_tcon()
3392 list_add(&tcon->tcon_list, &ses->tcon_list); in cifs_get_tcon()
3395 cifs_fscache_get_super_cookie(tcon); in cifs_get_tcon()
3397 return tcon; in cifs_get_tcon()
3400 tconInfoFree(tcon); in cifs_get_tcon()
3410 if (!atomic_dec_and_test(&tlink->tl_count) || in cifs_put_tlink()
3411 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) { in cifs_put_tlink()
3412 tlink->tl_time = jiffies; in cifs_put_tlink()
3426 struct cifs_sb_info *new = mnt_data->cifs_sb; in compare_mount_options()
3427 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK; in compare_mount_options()
3428 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK; in compare_mount_options()
3430 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) in compare_mount_options()
3433 if (old->mnt_cifs_serverino_autodisabled) in compare_mount_options()
3443 if (new->wsize && new->wsize < old->wsize) in compare_mount_options()
3446 if (new->rsize && new->rsize < old->rsize) in compare_mount_options()
3449 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid)) in compare_mount_options()
3452 if (old->mnt_file_mode != new->mnt_file_mode || in compare_mount_options()
3453 old->mnt_dir_mode != new->mnt_dir_mode) in compare_mount_options()
3456 if (strcmp(old->local_nls->charset, new->local_nls->charset)) in compare_mount_options()
3459 if (old->actimeo != new->actimeo) in compare_mount_options()
3469 struct cifs_sb_info *new = mnt_data->cifs_sb; in match_prepath()
3470 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && in match_prepath()
3471 old->prepath; in match_prepath()
3472 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && in match_prepath()
3473 new->prepath; in match_prepath()
3475 if (old_set && new_set && !strcmp(new->prepath, old->prepath)) in match_prepath()
3491 struct cifs_tcon *tcon; in cifs_match_super() local
3502 tcon = tlink_tcon(tlink); in cifs_match_super()
3503 ses = tcon->ses; in cifs_match_super()
3504 tcp_srv = ses->server; in cifs_match_super()
3506 volume_info = mnt_data->vol; in cifs_match_super()
3510 !match_tcon(tcon, volume_info) || in cifs_match_super()
3530 struct sock *sk = sock->sk; in cifs_reclassify_socket4()
3532 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", in cifs_reclassify_socket4()
3533 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); in cifs_reclassify_socket4()
3539 struct sock *sk = sock->sk; in cifs_reclassify_socket6()
3541 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", in cifs_reclassify_socket6()
3542 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); in cifs_reclassify_socket6()
3574 if (server->srcaddr.ss_family != AF_UNSPEC) { in bind_socket()
3576 struct socket *socket = server->ssocket; in bind_socket()
3577 rc = socket->ops->bind(socket, in bind_socket()
3578 (struct sockaddr *) &server->srcaddr, in bind_socket()
3579 sizeof(server->srcaddr)); in bind_socket()
3583 saddr4 = (struct sockaddr_in *)&server->srcaddr; in bind_socket()
3584 saddr6 = (struct sockaddr_in6 *)&server->srcaddr; in bind_socket()
3585 if (saddr6->sin6_family == AF_INET6) in bind_socket()
3587 &saddr6->sin6_addr, rc); in bind_socket()
3590 &saddr4->sin_addr.s_addr, rc); in bind_socket()
3602 * negprot - BB check reconnection in case where second in ip_rfc1001_connect()
3610 ses_init_buf->trailer.session_req.called_len = 32; in ip_rfc1001_connect()
3612 if (server->server_RFC1001_name[0] != 0) in ip_rfc1001_connect()
3613 rfc1002mangle(ses_init_buf->trailer. in ip_rfc1001_connect()
3615 server->server_RFC1001_name, in ip_rfc1001_connect()
3618 rfc1002mangle(ses_init_buf->trailer. in ip_rfc1001_connect()
3623 ses_init_buf->trailer.session_req.calling_len = 32; in ip_rfc1001_connect()
3629 if (server->workstation_RFC1001_name[0] != 0) in ip_rfc1001_connect()
3630 rfc1002mangle(ses_init_buf->trailer. in ip_rfc1001_connect()
3632 server->workstation_RFC1001_name, in ip_rfc1001_connect()
3635 rfc1002mangle(ses_init_buf->trailer. in ip_rfc1001_connect()
3640 ses_init_buf->trailer.session_req.scope1 = 0; in ip_rfc1001_connect()
3641 ses_init_buf->trailer.session_req.scope2 = 0; in ip_rfc1001_connect()
3645 smb_buf->smb_buf_length = cpu_to_be32(0x81000044); in ip_rfc1001_connect()
3674 struct socket *socket = server->ssocket; in generic_ip_connect()
3677 saddr = (struct sockaddr *) &server->dstaddr; in generic_ip_connect()
3679 if (server->dstaddr.ss_family == AF_INET6) { in generic_ip_connect()
3680 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr; in generic_ip_connect()
3682 sport = ipv6->sin6_port; in generic_ip_connect()
3685 cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr, in generic_ip_connect()
3688 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr; in generic_ip_connect()
3690 sport = ipv4->sin_port; in generic_ip_connect()
3693 cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr, in generic_ip_connect()
3702 server->ssocket = NULL; in generic_ip_connect()
3708 server->ssocket = socket; in generic_ip_connect()
3709 socket->sk->sk_allocation = GFP_NOFS; in generic_ip_connect()
3725 socket->sk->sk_rcvtimeo = 7 * HZ; in generic_ip_connect()
3726 socket->sk->sk_sndtimeo = 5 * HZ; in generic_ip_connect()
3729 if (server->noautotune) { in generic_ip_connect()
3730 if (socket->sk->sk_sndbuf < (200 * 1024)) in generic_ip_connect()
3731 socket->sk->sk_sndbuf = 200 * 1024; in generic_ip_connect()
3732 if (socket->sk->sk_rcvbuf < (140 * 1024)) in generic_ip_connect()
3733 socket->sk->sk_rcvbuf = 140 * 1024; in generic_ip_connect()
3736 if (server->tcp_nodelay) in generic_ip_connect()
3737 tcp_sock_set_nodelay(socket->sk); in generic_ip_connect()
3740 socket->sk->sk_sndbuf, in generic_ip_connect()
3741 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); in generic_ip_connect()
3743 rc = socket->ops->connect(socket, saddr, slen, in generic_ip_connect()
3744 server->noblockcnt ? O_NONBLOCK : 0); in generic_ip_connect()
3748 * reconnect failover - if possible. in generic_ip_connect()
3750 if (server->noblockcnt && rc == -EINPROGRESS) in generic_ip_connect()
3755 server->ssocket = NULL; in generic_ip_connect()
3769 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; in ip_connect()
3770 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; in ip_connect()
3772 if (server->dstaddr.ss_family == AF_INET6) in ip_connect()
3773 sport = &addr6->sin6_port; in ip_connect()
3775 sport = &addr->sin_port; in ip_connect()
3794 void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, in reset_cifs_unix_caps() argument
3801 * Perhaps we could add a backpointer to array of sb from tcon in reset_cifs_unix_caps()
3803 * sb as NFS - then we only have one backpointer to sb. in reset_cifs_unix_caps()
3806 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); in reset_cifs_unix_caps()
3808 if (vol_info && vol_info->no_linux_ext) { in reset_cifs_unix_caps()
3809 tcon->fsUnixInfo.Capability = 0; in reset_cifs_unix_caps()
3810 tcon->unix_ext = 0; /* Unix Extensions disabled */ in reset_cifs_unix_caps()
3814 tcon->unix_ext = 1; /* Unix Extensions supported */ in reset_cifs_unix_caps()
3816 if (tcon->unix_ext == 0) { in reset_cifs_unix_caps()
3821 if (!CIFSSMBQFSUnixInfo(xid, tcon)) { in reset_cifs_unix_caps()
3822 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); in reset_cifs_unix_caps()
3842 cifs_dbg(VFS, "per-share encryption not supported yet\n"); in reset_cifs_unix_caps()
3845 if (vol_info && vol_info->no_psx_acl) in reset_cifs_unix_caps()
3850 cifs_sb->mnt_cifs_flags |= in reset_cifs_unix_caps()
3854 if (vol_info && vol_info->posix_paths == 0) in reset_cifs_unix_caps()
3859 cifs_sb->mnt_cifs_flags |= in reset_cifs_unix_caps()
3884 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { in reset_cifs_unix_caps()
3897 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); in cifs_setup_cifs_sb()
3899 spin_lock_init(&cifs_sb->tlink_tree_lock); in cifs_setup_cifs_sb()
3900 cifs_sb->tlink_tree = RB_ROOT; in cifs_setup_cifs_sb()
3902 cifs_sb->bsize = pvolume_info->bsize; in cifs_setup_cifs_sb()
3907 cifs_sb->rsize = pvolume_info->rsize; in cifs_setup_cifs_sb()
3908 cifs_sb->wsize = pvolume_info->wsize; in cifs_setup_cifs_sb()
3910 cifs_sb->mnt_uid = pvolume_info->linux_uid; in cifs_setup_cifs_sb()
3911 cifs_sb->mnt_gid = pvolume_info->linux_gid; in cifs_setup_cifs_sb()
3912 cifs_sb->mnt_file_mode = pvolume_info->file_mode; in cifs_setup_cifs_sb()
3913 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; in cifs_setup_cifs_sb()
3915 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); in cifs_setup_cifs_sb()
3917 cifs_sb->actimeo = pvolume_info->actimeo; in cifs_setup_cifs_sb()
3918 cifs_sb->local_nls = pvolume_info->local_nls; in cifs_setup_cifs_sb()
3920 if (pvolume_info->nodfs) in cifs_setup_cifs_sb()
3921 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS; in cifs_setup_cifs_sb()
3922 if (pvolume_info->noperm) in cifs_setup_cifs_sb()
3923 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; in cifs_setup_cifs_sb()
3924 if (pvolume_info->setuids) in cifs_setup_cifs_sb()
3925 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; in cifs_setup_cifs_sb()
3926 if (pvolume_info->setuidfromacl) in cifs_setup_cifs_sb()
3927 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL; in cifs_setup_cifs_sb()
3928 if (pvolume_info->server_ino) in cifs_setup_cifs_sb()
3929 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; in cifs_setup_cifs_sb()
3930 if (pvolume_info->remap) in cifs_setup_cifs_sb()
3931 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR; in cifs_setup_cifs_sb()
3932 if (pvolume_info->sfu_remap) in cifs_setup_cifs_sb()
3933 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; in cifs_setup_cifs_sb()
3934 if (pvolume_info->no_xattr) in cifs_setup_cifs_sb()
3935 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; in cifs_setup_cifs_sb()
3936 if (pvolume_info->sfu_emul) in cifs_setup_cifs_sb()
3937 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; in cifs_setup_cifs_sb()
3938 if (pvolume_info->nobrl) in cifs_setup_cifs_sb()
3939 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; in cifs_setup_cifs_sb()
3940 if (pvolume_info->nohandlecache) in cifs_setup_cifs_sb()
3941 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE; in cifs_setup_cifs_sb()
3942 if (pvolume_info->nostrictsync) in cifs_setup_cifs_sb()
3943 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; in cifs_setup_cifs_sb()
3944 if (pvolume_info->mand_lock) in cifs_setup_cifs_sb()
3945 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; in cifs_setup_cifs_sb()
3946 if (pvolume_info->rwpidforward) in cifs_setup_cifs_sb()
3947 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; in cifs_setup_cifs_sb()
3948 if (pvolume_info->mode_ace) in cifs_setup_cifs_sb()
3949 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID; in cifs_setup_cifs_sb()
3950 if (pvolume_info->cifs_acl) in cifs_setup_cifs_sb()
3951 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; in cifs_setup_cifs_sb()
3952 if (pvolume_info->backupuid_specified) { in cifs_setup_cifs_sb()
3953 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; in cifs_setup_cifs_sb()
3954 cifs_sb->mnt_backupuid = pvolume_info->backupuid; in cifs_setup_cifs_sb()
3956 if (pvolume_info->backupgid_specified) { in cifs_setup_cifs_sb()
3957 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; in cifs_setup_cifs_sb()
3958 cifs_sb->mnt_backupgid = pvolume_info->backupgid; in cifs_setup_cifs_sb()
3960 if (pvolume_info->override_uid) in cifs_setup_cifs_sb()
3961 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; in cifs_setup_cifs_sb()
3962 if (pvolume_info->override_gid) in cifs_setup_cifs_sb()
3963 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; in cifs_setup_cifs_sb()
3964 if (pvolume_info->dynperm) in cifs_setup_cifs_sb()
3965 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; in cifs_setup_cifs_sb()
3966 if (pvolume_info->fsc) in cifs_setup_cifs_sb()
3967 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE; in cifs_setup_cifs_sb()
3968 if (pvolume_info->multiuser) in cifs_setup_cifs_sb()
3969 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | in cifs_setup_cifs_sb()
3971 if (pvolume_info->strict_io) in cifs_setup_cifs_sb()
3972 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; in cifs_setup_cifs_sb()
3973 if (pvolume_info->direct_io) { in cifs_setup_cifs_sb()
3975 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; in cifs_setup_cifs_sb()
3977 if (pvolume_info->cache_ro) { in cifs_setup_cifs_sb()
3979 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; in cifs_setup_cifs_sb()
3980 } else if (pvolume_info->cache_rw) { in cifs_setup_cifs_sb()
3982 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE | in cifs_setup_cifs_sb()
3985 if (pvolume_info->mfsymlinks) { in cifs_setup_cifs_sb()
3986 if (pvolume_info->sfu_emul) { in cifs_setup_cifs_sb()
4000 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; in cifs_setup_cifs_sb()
4003 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) in cifs_setup_cifs_sb()
4006 if (pvolume_info->prepath) { in cifs_setup_cifs_sb()
4007 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL); in cifs_setup_cifs_sb()
4008 if (cifs_sb->prepath == NULL) in cifs_setup_cifs_sb()
4009 return -ENOMEM; in cifs_setup_cifs_sb()
4018 kfree(volume_info->username); in cifs_cleanup_volume_info_contents()
4019 kfree_sensitive(volume_info->password); in cifs_cleanup_volume_info_contents()
4020 kfree(volume_info->UNC); in cifs_cleanup_volume_info_contents()
4021 kfree(volume_info->domainname); in cifs_cleanup_volume_info_contents()
4022 kfree(volume_info->iocharset); in cifs_cleanup_volume_info_contents()
4023 kfree(volume_info->prepath); in cifs_cleanup_volume_info_contents()
4039 struct cifs_ses *ses, struct cifs_tcon *tcon) in mount_put_conns() argument
4043 if (tcon) in mount_put_conns()
4044 cifs_put_tcon(tcon); in mount_put_conns()
4049 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS; in mount_put_conns()
4053 /* Get connections for tcp, ses and tcon */
4062 struct cifs_tcon *tcon; in mount_get_conns() local
4079 if ((vol->max_credits < 20) || (vol->max_credits > 60000)) in mount_get_conns()
4080 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE; in mount_get_conns()
4082 server->max_credits = vol->max_credits; in mount_get_conns()
4093 if ((vol->persistent == true) && (!(ses->server->capabilities & in mount_get_conns()
4096 return -EOPNOTSUPP; in mount_get_conns()
4099 /* search for existing tcon to this server share */ in mount_get_conns()
4100 tcon = cifs_get_tcon(ses, vol); in mount_get_conns()
4101 if (IS_ERR(tcon)) { in mount_get_conns()
4102 rc = PTR_ERR(tcon); in mount_get_conns()
4106 *ntcon = tcon; in mount_get_conns()
4109 if (tcon->posix_extensions) in mount_get_conns()
4110 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; in mount_get_conns()
4113 if (cap_unix(tcon->ses)) { in mount_get_conns()
4118 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol); in mount_get_conns()
4119 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && in mount_get_conns()
4120 (le64_to_cpu(tcon->fsUnixInfo.Capability) & in mount_get_conns()
4122 return -EACCES; in mount_get_conns()
4124 tcon->unix_ext = 0; /* server does not support them */ in mount_get_conns()
4126 /* do not care if a following call succeed - informational */ in mount_get_conns()
4127 if (!tcon->pipe && server->ops->qfs_tcon) { in mount_get_conns()
4128 server->ops->qfs_tcon(*xid, tcon, cifs_sb); in mount_get_conns()
4129 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { in mount_get_conns()
4130 if (tcon->fsDevInfo.DeviceCharacteristics & in mount_get_conns()
4133 else if ((cifs_sb->mnt_cifs_flags & in mount_get_conns()
4140 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol); in mount_get_conns()
4141 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol); in mount_get_conns()
4147 struct cifs_tcon *tcon) in mount_setup_tlink() argument
4151 /* hang the tcon off of the superblock */ in mount_setup_tlink()
4154 return -ENOMEM; in mount_setup_tlink()
4156 tlink->tl_uid = ses->linux_uid; in mount_setup_tlink()
4157 tlink->tl_tcon = tcon; in mount_setup_tlink()
4158 tlink->tl_time = jiffies; in mount_setup_tlink()
4159 set_bit(TCON_LINK_MASTER, &tlink->tl_flags); in mount_setup_tlink()
4160 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in mount_setup_tlink()
4162 cifs_sb->master_tlink = tlink; in mount_setup_tlink()
4163 spin_lock(&cifs_sb->tlink_tree_lock); in mount_setup_tlink()
4164 tlink_rb_insert(&cifs_sb->tlink_tree, tlink); in mount_setup_tlink()
4165 spin_unlock(&cifs_sb->tlink_tree_lock); in mount_setup_tlink()
4167 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, in mount_setup_tlink()
4175 * exiting connection (tcon)
4182 unsigned int pplen = useppath && vol->prepath ? in build_unc_path_to_root()
4183 strlen(vol->prepath) + 1 : 0; in build_unc_path_to_root()
4184 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); in build_unc_path_to_root()
4187 return ERR_PTR(-EINVAL); in build_unc_path_to_root()
4191 return ERR_PTR(-ENOMEM); in build_unc_path_to_root()
4193 memcpy(full_path, vol->UNC, unc_len); in build_unc_path_to_root()
4198 memcpy(pos + 1, vol->prepath, pplen); in build_unc_path_to_root()
4209 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4212 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4228 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) in expand_dfs_referral()
4229 return -EREMOTE; in expand_dfs_referral()
4235 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), in expand_dfs_referral()
4240 mdata = cifs_compose_mount_options(cifs_sb->mountdata, in expand_dfs_referral()
4254 kfree(cifs_sb->mountdata); in expand_dfs_referral()
4255 cifs_sb->mountdata = mdata; in expand_dfs_referral()
4269 return !*tgt_it ? -EHOSTDOWN : 0; in get_next_dfs_tgt()
4281 return -ENOMEM; in update_vol_info()
4284 kfree(vol->UNC); in update_vol_info()
4285 vol->UNC = new_unc; in update_vol_info()
4287 if (fake_vol->prepath) { in update_vol_info()
4288 kfree(vol->prepath); in update_vol_info()
4289 vol->prepath = fake_vol->prepath; in update_vol_info()
4290 fake_vol->prepath = NULL; in update_vol_info()
4292 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr)); in update_vol_info()
4301 struct cifs_tcon **tcon) in setup_dfs_tgt_conn() argument
4314 mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname); in setup_dfs_tgt_conn()
4334 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); in setup_dfs_tgt_conn()
4336 tcon); in setup_dfs_tgt_conn()
4352 struct cifs_tcon **tcon) in do_dfs_failover() argument
4358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) in do_dfs_failover()
4359 return -EOPNOTSUPP; in do_dfs_failover()
4366 /* Get next DFS target server - if any */ in do_dfs_failover()
4372 tcon); in do_dfs_failover()
4382 cifs_sb->local_nls, in do_dfs_failover()
4398 return -EINVAL; in cifs_setup_volume_info()
4400 if (volume_info->nullauth) { in cifs_setup_volume_info()
4402 kfree(volume_info->username); in cifs_setup_volume_info()
4403 volume_info->username = NULL; in cifs_setup_volume_info()
4404 } else if (volume_info->username) { in cifs_setup_volume_info()
4406 cifs_dbg(FYI, "Username: %s\n", volume_info->username); in cifs_setup_volume_info()
4411 return -EINVAL; in cifs_setup_volume_info()
4415 if (volume_info->iocharset == NULL) { in cifs_setup_volume_info()
4417 volume_info->local_nls = load_nls_default(); in cifs_setup_volume_info()
4419 volume_info->local_nls = load_nls(volume_info->iocharset); in cifs_setup_volume_info()
4420 if (volume_info->local_nls == NULL) { in cifs_setup_volume_info()
4422 volume_info->iocharset); in cifs_setup_volume_info()
4423 return -ELIBACC; in cifs_setup_volume_info()
4438 return ERR_PTR(-ENOMEM); in cifs_get_volume_info()
4452 struct cifs_tcon *tcon, in cifs_are_all_path_components_accessible() argument
4465 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, ""); in cifs_are_all_path_components_accessible()
4484 * temporarily null-terminate the path at the end of in cifs_are_all_path_components_accessible()
4489 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, in cifs_are_all_path_components_accessible()
4497 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4503 struct cifs_tcon *tcon) in is_path_remote() argument
4508 if (!server->ops->is_path_accessible) in is_path_remote()
4509 return -EOPNOTSUPP; in is_path_remote()
4512 * cifs_build_path_to_root works only when we have a valid tcon in is_path_remote()
4514 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon, in is_path_remote()
4515 tcon->Flags & SMB_SHARE_IS_IN_DFS); in is_path_remote()
4517 return -ENOMEM; in is_path_remote()
4521 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, in is_path_remote()
4523 if (rc != 0 && rc != -EREMOTE) { in is_path_remote()
4528 if (rc != -EREMOTE) { in is_path_remote()
4529 rc = cifs_are_all_path_components_accessible(server, xid, tcon, in is_path_remote()
4530 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); in is_path_remote()
4533 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; in is_path_remote()
4548 ses->ses_count++; in set_root_ses()
4549 if (ses->tcon_ipc) in set_root_ses()
4550 ses->tcon_ipc->remap = cifs_remap(cifs_sb); in set_root_ses()
4565 struct cifs_tcon *tcon, char **dfs_path) in check_dfs_prepath() argument
4571 int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS; in check_dfs_prepath()
4574 path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename); in check_dfs_prepath()
4576 return -ENOMEM; in check_dfs_prepath()
4580 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path in check_dfs_prepath()
4603 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path); in check_dfs_prepath()
4604 if (rc && rc == -EREMOTE) { in check_dfs_prepath()
4611 rc = -EREMOTE; in check_dfs_prepath()
4615 v.UNC = vol->UNC; in check_dfs_prepath()
4639 struct cifs_tcon *tcon = NULL; in cifs_mount() local
4645 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); in cifs_mount()
4653 if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL, in cifs_mount()
4659 rc = is_path_remote(cifs_sb, vol, xid, server, tcon); in cifs_mount()
4662 if (rc != -EREMOTE) in cifs_mount()
4666 mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL); in cifs_mount()
4668 rc = -ENOMEM; in cifs_mount()
4690 oldmnt = cifs_sb->mountdata; in cifs_mount()
4695 if (oldmnt != cifs_sb->mountdata) { in cifs_mount()
4696 mount_put_conns(cifs_sb, xid, server, ses, tcon); in cifs_mount()
4697 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); in cifs_mount()
4702 &server, &ses, &tcon); in cifs_mount()
4704 if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses) in cifs_mount()
4706 if (!tcon) in cifs_mount()
4709 if (is_tcon_dfs(tcon)) { in cifs_mount()
4713 /* Check for remaining path components and then continue chasing them (-EREMOTE) */ in cifs_mount()
4714 rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path); in cifs_mount()
4716 if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) in cifs_mount()
4717 rc = -ELOOP; in cifs_mount()
4718 } while (rc == -EREMOTE); in cifs_mount()
4729 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so in cifs_mount()
4730 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS in cifs_mount()
4734 cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL); in cifs_mount()
4735 if (!cifs_sb->origin_fullpath) { in cifs_mount()
4736 rc = -ENOMEM; in cifs_mount()
4740 tcon->dfs_path = full_path; in cifs_mount()
4742 tcon->remap = cifs_remap(cifs_sb); in cifs_mount()
4746 rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath); in cifs_mount()
4759 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; in cifs_mount()
4760 kfree(cifs_sb->prepath); in cifs_mount()
4761 cifs_sb->prepath = vol->prepath; in cifs_mount()
4762 vol->prepath = NULL; in cifs_mount()
4767 return mount_setup_tlink(cifs_sb, ses, tcon); in cifs_mount()
4773 kfree(cifs_sb->origin_fullpath); in cifs_mount()
4775 mount_put_conns(cifs_sb, xid, server, ses, tcon); in cifs_mount()
4784 struct cifs_tcon *tcon; in cifs_mount() local
4787 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); in cifs_mount()
4791 if (tcon) { in cifs_mount()
4792 rc = is_path_remote(cifs_sb, vol, xid, server, tcon); in cifs_mount()
4793 if (rc == -EREMOTE) in cifs_mount()
4794 rc = -EOPNOTSUPP; in cifs_mount()
4801 return mount_setup_tlink(cifs_sb, ses, tcon); in cifs_mount()
4804 mount_put_conns(cifs_sb, xid, server, ses, tcon); in cifs_mount()
4814 const char *tree, struct cifs_tcon *tcon, in CIFSTCon() argument
4827 return -EIO; in CIFSTCon()
4831 return -ENOMEM; in CIFSTCon()
4838 smb_buffer->Mid = get_next_mid(ses->server); in CIFSTCon()
4839 smb_buffer->Uid = ses->Suid; in CIFSTCon()
4843 pSMB->AndXCommand = 0xFF; in CIFSTCon()
4844 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); in CIFSTCon()
4845 bcc_ptr = &pSMB->Password[0]; in CIFSTCon()
4846 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) { in CIFSTCon()
4847 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ in CIFSTCon()
4852 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); in CIFSTCon()
4861 (ses->sectype == LANMAN)) in CIFSTCon()
4862 calc_lanman_hash(tcon->password, ses->server->cryptkey, in CIFSTCon()
4863 ses->server->sec_mode & in CIFSTCon()
4868 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, in CIFSTCon()
4878 if (ses->capabilities & CAP_UNICODE) { in CIFSTCon()
4885 if (ses->server->sign) in CIFSTCon()
4886 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; in CIFSTCon()
4888 if (ses->capabilities & CAP_STATUS32) { in CIFSTCon()
4889 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; in CIFSTCon()
4891 if (ses->capabilities & CAP_DFS) { in CIFSTCon()
4892 smb_buffer->Flags2 |= SMBFLG2_DFS; in CIFSTCon()
4894 if (ses->capabilities & CAP_UNICODE) { in CIFSTCon()
4895 smb_buffer->Flags2 |= SMBFLG2_UNICODE; in CIFSTCon()
4909 count = bcc_ptr - &pSMB->Password[0]; in CIFSTCon()
4910 be32_add_cpu(&pSMB->hdr.smb_buf_length, count); in CIFSTCon()
4911 pSMB->ByteCount = cpu_to_le16(count); in CIFSTCon()
4920 tcon->tidStatus = CifsGood; in CIFSTCon()
4921 tcon->need_reconnect = false; in CIFSTCon()
4922 tcon->tid = smb_buffer_response->Tid; in CIFSTCon()
4925 length = strnlen(bcc_ptr, bytes_left - 2); in CIFSTCon()
4926 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) in CIFSTCon()
4937 tcon->ipc = true; in CIFSTCon()
4938 tcon->pipe = true; in CIFSTCon()
4947 bytes_left -= (length + 1); in CIFSTCon()
4948 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); in CIFSTCon()
4950 /* mostly informational -- no need to fail on error here */ in CIFSTCon()
4951 kfree(tcon->nativeFileSystem); in CIFSTCon()
4952 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, in CIFSTCon()
4956 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem); in CIFSTCon()
4958 if ((smb_buffer_response->WordCount == 3) || in CIFSTCon()
4959 (smb_buffer_response->WordCount == 7)) in CIFSTCon()
4961 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); in CIFSTCon()
4963 tcon->Flags = 0; in CIFSTCon()
4964 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags); in CIFSTCon()
4974 unload_nls(sbi->local_nls); in delayed_free()
4981 struct rb_root *root = &cifs_sb->tlink_tree; in cifs_umount()
4985 cancel_delayed_work_sync(&cifs_sb->prune_tlinks); in cifs_umount()
4987 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_umount()
4991 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in cifs_umount()
4994 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_umount()
4996 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_umount()
4998 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_umount()
5000 kfree(cifs_sb->mountdata); in cifs_umount()
5001 kfree(cifs_sb->prepath); in cifs_umount()
5003 dfs_cache_del_vol(cifs_sb->origin_fullpath); in cifs_umount()
5004 kfree(cifs_sb->origin_fullpath); in cifs_umount()
5006 call_rcu(&cifs_sb->rcu, delayed_free); in cifs_umount()
5015 if (!server->ops->need_neg || !server->ops->negotiate) in cifs_negotiate_protocol()
5016 return -ENOSYS; in cifs_negotiate_protocol()
5019 if (!server->ops->need_neg(server)) in cifs_negotiate_protocol()
5022 rc = server->ops->negotiate(xid, ses); in cifs_negotiate_protocol()
5025 if (server->tcpStatus == CifsNeedNegotiate) in cifs_negotiate_protocol()
5026 server->tcpStatus = CifsGood; in cifs_negotiate_protocol()
5028 rc = -EHOSTDOWN; in cifs_negotiate_protocol()
5039 int rc = -ENOSYS; in cifs_setup_session()
5042 if (!ses->binding) { in cifs_setup_session()
5043 ses->capabilities = server->capabilities; in cifs_setup_session()
5045 ses->capabilities &= (~server->vals->cap_unix); in cifs_setup_session()
5047 if (ses->auth_key.response) { in cifs_setup_session()
5049 ses->auth_key.response); in cifs_setup_session()
5050 kfree(ses->auth_key.response); in cifs_setup_session()
5051 ses->auth_key.response = NULL; in cifs_setup_session()
5052 ses->auth_key.len = 0; in cifs_setup_session()
5057 server->sec_mode, server->capabilities, server->timeAdj); in cifs_setup_session()
5059 if (server->ops->sess_setup) in cifs_setup_session()
5060 rc = server->ops->sess_setup(xid, ses, nls_info); in cifs_setup_session()
5071 vol->sectype = ses->sectype; in cifs_set_vol_auth()
5074 if (vol->sectype == Kerberos) in cifs_set_vol_auth()
5086 struct cifs_tcon *tcon = NULL; in cifs_construct_tcon() local
5091 return ERR_PTR(-ENOMEM); in cifs_construct_tcon()
5093 vol_info->local_nls = cifs_sb->local_nls; in cifs_construct_tcon()
5094 vol_info->linux_uid = fsuid; in cifs_construct_tcon()
5095 vol_info->cred_uid = fsuid; in cifs_construct_tcon()
5096 vol_info->UNC = master_tcon->treeName; in cifs_construct_tcon()
5097 vol_info->retry = master_tcon->retry; in cifs_construct_tcon()
5098 vol_info->nocase = master_tcon->nocase; in cifs_construct_tcon()
5099 vol_info->nohandlecache = master_tcon->nohandlecache; in cifs_construct_tcon()
5100 vol_info->local_lease = master_tcon->local_lease; in cifs_construct_tcon()
5101 vol_info->no_lease = master_tcon->no_lease; in cifs_construct_tcon()
5102 vol_info->resilient = master_tcon->use_resilient; in cifs_construct_tcon()
5103 vol_info->persistent = master_tcon->use_persistent; in cifs_construct_tcon()
5104 vol_info->handle_timeout = master_tcon->handle_timeout; in cifs_construct_tcon()
5105 vol_info->no_linux_ext = !master_tcon->unix_ext; in cifs_construct_tcon()
5106 vol_info->linux_ext = master_tcon->posix_extensions; in cifs_construct_tcon()
5107 vol_info->sectype = master_tcon->ses->sectype; in cifs_construct_tcon()
5108 vol_info->sign = master_tcon->ses->sign; in cifs_construct_tcon()
5109 vol_info->seal = master_tcon->seal; in cifs_construct_tcon()
5111 rc = cifs_set_vol_auth(vol_info, master_tcon->ses); in cifs_construct_tcon()
5113 tcon = ERR_PTR(rc); in cifs_construct_tcon()
5119 ++master_tcon->ses->server->srv_count; in cifs_construct_tcon()
5122 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info); in cifs_construct_tcon()
5124 tcon = (struct cifs_tcon *)ses; in cifs_construct_tcon()
5125 cifs_put_tcp_session(master_tcon->ses->server, 0); in cifs_construct_tcon()
5129 tcon = cifs_get_tcon(ses, vol_info); in cifs_construct_tcon()
5130 if (IS_ERR(tcon)) { in cifs_construct_tcon()
5136 reset_cifs_unix_caps(0, tcon, NULL, vol_info); in cifs_construct_tcon()
5139 kfree(vol_info->username); in cifs_construct_tcon()
5140 kfree_sensitive(vol_info->password); in cifs_construct_tcon()
5143 return tcon; in cifs_construct_tcon()
5156 struct rb_node *node = root->rb_node; in tlink_rb_search()
5162 if (uid_gt(tlink->tl_uid, uid)) in tlink_rb_search()
5163 node = node->rb_left; in tlink_rb_search()
5164 else if (uid_lt(tlink->tl_uid, uid)) in tlink_rb_search()
5165 node = node->rb_right; in tlink_rb_search()
5176 struct rb_node **new = &(root->rb_node), *parent = NULL; in tlink_rb_insert()
5183 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid)) in tlink_rb_insert()
5184 new = &((*new)->rb_left); in tlink_rb_insert()
5186 new = &((*new)->rb_right); in tlink_rb_insert()
5189 rb_link_node(&new_tlink->tl_rbnode, parent, new); in tlink_rb_insert()
5190 rb_insert_color(&new_tlink->tl_rbnode, root); in tlink_rb_insert()
5194 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5198 * the master tcon for the mount.
5200 * First, search the rbtree for an existing tcon for this fsuid. If one
5216 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) in cifs_sb_tlink()
5219 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
5220 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); in cifs_sb_tlink()
5223 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
5228 return ERR_PTR(-ENOMEM); in cifs_sb_tlink()
5229 newtlink->tl_uid = fsuid; in cifs_sb_tlink()
5230 newtlink->tl_tcon = ERR_PTR(-EACCES); in cifs_sb_tlink()
5231 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags); in cifs_sb_tlink()
5232 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags); in cifs_sb_tlink()
5235 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
5237 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); in cifs_sb_tlink()
5240 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
5245 tlink_rb_insert(&cifs_sb->tlink_tree, tlink); in cifs_sb_tlink()
5246 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_sb_tlink()
5249 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, in cifs_sb_tlink()
5253 return ERR_PTR(-ERESTARTSYS); in cifs_sb_tlink()
5257 if (!IS_ERR(tlink->tl_tcon)) in cifs_sb_tlink()
5261 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) { in cifs_sb_tlink()
5263 return ERR_PTR(-EACCES); in cifs_sb_tlink()
5266 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags)) in cifs_sb_tlink()
5270 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid); in cifs_sb_tlink()
5271 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags); in cifs_sb_tlink()
5272 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING); in cifs_sb_tlink()
5274 if (IS_ERR(tlink->tl_tcon)) { in cifs_sb_tlink()
5276 return ERR_PTR(-EACCES); in cifs_sb_tlink()
5291 struct rb_root *root = &cifs_sb->tlink_tree; in cifs_prune_tlinks()
5300 * umounts. Because this function is non-reentrant and is canceled in cifs_prune_tlinks()
5303 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
5310 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) || in cifs_prune_tlinks()
5311 atomic_read(&tlink->tl_count) != 0 || in cifs_prune_tlinks()
5312 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies)) in cifs_prune_tlinks()
5316 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); in cifs_prune_tlinks()
5319 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
5321 spin_lock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
5323 spin_unlock(&cifs_sb->tlink_tree_lock); in cifs_prune_tlinks()
5325 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, in cifs_prune_tlinks()
5330 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) in cifs_tree_connect() argument
5333 struct TCP_Server_Info *server = tcon->ses->server; in cifs_tree_connect()
5334 const struct smb_version_operations *ops = server->ops; in cifs_tree_connect()
5348 return -ENOMEM; in cifs_tree_connect()
5350 if (!tcon->dfs_path) { in cifs_tree_connect()
5351 if (tcon->ipc) { in cifs_tree_connect()
5352 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); in cifs_tree_connect()
5353 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); in cifs_tree_connect()
5355 rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); in cifs_tree_connect()
5360 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl); in cifs_tree_connect()
5366 extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); in cifs_tree_connect()
5376 rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix); in cifs_tree_connect()
5402 if (tcon->ipc) { in cifs_tree_connect()
5404 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); in cifs_tree_connect()
5407 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); in cifs_tree_connect()
5410 rc = update_super_prepath(tcon, prefix); in cifs_tree_connect()
5414 if (rc == -EREMOTE) in cifs_tree_connect()
5423 rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it); in cifs_tree_connect()
5425 rc = -ENOENT; in cifs_tree_connect()
5433 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) in cifs_tree_connect() argument
5435 const struct smb_version_operations *ops = tcon->ses->server->ops; in cifs_tree_connect()
5437 return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); in cifs_tree_connect()