diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8463c940e0e5..b95db2b593cb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -102,7 +102,7 @@ enum { | |||
102 | Opt_backupuid, Opt_backupgid, Opt_uid, | 102 | Opt_backupuid, Opt_backupgid, Opt_uid, |
103 | Opt_cruid, Opt_gid, Opt_file_mode, | 103 | Opt_cruid, Opt_gid, Opt_file_mode, |
104 | Opt_dirmode, Opt_port, | 104 | Opt_dirmode, Opt_port, |
105 | Opt_rsize, Opt_wsize, Opt_actimeo, | 105 | Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, |
106 | Opt_echo_interval, Opt_max_credits, | 106 | Opt_echo_interval, Opt_max_credits, |
107 | Opt_snapshot, | 107 | Opt_snapshot, |
108 | 108 | ||
@@ -204,6 +204,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
204 | { Opt_dirmode, "dirmode=%s" }, | 204 | { Opt_dirmode, "dirmode=%s" }, |
205 | { Opt_dirmode, "dir_mode=%s" }, | 205 | { Opt_dirmode, "dir_mode=%s" }, |
206 | { Opt_port, "port=%s" }, | 206 | { Opt_port, "port=%s" }, |
207 | { Opt_blocksize, "bsize=%s" }, | ||
207 | { Opt_rsize, "rsize=%s" }, | 208 | { Opt_rsize, "rsize=%s" }, |
208 | { Opt_wsize, "wsize=%s" }, | 209 | { Opt_wsize, "wsize=%s" }, |
209 | { Opt_actimeo, "actimeo=%s" }, | 210 | { Opt_actimeo, "actimeo=%s" }, |
@@ -348,7 +349,7 @@ static int reconn_set_ipaddr(struct TCP_Server_Info *server) | |||
348 | cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); | 349 | cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); |
349 | return -ENOMEM; | 350 | return -ENOMEM; |
350 | } | 351 | } |
351 | snprintf(unc, len, "\\\\%s", server->hostname); | 352 | scnprintf(unc, len, "\\\\%s", server->hostname); |
352 | 353 | ||
353 | rc = dns_resolve_server_name_to_ip(unc, &ipaddr); | 354 | rc = dns_resolve_server_name_to_ip(unc, &ipaddr); |
354 | kfree(unc); | 355 | kfree(unc); |
@@ -592,6 +593,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
592 | msleep(3000); | 593 | msleep(3000); |
593 | } else { | 594 | } else { |
594 | atomic_inc(&tcpSesReconnectCount); | 595 | atomic_inc(&tcpSesReconnectCount); |
596 | set_credits(server, 1); | ||
595 | spin_lock(&GlobalMid_Lock); | 597 | spin_lock(&GlobalMid_Lock); |
596 | if (server->tcpStatus != CifsExiting) | 598 | if (server->tcpStatus != CifsExiting) |
597 | server->tcpStatus = CifsNeedNegotiate; | 599 | server->tcpStatus = CifsNeedNegotiate; |
@@ -1053,7 +1055,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1053 | } | 1055 | } |
1054 | 1056 | ||
1055 | if (server->ops->is_status_pending && | 1057 | if (server->ops->is_status_pending && |
1056 | server->ops->is_status_pending(buf, server, length)) | 1058 | server->ops->is_status_pending(buf, server)) |
1057 | return -1; | 1059 | return -1; |
1058 | 1060 | ||
1059 | if (!mid) | 1061 | if (!mid) |
@@ -1063,6 +1065,26 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1063 | return 0; | 1065 | return 0; |
1064 | } | 1066 | } |
1065 | 1067 | ||
1068 | static void | ||
1069 | smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) | ||
1070 | { | ||
1071 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; | ||
1072 | |||
1073 | /* | ||
1074 | * SMB1 does not use credits. | ||
1075 | */ | ||
1076 | if (server->vals->header_preamble_size) | ||
1077 | return; | ||
1078 | |||
1079 | if (shdr->CreditRequest) { | ||
1080 | spin_lock(&server->req_lock); | ||
1081 | server->credits += le16_to_cpu(shdr->CreditRequest); | ||
1082 | spin_unlock(&server->req_lock); | ||
1083 | wake_up(&server->request_q); | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | |||
1066 | static int | 1088 | static int |
1067 | cifs_demultiplex_thread(void *p) | 1089 | cifs_demultiplex_thread(void *p) |
1068 | { | 1090 | { |
@@ -1192,6 +1214,7 @@ next_pdu: | |||
1192 | } else if (server->ops->is_oplock_break && | 1214 | } else if (server->ops->is_oplock_break && |
1193 | server->ops->is_oplock_break(bufs[i], | 1215 | server->ops->is_oplock_break(bufs[i], |
1194 | server)) { | 1216 | server)) { |
1217 | smb2_add_credits_from_hdr(bufs[i], server); | ||
1195 | cifs_dbg(FYI, "Received oplock break\n"); | 1218 | cifs_dbg(FYI, "Received oplock break\n"); |
1196 | } else { | 1219 | } else { |
1197 | cifs_dbg(VFS, "No task to wake, unknown frame " | 1220 | cifs_dbg(VFS, "No task to wake, unknown frame " |
@@ -1203,6 +1226,7 @@ next_pdu: | |||
1203 | if (server->ops->dump_detail) | 1226 | if (server->ops->dump_detail) |
1204 | server->ops->dump_detail(bufs[i], | 1227 | server->ops->dump_detail(bufs[i], |
1205 | server); | 1228 | server); |
1229 | smb2_add_credits_from_hdr(bufs[i], server); | ||
1206 | cifs_dump_mids(server); | 1230 | cifs_dump_mids(server); |
1207 | #endif /* CIFS_DEBUG2 */ | 1231 | #endif /* CIFS_DEBUG2 */ |
1208 | } | 1232 | } |
@@ -1486,6 +1510,11 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) | |||
1486 | const char *delims = "/\\"; | 1510 | const char *delims = "/\\"; |
1487 | size_t len; | 1511 | size_t len; |
1488 | 1512 | ||
1513 | if (unlikely(!devname || !*devname)) { | ||
1514 | cifs_dbg(VFS, "Device name not specified.\n"); | ||
1515 | return -EINVAL; | ||
1516 | } | ||
1517 | |||
1489 | /* make sure we have a valid UNC double delimiter prefix */ | 1518 | /* make sure we have a valid UNC double delimiter prefix */ |
1490 | len = strspn(devname, delims); | 1519 | len = strspn(devname, delims); |
1491 | if (len != 2) | 1520 | if (len != 2) |
@@ -1571,7 +1600,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1571 | vol->cred_uid = current_uid(); | 1600 | vol->cred_uid = current_uid(); |
1572 | vol->linux_uid = current_uid(); | 1601 | vol->linux_uid = current_uid(); |
1573 | vol->linux_gid = current_gid(); | 1602 | vol->linux_gid = current_gid(); |
1574 | 1603 | vol->bsize = 1024 * 1024; /* can improve cp performance significantly */ | |
1575 | /* | 1604 | /* |
1576 | * default to SFM style remapping of seven reserved characters | 1605 | * default to SFM style remapping of seven reserved characters |
1577 | * unless user overrides it or we negotiate CIFS POSIX where | 1606 | * unless user overrides it or we negotiate CIFS POSIX where |
@@ -1944,6 +1973,26 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1944 | } | 1973 | } |
1945 | port = (unsigned short)option; | 1974 | port = (unsigned short)option; |
1946 | break; | 1975 | break; |
1976 | case Opt_blocksize: | ||
1977 | if (get_option_ul(args, &option)) { | ||
1978 | cifs_dbg(VFS, "%s: Invalid blocksize value\n", | ||
1979 | __func__); | ||
1980 | goto cifs_parse_mount_err; | ||
1981 | } | ||
1982 | /* | ||
1983 | * inode blocksize realistically should never need to be | ||
1984 | * less than 16K or greater than 16M and default is 1MB. | ||
1985 | * Note that small inode block sizes (e.g. 64K) can lead | ||
1986 | * to very poor performance of common tools like cp and scp | ||
1987 | */ | ||
1988 | if ((option < CIFS_MAX_MSGSIZE) || | ||
1989 | (option > (4 * SMB3_DEFAULT_IOSIZE))) { | ||
1990 | cifs_dbg(VFS, "%s: Invalid blocksize\n", | ||
1991 | __func__); | ||
1992 | goto cifs_parse_mount_err; | ||
1993 | } | ||
1994 | vol->bsize = option; | ||
1995 | break; | ||
1947 | case Opt_rsize: | 1996 | case Opt_rsize: |
1948 | if (get_option_ul(args, &option)) { | 1997 | if (get_option_ul(args, &option)) { |
1949 | cifs_dbg(VFS, "%s: Invalid rsize value\n", | 1998 | cifs_dbg(VFS, "%s: Invalid rsize value\n", |
@@ -2609,7 +2658,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2609 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); | 2658 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); |
2610 | tcp_ses->session_estab = false; | 2659 | tcp_ses->session_estab = false; |
2611 | tcp_ses->sequence_number = 0; | 2660 | tcp_ses->sequence_number = 0; |
2612 | tcp_ses->reconnect_instance = 0; | 2661 | tcp_ses->reconnect_instance = 1; |
2613 | tcp_ses->lstrp = jiffies; | 2662 | tcp_ses->lstrp = jiffies; |
2614 | spin_lock_init(&tcp_ses->req_lock); | 2663 | spin_lock_init(&tcp_ses->req_lock); |
2615 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); | 2664 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
@@ -2770,7 +2819,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2770 | if (tcon == NULL) | 2819 | if (tcon == NULL) |
2771 | return -ENOMEM; | 2820 | return -ENOMEM; |
2772 | 2821 | ||
2773 | snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname); | 2822 | scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname); |
2774 | 2823 | ||
2775 | /* cannot fail */ | 2824 | /* cannot fail */ |
2776 | nls_codepage = load_nls_default(); | 2825 | nls_codepage = load_nls_default(); |
@@ -3839,6 +3888,7 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
3839 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 3888 | spin_lock_init(&cifs_sb->tlink_tree_lock); |
3840 | cifs_sb->tlink_tree = RB_ROOT; | 3889 | cifs_sb->tlink_tree = RB_ROOT; |
3841 | 3890 | ||
3891 | cifs_sb->bsize = pvolume_info->bsize; | ||
3842 | /* | 3892 | /* |
3843 | * Temporarily set r/wsize for matching superblock. If we end up using | 3893 | * Temporarily set r/wsize for matching superblock. If we end up using |
3844 | * new sb then client will later negotiate it downward if needed. | 3894 | * new sb then client will later negotiate it downward if needed. |
@@ -4198,7 +4248,7 @@ static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it, | |||
4198 | new_unc = kmalloc(len, GFP_KERNEL); | 4248 | new_unc = kmalloc(len, GFP_KERNEL); |
4199 | if (!new_unc) | 4249 | if (!new_unc) |
4200 | return -ENOMEM; | 4250 | return -ENOMEM; |
4201 | snprintf(new_unc, len, "\\%s", tgt); | 4251 | scnprintf(new_unc, len, "\\%s", tgt); |
4202 | 4252 | ||
4203 | kfree(vol->UNC); | 4253 | kfree(vol->UNC); |
4204 | vol->UNC = new_unc; | 4254 | vol->UNC = new_unc; |
@@ -4902,8 +4952,6 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses) | |||
4902 | if (!server->ops->need_neg(server)) | 4952 | if (!server->ops->need_neg(server)) |
4903 | return 0; | 4953 | return 0; |
4904 | 4954 | ||
4905 | set_credits(server, 1); | ||
4906 | |||
4907 | rc = server->ops->negotiate(xid, ses); | 4955 | rc = server->ops->negotiate(xid, ses); |
4908 | if (rc == 0) { | 4956 | if (rc == 0) { |
4909 | spin_lock(&GlobalMid_Lock); | 4957 | spin_lock(&GlobalMid_Lock); |