X-Git-Url: http://git.monstr.eu/?a=blobdiff_plain;f=fs%2Fcifs%2Fsmb2pdu.c;h=3f5c3dd57c86c1096741d8eedf861df58d57d9bf;hb=b1bc1874b885683df5da9d9548ca66dfc0e407f2;hp=b30aa3cdd845f333304de9fcbdc95f1ae3ec5e99;hpb=729ea4e064202aeec149b034b459501ef0a5060e;p=linux-2.6-microblaze.git diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index b30aa3cdd845..3f5c3dd57c86 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -85,7 +85,7 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { int smb3_encryption_required(const struct cifs_tcon *tcon) { - if (!tcon) + if (!tcon || !tcon->ses) return 0; if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) @@ -98,14 +98,13 @@ int smb3_encryption_required(const struct cifs_tcon *tcon) static void smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, - const struct cifs_tcon *tcon) + const struct cifs_tcon *tcon, + struct TCP_Server_Info *server) { shdr->ProtocolId = SMB2_PROTO_NUMBER; shdr->StructureSize = cpu_to_le16(64); shdr->Command = smb2_cmd; - if (tcon && tcon->ses && tcon->ses->server) { - struct TCP_Server_Info *server = tcon->ses->server; - + if (server) { spin_lock(&server->req_lock); /* Request up to 10 credits but don't go over the limit. */ if (server->credits >= server->max_credits) @@ -125,8 +124,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ - if ((tcon->ses) && (tcon->ses->server) && - (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) shdr->CreditCharge = cpu_to_le16(1); /* else CreditCharge MBZ */ @@ -148,8 +146,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, /* if (tcon->share_flags & SHI1005_FLAGS_DFS) shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ - if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && - !smb3_encryption_required(tcon)) + if (server && server->sign && !smb3_encryption_required(tcon)) shdr->Flags |= SMB2_FLAGS_SIGNED; out: return; @@ -160,6 +157,7 @@ static int __smb2_reconnect(const struct nls_table *nlsc, struct cifs_tcon *tcon) { int rc; + struct TCP_Server_Info *server = tcon->ses->server; struct dfs_cache_tgt_list tl; struct dfs_cache_tgt_iterator *it = NULL; char *tree; @@ -172,15 +170,15 @@ static int __smb2_reconnect(const struct nls_table *nlsc, if (!tree) return -ENOMEM; - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", - tcon->ses->server->hostname); - rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); - goto out; - } - if (!tcon->dfs_path) { - rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc); + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", + server->hostname); + rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); + } else { + rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, + nlsc); + } goto out; } @@ -188,13 +186,13 @@ static int __smb2_reconnect(const struct nls_table *nlsc, if (rc) goto out; - extract_unc_hostname(tcon->ses->server->hostname, &tcp_host, - &tcp_host_len); + extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) { const char *share, *prefix; size_t share_len, prefix_len; + bool target_match; rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, &prefix_len); @@ -208,19 +206,38 @@ static int __smb2_reconnect(const struct nls_table *nlsc, if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { - cifs_dbg(FYI, "%s: skipping %.*s, doesn't match %.*s", + cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, dfs_host, (int)tcp_host_len, tcp_host); - continue; - } - scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, share); + rc = match_target_ip(server, dfs_host, dfs_host_len, + &target_match); + if (rc) { + cifs_dbg(VFS, "%s: failed to match target ip: %d\n", + __func__, rc); + break; + } - rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); - if (!rc) { - rc = update_super_prepath(tcon, prefix, prefix_len); - break; + if (!target_match) { + cifs_dbg(FYI, "%s: skipping target\n", __func__); + continue; + } + } + + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$", + (int)share_len, share); + rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); + } else { + scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, + share); + rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); + if (!rc) { + rc = update_super_prepath(tcon, prefix, + prefix_len); + break; + } } if (rc == -EREMOTE) break; @@ -247,12 +264,12 @@ static inline int __smb2_reconnect(const struct nls_table *nlsc, #endif static int -smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) +smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server) { int rc; struct nls_table *nls_codepage; struct cifs_ses *ses; - struct TCP_Server_Info *server; int retries; /* @@ -281,12 +298,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) } } if ((!tcon->ses) || (tcon->ses->status == CifsExiting) || - (!tcon->ses->server)) + (!tcon->ses->server) || !server) return -EIO; ses = tcon->ses; - server = ses->server; - retries = server->nr_targets; /* @@ -314,8 +329,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) (server->tcpStatus != CifsNeedReconnect), 10 * HZ); if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to a received" - " signal by the process\n", __func__); + cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n", + __func__); return -ERESTARTSYS; } @@ -360,15 +375,31 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) goto out; } + /* + * If we are reconnecting an extra channel, bind + */ + if (server->is_channel) { + ses->binding = true; + ses->binding_chan = cifs_ses_find_chan(ses, server); + } + rc = cifs_negotiate_protocol(0, tcon->ses); if (!rc && tcon->ses->need_reconnect) { rc = cifs_setup_session(0, tcon->ses, nls_codepage); if ((rc == -EACCES) && !tcon->retry) { rc = -EHOSTDOWN; + ses->binding = false; + ses->binding_chan = NULL; mutex_unlock(&tcon->ses->session_mutex); goto failed; } } + /* + * End of channel binding + */ + ses->binding = false; + ses->binding_chan = NULL; + if (rc || !tcon->need_reconnect) { mutex_unlock(&tcon->ses->session_mutex); goto out; @@ -384,7 +415,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); if (rc) { /* If sess reconnected but tcon didn't, something strange ... */ - printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc); + pr_warn_once("reconnect tcon failed rc = %d\n", rc); goto out; } @@ -419,7 +450,9 @@ failed: } static void -fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, +fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, + void *buf, unsigned int *total_len) { struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; @@ -432,7 +465,7 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, */ memset(buf, 0, 256); - smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon); + smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon, server); spdu->StructureSize2 = cpu_to_le16(parmsize); *total_len = parmsize + sizeof(struct smb2_sync_hdr); @@ -444,7 +477,8 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, * function must have filled in request_buf pointer. */ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, - void **request_buf, unsigned int *total_len) + struct TCP_Server_Info *server, + void **request_buf, unsigned int *total_len) { /* BB eventually switch this to SMB2 specific small buf size */ if (smb2_command == SMB2_SET_INFO) @@ -456,7 +490,7 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, return -ENOMEM; } - fill_small_buf(smb2_command, tcon, + fill_small_buf(smb2_command, tcon, server, (struct smb2_sync_hdr *)(*request_buf), total_len); @@ -470,27 +504,30 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, } static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, void **request_buf, unsigned int *total_len) { int rc; - rc = smb2_reconnect(smb2_command, tcon); + rc = smb2_reconnect(smb2_command, tcon, server); if (rc) return rc; - return __smb2_plain_req_init(smb2_command, tcon, request_buf, + return __smb2_plain_req_init(smb2_command, tcon, server, request_buf, total_len); } static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, void **request_buf, unsigned int *total_len) { /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) { - return __smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, - total_len); + return __smb2_plain_req_init(SMB2_IOCTL, tcon, server, + request_buf, total_len); } - return smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, total_len); + return smb2_plain_req_init(SMB2_IOCTL, tcon, server, + request_buf, total_len); } /* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */ @@ -626,13 +663,13 @@ static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) /* If invalid preauth context warn but use what we requested, SHA-512 */ if (len < MIN_PREAUTH_CTXT_DATA_LEN) { - printk_once(KERN_WARNING "server sent bad preauth context\n"); + pr_warn_once("server sent bad preauth context\n"); return; } if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1) - printk_once(KERN_WARNING "illegal SMB3 hash algorithm count\n"); + pr_warn_once("Invalid SMB3 hash algorithm count\n"); if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) - printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n"); + pr_warn_once("unknown SMB3 hash algorithm\n"); } static void decode_compress_ctx(struct TCP_Server_Info *server, @@ -642,15 +679,15 @@ static void decode_compress_ctx(struct TCP_Server_Info *server, /* sizeof compress context is a one element compression capbility struct */ if (len < 10) { - printk_once(KERN_WARNING "server sent bad compression cntxt\n"); + pr_warn_once("server sent bad compression cntxt\n"); return; } if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) { - printk_once(KERN_WARNING "illegal SMB3 compress algorithm count\n"); + pr_warn_once("Invalid SMB3 compress algorithm count\n"); return; } if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) { - printk_once(KERN_WARNING "unknown compression algorithm\n"); + pr_warn_once("unknown compression algorithm\n"); return; } server->compress_algorithm = ctxt->CompressionAlgorithms[0]; @@ -663,18 +700,18 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server, cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len); if (len < MIN_ENCRYPT_CTXT_DATA_LEN) { - printk_once(KERN_WARNING "server sent bad crypto ctxt len\n"); + pr_warn_once("server sent bad crypto ctxt len\n"); return -EINVAL; } if (le16_to_cpu(ctxt->CipherCount) != 1) { - printk_once(KERN_WARNING "illegal SMB3.11 cipher count\n"); + pr_warn_once("Invalid SMB3.11 cipher count\n"); return -EINVAL; } cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0])); if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) && (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) { - printk_once(KERN_WARNING "invalid SMB3.11 cipher returned\n"); + pr_warn_once("Invalid SMB3.11 cipher returned\n"); return -EINVAL; } server->cipher_type = ctxt->Ciphers[0]; @@ -774,7 +811,7 @@ create_posix_buf(umode_t mode) buf->Name[14] = 0xCD; buf->Name[15] = 0x7C; buf->Mode = cpu_to_le32(mode); - cifs_dbg(FYI, "mode on posix create 0%o", mode); + cifs_dbg(FYI, "mode on posix create 0%o\n", mode); return buf; } @@ -786,7 +823,7 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) iov[num].iov_base = create_posix_buf(mode); if (mode == ACL_NO_MODE) - cifs_dbg(FYI, "illegal mode\n"); + cifs_dbg(FYI, "Invalid mode\n"); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_posix); @@ -838,7 +875,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) return -EIO; } - rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, + (void **) &req, &total_len); if (rc) return rc; @@ -896,7 +934,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base; /* @@ -904,9 +943,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); */ if (rc == -EOPNOTSUPP) { - cifs_server_dbg(VFS, "Dialect not supported by server. Consider " - "specifying vers=1.0 or vers=2.0 on mount for accessing" - " older servers\n"); + cifs_server_dbg(VFS, "Dialect not supported by server. Consider specifying vers=1.0 or vers=2.0 on mount for accessing older servers\n"); goto neg_exit; } else if (rc != 0) goto neg_exit; @@ -939,8 +976,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) } else if (le16_to_cpu(rsp->DialectRevision) != server->vals->protocol_id) { /* if requested single dialect ensure returned dialect matched */ - cifs_server_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", - le16_to_cpu(rsp->DialectRevision)); + cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n", + le16_to_cpu(rsp->DialectRevision)); return -EIO; } @@ -957,8 +994,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); else { - cifs_server_dbg(VFS, "Illegal dialect returned by server 0x%x\n", - le16_to_cpu(rsp->DialectRevision)); + cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n", + le16_to_cpu(rsp->DialectRevision)); rc = -EIO; goto neg_exit; } @@ -1116,15 +1153,16 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) rc = 0; goto out_free_inbuf; } else if (rc != 0) { - cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); + cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", + rc); rc = -EIO; goto out_free_inbuf; } rc = -EIO; if (rsplen != sizeof(*pneg_rsp)) { - cifs_tcon_dbg(VFS, "invalid protocol negotiate response size: %d\n", - rsplen); + cifs_tcon_dbg(VFS, "Invalid protocol negotiate response size: %d\n", + rsplen); /* relax check since Mac returns max bufsize allowed on ioctl */ if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp)) @@ -1208,8 +1246,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) struct TCP_Server_Info *server = cifs_ses_server(ses); unsigned int total_len; - rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, + (void **) &req, + &total_len); if (rc) return rc; @@ -1286,6 +1325,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) /* BB add code to build os and lm fields */ rc = cifs_send_recv(sess_data->xid, sess_data->ses, + cifs_ses_server(sess_data->ses), &rqst, &sess_data->buf0_type, CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov); @@ -1357,9 +1397,8 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) * sending us a response in an expected form */ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { - cifs_dbg(VFS, - "bad cifs.upcall version. Expected %d got %d", - CIFS_SPNEGO_UPCALL_VERSION, msg->version); + cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d\n", + CIFS_SPNEGO_UPCALL_VERSION, msg->version); rc = -EKEYREJECTED; goto out_put_spnego_key; } @@ -1369,8 +1408,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, GFP_KERNEL); if (!ses->auth_key.response) { - cifs_dbg(VFS, - "Kerberos can't allocate (%u bytes) memory", + cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n", msg->sesskey_len); rc = -ENOMEM; goto out_put_spnego_key; @@ -1584,8 +1622,7 @@ SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data) type = smb2_select_sectype(cifs_ses_server(ses), ses->sectype); cifs_dbg(FYI, "sess setup type %d\n", type); if (type == Unspecified) { - cifs_dbg(VFS, - "Unable to select appropriate authentication method!"); + cifs_dbg(VFS, "Unable to select appropriate authentication method!\n"); return -EINVAL; } @@ -1673,7 +1710,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) if (ses->need_reconnect) goto smb2_session_already_dead; - rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, + (void **) &req, &total_len); if (rc) return rc; @@ -1694,7 +1732,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, ses->server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); /* * No tcon so can't do @@ -1735,7 +1774,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, __le16 *unc_path = NULL; int flags = 0; unsigned int total_len; - struct TCP_Server_Info *server = ses->server; + struct TCP_Server_Info *server; + + /* always use master channel */ + server = ses->server; cifs_dbg(FYI, "TCON\n"); @@ -1756,8 +1798,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */ tcon->tid = 0; atomic_set(&tcon->num_remote_opens, 0); - rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, + (void **) &req, &total_len); if (rc) { kfree(unc_path); return rc; @@ -1796,7 +1838,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, /* Need 64 for max size write so ask for more in case not there yet */ req->sync_hdr.CreditRequest = cpu_to_le16(64); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(req); rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); @@ -1881,8 +1924,9 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) close_shroot_lease(&tcon->crfid); - rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server, + (void **) &req, + &total_len); if (rc) return rc; @@ -1898,7 +1942,8 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, ses->server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); if (rc) cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); @@ -2452,6 +2497,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, int flags = 0; unsigned int total_len; __le16 *utf16_path = NULL; + struct TCP_Server_Info *server = cifs_pick_channel(ses); cifs_dbg(FYI, "mkdir\n"); @@ -2460,13 +2506,14 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, if (!utf16_path) return -ENOMEM; - if (!ses || !(ses->server)) { + if (!ses || !server) { rc = -EIO; goto err_free_path; } /* resource #2: request */ - rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_CREATE, tcon, server, + (void **) &req, &total_len); if (rc) goto err_free_path; @@ -2552,7 +2599,8 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES); /* resource #4: response buffer */ - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); if (rc) { cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, @@ -2581,10 +2629,10 @@ err_free_path: } int -SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, +SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, + struct smb_rqst *rqst, __u8 *oplock, struct cifs_open_parms *oparms, __le16 *path) { - struct TCP_Server_Info *server = tcon->ses->server; struct smb2_create_req *req; unsigned int n_iov = 2; __u32 file_attributes = 0; @@ -2595,7 +2643,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, __le16 *copy_path; int rc; - rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_CREATE, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -2767,9 +2816,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, { struct smb_rqst rqst; struct smb2_create_rsp *rsp = NULL; - struct TCP_Server_Info *server; struct cifs_tcon *tcon = oparms->tcon; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); struct kvec iov[SMB2_CREATE_IOV_SIZE]; struct kvec rsp_iov = {NULL, 0}; int resp_buftype = CIFS_NO_BUFFER; @@ -2777,9 +2826,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, int flags = 0; cifs_dbg(FYI, "create/open\n"); - if (ses && (ses->server)) - server = ses->server; - else + if (!ses || !server) return -EIO; if (smb3_encryption_required(tcon)) @@ -2790,14 +2837,16 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, rqst.rq_iov = iov; rqst.rq_nvec = SMB2_CREATE_IOV_SIZE; - rc = SMB2_open_init(tcon, &rqst, oplock, oparms, path); + rc = SMB2_open_init(tcon, server, + &rqst, oplock, oparms, path); if (rc) goto creat_exit; trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->create_options, oparms->desired_access); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; @@ -2812,8 +2861,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, trace_smb3_open_err(xid, tcon->tid, ses->Suid, oparms->create_options, oparms->desired_access, rc); if (rc == -EREMCHG) { - printk_once(KERN_WARNING "server share %s deleted\n", - tcon->treeName); + pr_warn_once("server share %s deleted\n", + tcon->treeName); tcon->need_reconnect = true; } goto creat_exit; @@ -2849,7 +2898,8 @@ creat_exit: } int -SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, + struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, __u32 max_response_size) @@ -2860,7 +2910,8 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, int rc; char *in_data_buf; - rc = smb2_ioctl_req_init(opcode, tcon, (void **) &req, &total_len); + rc = smb2_ioctl_req_init(opcode, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -2922,7 +2973,9 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, * response size smaller. */ req->MaxOutputResponse = cpu_to_le32(max_response_size); - + req->sync_hdr.CreditCharge = + cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size), + SMB2_MAX_BUFFER_SIZE)); if (is_fsctl) req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); else @@ -2960,12 +3013,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, struct smb_rqst rqst; struct smb2_ioctl_rsp *rsp = NULL; struct cifs_ses *ses; + struct TCP_Server_Info *server; struct kvec iov[SMB2_IOCTL_IOV_SIZE]; struct kvec rsp_iov = {NULL, 0}; int resp_buftype = CIFS_NO_BUFFER; int rc = 0; int flags = 0; - struct TCP_Server_Info *server; cifs_dbg(FYI, "SMB2 IOCTL\n"); @@ -2976,14 +3029,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, if (plen) *plen = 0; - if (tcon) - ses = tcon->ses; - else + if (!tcon) return -EIO; + ses = tcon->ses; if (!ses) return -EIO; - server = ses->server; + + server = cifs_pick_channel(ses); if (!server) return -EIO; @@ -2995,12 +3048,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, rqst.rq_iov = iov; rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, opcode, + rc = SMB2_ioctl_init(tcon, server, + &rqst, persistent_fid, volatile_fid, opcode, is_fsctl, in_data, indatalen, max_out_data_len); if (rc) goto ioctl_exit; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; @@ -3088,7 +3143,8 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, } int -SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, + struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, bool query_attrs) { struct smb2_close_req *req; @@ -3096,7 +3152,8 @@ SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, unsigned int total_len; int rc; - rc = smb2_plain_req_init(SMB2_CLOSE, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_CLOSE, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -3127,6 +3184,7 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, struct smb_rqst rqst; struct smb2_close_rsp *rsp = NULL; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); struct kvec iov[1]; struct kvec rsp_iov; int resp_buftype = CIFS_NO_BUFFER; @@ -3136,7 +3194,7 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, cifs_dbg(FYI, "Close\n"); - if (!ses || !(ses->server)) + if (!ses || !server) return -EIO; if (smb3_encryption_required(tcon)) @@ -3152,12 +3210,14 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, query_attrs = true; trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); - rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid, + rc = SMB2_close_init(tcon, server, + &rqst, persistent_fid, volatile_fid, query_attrs); if (rc) goto close_exit; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_close_rsp *)rsp_iov.iov_base; if (rc != 0) { @@ -3225,7 +3285,7 @@ smb2_validate_iov(unsigned int offset, unsigned int buffer_length, } if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) { - cifs_dbg(VFS, "illegal server response, bad offset to data\n"); + cifs_dbg(VFS, "Invalid server response, bad offset to data\n"); return -EINVAL; } @@ -3257,7 +3317,8 @@ smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_length, } int -SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, + struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type, u32 additional_info, size_t output_len, size_t input_len, void *input) @@ -3267,8 +3328,8 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, unsigned int total_len; int rc; - rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -3320,7 +3381,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, if (!ses) return -EIO; - server = ses->server; + server = cifs_pick_channel(ses); if (!server) return -EIO; @@ -3332,7 +3393,8 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst, persistent_fid, volatile_fid, + rc = SMB2_query_info_init(tcon, server, + &rqst, persistent_fid, volatile_fid, info_class, info_type, additional_info, output_len, 0, NULL); if (rc) @@ -3341,7 +3403,8 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid, ses->Suid, info_class, (__u32)info_type); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; if (rc) { @@ -3395,6 +3458,19 @@ int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, NULL); } +int +SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen) +{ + size_t output_len = sizeof(struct smb311_posix_qinfo *) + + (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2); + *plen = 0; + + return query_info(xid, tcon, persistent_fid, volatile_fid, + SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0, + output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen); +} + int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, @@ -3426,15 +3502,17 @@ SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, static int SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, - struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, - u32 completion_filter, bool watch_tree) + struct cifs_tcon *tcon, struct TCP_Server_Info *server, + u64 persistent_fid, u64 volatile_fid, + u32 completion_filter, bool watch_tree) { struct smb2_change_notify_req *req; struct kvec *iov = rqst->rq_iov; unsigned int total_len; int rc; - rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -3461,6 +3539,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, u32 completion_filter) { struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); struct smb_rqst rqst; struct kvec iov[1]; struct kvec rsp_iov = {NULL, 0}; @@ -3469,7 +3548,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, int rc = 0; cifs_dbg(FYI, "change notify\n"); - if (!ses || !(ses->server)) + if (!ses || !server) return -EIO; if (smb3_encryption_required(tcon)) @@ -3480,14 +3559,16 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = SMB2_notify_init(xid, &rqst, tcon, persistent_fid, volatile_fid, + rc = SMB2_notify_init(xid, &rqst, tcon, server, + persistent_fid, volatile_fid, completion_filter, watch_tree); if (rc) goto cnotify_exit; trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid, (u8)watch_tree, completion_filter); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); if (rc != 0) { cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); @@ -3577,7 +3658,7 @@ void smb2_reconnect_server(struct work_struct *work) spin_unlock(&cifs_tcp_ses_lock); list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { - rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon); + rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server); if (!rc) cifs_reopen_persistent_handles(tcon); else @@ -3617,7 +3698,8 @@ SMB2_echo(struct TCP_Server_Info *server) return rc; } - rc = smb2_plain_req_init(SMB2_ECHO, NULL, (void **)&req, &total_len); + rc = smb2_plain_req_init(SMB2_ECHO, NULL, server, + (void **)&req, &total_len); if (rc) return rc; @@ -3644,14 +3726,16 @@ SMB2_flush_free(struct smb_rqst *rqst) int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, - struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) + struct cifs_tcon *tcon, struct TCP_Server_Info *server, + u64 persistent_fid, u64 volatile_fid) { struct smb2_flush_req *req; struct kvec *iov = rqst->rq_iov; unsigned int total_len; int rc; - rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_FLUSH, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -3672,6 +3756,7 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, struct smb_rqst rqst; struct kvec iov[1]; struct kvec rsp_iov = {NULL, 0}; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int resp_buftype = CIFS_NO_BUFFER; int flags = 0; int rc = 0; @@ -3688,12 +3773,14 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = SMB2_flush_init(xid, &rqst, tcon, persistent_fid, volatile_fid); + rc = SMB2_flush_init(xid, &rqst, tcon, server, + persistent_fid, volatile_fid); if (rc) goto flush_exit; trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid); - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); if (rc != 0) { cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); @@ -3721,14 +3808,13 @@ smb2_new_read_req(void **buf, unsigned int *total_len, int rc = -EACCES; struct smb2_read_plain_req *req = NULL; struct smb2_sync_hdr *shdr; - struct TCP_Server_Info *server; + struct TCP_Server_Info *server = io_parms->server; - rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req, - total_len); + rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server, + (void **) &req, total_len); if (rc) return rc; - server = io_parms->tcon->ses->server; if (server == NULL) return -ECONNABORTED; @@ -3757,8 +3843,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len, rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) { struct smbd_buffer_descriptor_v1 *v1; - bool need_invalidate = - io_parms->tcon->ses->server->dialect == SMB30_PROT_ID; + bool need_invalidate = server->dialect == SMB30_PROT_ID; rdata->mr = smbd_register_mr( server->smbd_conn, rdata->pages, @@ -3815,7 +3900,7 @@ smb2_readv_callback(struct mid_q_entry *mid) { struct cifs_readdata *rdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; + struct TCP_Server_Info *server = rdata->server; struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)rdata->iov[0].iov_base; struct cifs_credits credits = { .value = 0, .instance = 0 }; @@ -3827,6 +3912,10 @@ smb2_readv_callback(struct mid_q_entry *mid) .rq_pagesz = rdata->pagesz, .rq_tailsz = rdata->tailsz }; + WARN_ONCE(rdata->server != mid->server, + "rdata server %p != mid server %p", + rdata->server, mid->server); + cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n", __func__, mid->mid, mid->mid_state, rdata->result, rdata->bytes); @@ -3904,20 +3993,23 @@ smb2_async_readv(struct cifs_readdata *rdata) struct smb_rqst rqst = { .rq_iov = rdata->iov, .rq_nvec = 1 }; struct TCP_Server_Info *server; + struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); unsigned int total_len; cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", __func__, rdata->offset, rdata->bytes); + if (!rdata->server) + rdata->server = cifs_pick_channel(tcon->ses); + io_parms.tcon = tlink_tcon(rdata->cfile->tlink); + io_parms.server = server = rdata->server; io_parms.offset = rdata->offset; io_parms.length = rdata->bytes; io_parms.persistent_fid = rdata->cfile->fid.persistent_fid; io_parms.volatile_fid = rdata->cfile->fid.volatile_fid; io_parms.pid = rdata->pid; - server = io_parms.tcon->ses->server; - rc = smb2_new_read_req( (void **) &buf, &total_len, &io_parms, rdata, 0, 0); if (rc) @@ -3945,7 +4037,7 @@ smb2_async_readv(struct cifs_readdata *rdata) } kref_get(&rdata->refcount); - rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, + rc = cifs_call_async(server, &rqst, cifs_readv_receive, smb2_readv_callback, smb3_handle_read_data, rdata, flags, &rdata->credits); @@ -3977,6 +4069,9 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, int flags = CIFS_LOG_ERROR; struct cifs_ses *ses = io_parms->tcon->ses; + if (!io_parms->server) + io_parms->server = cifs_pick_channel(io_parms->tcon->ses); + *nbytes = 0; rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0); if (rc) @@ -3992,7 +4087,8 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, io_parms->server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; if (rc) { @@ -4048,11 +4144,15 @@ smb2_writev_callback(struct mid_q_entry *mid) { struct cifs_writedata *wdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; + struct TCP_Server_Info *server = wdata->server; unsigned int written; struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; struct cifs_credits credits = { .value = 0, .instance = 0 }; + WARN_ONCE(wdata->server != mid->server, + "wdata server %p != mid server %p", + wdata->server, mid->server); + switch (mid->mid_state) { case MID_RESPONSE_RECEIVED: credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); @@ -4108,8 +4208,8 @@ smb2_writev_callback(struct mid_q_entry *mid) tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes, wdata->result); if (wdata->result == -ENOSPC) - printk_once(KERN_WARNING "Out of space writing to %s\n", - tcon->treeName); + pr_warn_once("Out of space writing to %s\n", + tcon->treeName); } else trace_smb3_write_done(0 /* no xid */, wdata->cfile->fid.persistent_fid, @@ -4130,12 +4230,16 @@ smb2_async_writev(struct cifs_writedata *wdata, struct smb2_write_req *req = NULL; struct smb2_sync_hdr *shdr; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; + struct TCP_Server_Info *server = wdata->server; struct kvec iov[1]; struct smb_rqst rqst = { }; unsigned int total_len; - rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len); + if (!wdata->server) + server = wdata->server = cifs_pick_channel(tcon->ses); + + rc = smb2_plain_req_init(SMB2_WRITE, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -4274,20 +4378,24 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, struct kvec rsp_iov; int flags = 0; unsigned int total_len; + struct TCP_Server_Info *server; *nbytes = 0; if (n_vec < 1) return rc; - rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, (void **) &req, - &total_len); + if (!io_parms->server) + io_parms->server = cifs_pick_channel(io_parms->tcon->ses); + server = io_parms->server; + if (server == NULL) + return -ECONNABORTED; + + rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server, + (void **) &req, &total_len); if (rc) return rc; - if (io_parms->tcon->ses->server == NULL) - return -ECONNABORTED; - if (smb3_encryption_required(io_parms->tcon)) flags |= CIFS_TRANSFORM_REQ; @@ -4316,7 +4424,8 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, rqst.rq_iov = iov; rqst.rq_nvec = n_vec + 1; - rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst, + rc = cifs_send_recv(xid, io_parms->tcon->ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; @@ -4490,11 +4599,12 @@ num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry, * Readdir/FindFirst */ int SMB2_query_directory_init(const unsigned int xid, - struct cifs_tcon *tcon, struct smb_rqst *rqst, + struct cifs_tcon *tcon, + struct TCP_Server_Info *server, + struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, int index, int info_level) { - struct TCP_Server_Info *server = tcon->ses->server; struct smb2_query_directory_req *req; unsigned char *bufptr; __le16 asteriks = cpu_to_le16('*'); @@ -4505,8 +4615,8 @@ int SMB2_query_directory_init(const unsigned int xid, struct kvec *iov = rqst->rq_iov; int len, rc; - rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -4632,7 +4742,7 @@ smb2_parse_query_directory(struct cifs_tcon *tcon, else if (resp_buftype == CIFS_SMALL_BUFFER) srch_inf->smallBuf = true; else - cifs_tcon_dbg(VFS, "illegal search buffer type\n"); + cifs_tcon_dbg(VFS, "Invalid search buffer type\n"); return 0; } @@ -4649,6 +4759,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, struct kvec rsp_iov; int rc = 0; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int flags = 0; if (!ses || !(ses->server)) @@ -4662,13 +4773,15 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; - rc = SMB2_query_directory_init(xid, tcon, &rqst, persistent_fid, + rc = SMB2_query_directory_init(xid, tcon, server, + &rqst, persistent_fid, volatile_fid, index, srch_inf->info_level); if (rc) goto qdir_exit; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; if (rc) { @@ -4705,17 +4818,19 @@ qdir_exit: } int -SMB2_set_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, - u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class, - u8 info_type, u32 additional_info, - void **data, unsigned int *size) +SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, + struct smb_rqst *rqst, + u64 persistent_fid, u64 volatile_fid, u32 pid, + u8 info_class, u8 info_type, u32 additional_info, + void **data, unsigned int *size) { struct smb2_set_info_req *req; struct kvec *iov = rqst->rq_iov; unsigned int i, total_len; int rc; - rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -4766,9 +4881,10 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int flags = 0; - if (!ses || !(ses->server)) + if (!ses || !server) return -EIO; if (!num) @@ -4785,7 +4901,8 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = num; - rc = SMB2_set_info_init(tcon, &rqst, persistent_fid, volatile_fid, pid, + rc = SMB2_set_info_init(tcon, server, + &rqst, persistent_fid, volatile_fid, pid, info_class, info_type, additional_info, data, size); if (rc) { @@ -4794,7 +4911,8 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, } - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); SMB2_set_info_free(&rqst); rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; @@ -4857,6 +4975,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, int rc; struct smb2_oplock_break *req = NULL; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int flags = CIFS_OBREAK_OP; unsigned int total_len; struct kvec iov[1]; @@ -4864,8 +4983,8 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, int resp_buf_type; cifs_dbg(FYI, "SMB2_oplock_break\n"); - rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -4886,7 +5005,8 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); if (rc) { @@ -4929,8 +5049,10 @@ copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data, } static int -build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, - int outbuf_len, u64 persistent_fid, u64 volatile_fid) +build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, + int level, int outbuf_len, u64 persistent_fid, + u64 volatile_fid) { int rc; struct smb2_query_info_req *req; @@ -4938,11 +5060,11 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, cifs_dbg(FYI, "Query FSInfo level %d\n", level); - if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) + if ((tcon->ses == NULL) || server == NULL) return -EIO; - rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -4972,10 +5094,12 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); FILE_SYSTEM_POSIX_INFO *info = NULL; int flags = 0; - rc = build_qfs_info_req(&iov, tcon, FS_POSIX_INFORMATION, + rc = build_qfs_info_req(&iov, tcon, server, + FS_POSIX_INFORMATION, sizeof(FILE_SYSTEM_POSIX_INFO), persistent_fid, volatile_fid); if (rc) @@ -4988,7 +5112,8 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = &iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(iov.iov_base); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); @@ -5020,10 +5145,12 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); struct smb2_fs_full_size_info *info = NULL; int flags = 0; - rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION, + rc = build_qfs_info_req(&iov, tcon, server, + FS_FULL_SIZE_INFORMATION, sizeof(struct smb2_fs_full_size_info), persistent_fid, volatile_fid); if (rc) @@ -5036,7 +5163,8 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = &iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(iov.iov_base); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); @@ -5068,6 +5196,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, int rc = 0; int resp_buftype, max_len, min_len; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); unsigned int rsp_len, offset; int flags = 0; @@ -5088,7 +5217,8 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, return -EINVAL; } - rc = build_qfs_info_req(&iov, tcon, level, max_len, + rc = build_qfs_info_req(&iov, tcon, server, + level, max_len, persistent_fid, volatile_fid); if (rc) return rc; @@ -5100,7 +5230,8 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = &iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(iov.iov_base); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); @@ -5153,10 +5284,12 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, unsigned int count; int flags = CIFS_NO_RSP_BUF; unsigned int total_len; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); - rc = smb2_plain_req_init(SMB2_LOCK, tcon, (void **) &req, &total_len); + rc = smb2_plain_req_init(SMB2_LOCK, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -5182,7 +5315,8 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = 2; - rc = cifs_send_recv(xid, tcon->ses, &rqst, &resp_buf_type, flags, + rc = cifs_send_recv(xid, tcon->ses, server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); if (rc) { @@ -5227,10 +5361,11 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, int resp_buf_type; __u64 *please_key_high; __u64 *please_key_low; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); cifs_dbg(FYI, "SMB2_lease_break\n"); - rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, - &total_len); + rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, + (void **) &req, &total_len); if (rc) return rc; @@ -5253,7 +5388,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, rqst.rq_iov = iov; rqst.rq_nvec = 1; - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); please_key_low = (__u64 *)lease_key;