diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-06 02:40:53 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-06 02:40:53 +0300 |
commit | 3803d5e4d3ce2600ffddc16a1999798bc719042d (patch) | |
tree | 4bd971c4931a8f11d9608548bdd7fd304d07881d /fs/cifs | |
parent | 9daa0a27a0bce6596be287fb1df372ff80bb1087 (diff) | |
parent | 331cc667a99c633abbbebeab4675beae713fb331 (diff) | |
download | linux-3803d5e4d3ce2600ffddc16a1999798bc719042d.tar.xz |
Merge tag '5.8-rc-smb3-fixes-part-1' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French:
"22 changesets, 2 for stable.
Includes big performance improvement for large i/o when using
multichannel, also includes DFS fixes"
* tag '5.8-rc-smb3-fixes-part-1' of git://git.samba.org/sfrench/cifs-2.6: (22 commits)
cifs: update internal module version number
cifs: multichannel: try to rebind when reconnecting a channel
cifs: multichannel: use pointer for binding channel
smb3: remove static checker warning
cifs: multichannel: move channel selection above transport layer
cifs: multichannel: always zero struct cifs_io_parms
cifs: dump Security Type info in DebugData
smb3: fix incorrect number of credits when ioctl MaxOutputResponse > 64K
smb3: default to minimum of two channels when multichannel specified
cifs: multichannel: move channel selection in function
cifs: fix minor typos in comments and log messages
smb3: minor update to compression header definitions
cifs: minor fix to two debug messages
cifs: Standardize logging output
smb3: Add new parm "nodelete"
cifs: move some variables off the stack in smb2_ioctl_query_info
cifs: reduce stack use in smb2_compound_op
cifs: get rid of unused parameter in reconn_setup_dfs_targets()
cifs: handle hostnames that resolve to same ip in failover
cifs: set up next DFS target before generic_ip_connect()
...
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifs_debug.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 145 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 8 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 20 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 36 | ||||
-rw-r--r-- | fs/cifs/cifsroot.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 81 | ||||
-rw-r--r-- | fs/cifs/connect.c | 130 | ||||
-rw-r--r-- | fs/cifs/dfs_cache.c | 14 | ||||
-rw-r--r-- | fs/cifs/file.c | 60 | ||||
-rw-r--r-- | fs/cifs/inode.c | 17 | ||||
-rw-r--r-- | fs/cifs/link.c | 8 | ||||
-rw-r--r-- | fs/cifs/misc.c | 60 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 6 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 10 | ||||
-rw-r--r-- | fs/cifs/sess.c | 55 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2inode.c | 137 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 20 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 168 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 499 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 13 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 25 | ||||
-rw-r--r-- | fs/cifs/smbdirect.c | 165 | ||||
-rw-r--r-- | fs/cifs/transport.c | 75 |
27 files changed, 1041 insertions, 729 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 916567d770f5..3ad1a98fd567 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -221,6 +221,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) struct cifs_ses *ses; struct cifs_tcon *tcon; int i, j; + const char *security_types[] = {"Unspecified", "LANMAN", "NTLM", + "NTLMv2", "RawNTLMSSP", "Kerberos"}; seq_puts(m, "Display Internal CIFS Data Structures for Debugging\n" @@ -375,6 +377,10 @@ skip_rdma: ses->ses_count, ses->serverOS, ses->serverNOS, ses->capabilities, ses->status); } + + seq_printf(m,"Security type: %s\n", + security_types[server->ops->select_sectype(server, ses->sectype)]); + if (server->rdma) seq_printf(m, "RDMA\n\t"); seq_printf(m, "TCP status: %d Instance: %d\n\tLocal Users To " diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 100b0056a369..5e66dab712d0 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h @@ -8,6 +8,12 @@ #ifndef _H_CIFS_DEBUG #define _H_CIFS_DEBUG +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "CIFS: " fmt + void cifs_dump_mem(char *label, void *data, int length); void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info); void cifs_dump_mids(struct TCP_Server_Info *); @@ -46,92 +52,81 @@ extern int cifsFYI; */ /* Information level messages, minor events */ -#define cifs_info_func(ratefunc, fmt, ...) \ -do { \ - pr_info_ ## ratefunc("CIFS: " fmt, ##__VA_ARGS__); \ -} while (0) +#define cifs_info_func(ratefunc, fmt, ...) \ + pr_info_ ## ratefunc(fmt, ##__VA_ARGS__) -#define cifs_info(fmt, ...) \ -do { \ - cifs_info_func(ratelimited, fmt, ##__VA_ARGS__); \ -} while (0) +#define cifs_info(fmt, ...) \ + cifs_info_func(ratelimited, fmt, ##__VA_ARGS__) /* information message: e.g., configuration, major event */ -#define cifs_dbg_func(ratefunc, type, fmt, ...) \ -do { \ - if ((type) & FYI && cifsFYI & CIFS_INFO) { \ - pr_debug_ ## ratefunc("%s: " \ - fmt, __FILE__, ##__VA_ARGS__); \ - } else if ((type) & VFS) { \ - pr_err_ ## ratefunc("CIFS VFS: " \ - fmt, ##__VA_ARGS__); \ - } else if ((type) & NOISY && (NOISY != 0)) { \ - pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \ - } \ +#define cifs_dbg_func(ratefunc, type, fmt, ...) \ +do { \ + if ((type) & FYI && cifsFYI & CIFS_INFO) { \ + pr_debug_ ## ratefunc("%s: " fmt, \ + __FILE__, ##__VA_ARGS__); \ + } else if ((type) & VFS) { \ + pr_err_ ## ratefunc("VFS: " fmt, ##__VA_ARGS__); \ + } else if ((type) & NOISY && (NOISY != 0)) { \ + pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \ + } \ } while (0) -#define cifs_dbg(type, fmt, ...) \ -do { \ - if ((type) & ONCE) \ - cifs_dbg_func(once, \ - type, fmt, ##__VA_ARGS__); \ - else \ - cifs_dbg_func(ratelimited, \ - type, fmt, ##__VA_ARGS__); \ +#define cifs_dbg(type, fmt, ...) \ +do { \ + if ((type) & ONCE) \ + cifs_dbg_func(once, type, fmt, ##__VA_ARGS__); \ + else \ + cifs_dbg_func(ratelimited, type, fmt, ##__VA_ARGS__); \ } while (0) -#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ -do { \ - const char *sn = ""; \ - if (server && server->hostname) \ - sn = server->hostname; \ - if ((type) & FYI && cifsFYI & CIFS_INFO) { \ - pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \ - __FILE__, sn, ##__VA_ARGS__); \ - } else if ((type) & VFS) { \ - pr_err_ ## ratefunc("CIFS VFS: \\\\%s " fmt, \ - sn, ##__VA_ARGS__); \ - } else if ((type) & NOISY && (NOISY != 0)) { \ - pr_debug_ ## ratefunc("\\\\%s " fmt, \ - sn, ##__VA_ARGS__); \ - } \ +#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ +do { \ + const char *sn = ""; \ + if (server && server->hostname) \ + sn = server->hostname; \ + if ((type) & FYI && cifsFYI & CIFS_INFO) { \ + pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \ + __FILE__, sn, ##__VA_ARGS__); \ + } else if ((type) & VFS) { \ + pr_err_ ## ratefunc("VFS: \\\\%s " fmt, \ + sn, ##__VA_ARGS__); \ + } else if ((type) & NOISY && (NOISY != 0)) { \ + pr_debug_ ## ratefunc("\\\\%s " fmt, \ + sn, ##__VA_ARGS__); \ + } \ } while (0) -#define cifs_server_dbg(type, fmt, ...) \ -do { \ - if ((type) & ONCE) \ - cifs_server_dbg_func(once, \ - type, fmt, ##__VA_ARGS__); \ - else \ - cifs_server_dbg_func(ratelimited, \ - type, fmt, ##__VA_ARGS__); \ +#define cifs_server_dbg(type, fmt, ...) \ +do { \ + if ((type) & ONCE) \ + cifs_server_dbg_func(once, type, fmt, ##__VA_ARGS__); \ + else \ + cifs_server_dbg_func(ratelimited, type, fmt, \ + ##__VA_ARGS__); \ } while (0) -#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \ -do { \ - const char *tn = ""; \ - if (tcon && tcon->treeName) \ - tn = tcon->treeName; \ - if ((type) & FYI && cifsFYI & CIFS_INFO) { \ - pr_debug_ ## ratefunc("%s: %s " fmt, \ - __FILE__, tn, ##__VA_ARGS__); \ - } else if ((type) & VFS) { \ - pr_err_ ## ratefunc("CIFS VFS: %s " fmt, \ - tn, ##__VA_ARGS__); \ - } else if ((type) & NOISY && (NOISY != 0)) { \ - pr_debug_ ## ratefunc("%s " fmt, \ - tn, ##__VA_ARGS__); \ - } \ +#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \ +do { \ + const char *tn = ""; \ + if (tcon && tcon->treeName) \ + tn = tcon->treeName; \ + if ((type) & FYI && cifsFYI & CIFS_INFO) { \ + pr_debug_ ## ratefunc("%s: %s " fmt, \ + __FILE__, tn, ##__VA_ARGS__); \ + } else if ((type) & VFS) { \ + pr_err_ ## ratefunc("VFS: %s " fmt, tn, ##__VA_ARGS__); \ + } else if ((type) & NOISY && (NOISY != 0)) { \ + pr_debug_ ## ratefunc("%s " fmt, tn, ##__VA_ARGS__); \ + } \ } while (0) -#define cifs_tcon_dbg(type, fmt, ...) \ -do { \ - if ((type) & ONCE) \ - cifs_tcon_dbg_func(once, \ - type, fmt, ##__VA_ARGS__); \ - else \ - cifs_tcon_dbg_func(ratelimited, \ - type, fmt, ##__VA_ARGS__); \ +#define cifs_tcon_dbg(type, fmt, ...) \ +do { \ + if ((type) & ONCE) \ + cifs_tcon_dbg_func(once, type, fmt, ##__VA_ARGS__); \ + else \ + cifs_tcon_dbg_func(ratelimited, type, fmt, \ + ##__VA_ARGS__); \ } while (0) /* @@ -159,9 +154,7 @@ do { \ } while (0) #define cifs_info(fmt, ...) \ -do { \ - pr_info("CIFS: "fmt, ##__VA_ARGS__); \ -} while (0) + pr_info(fmt, ##__VA_ARGS__) #endif #endif /* _H_CIFS_DEBUG */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 97b7497c13ef..874a551f339c 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -520,7 +520,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { - cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__); + cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__); return rc; } @@ -624,7 +624,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { - cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__); + cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__); return rc; } @@ -723,7 +723,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) /* calculate ntlmv2_hash */ rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); if (rc) { - cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc); + cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc); goto unlock; } @@ -783,7 +783,7 @@ calc_seckey(struct cifs_ses *ses) ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL); if (!ctx_arc4) { - cifs_dbg(VFS, "could not allocate arc4 context\n"); + cifs_dbg(VFS, "Could not allocate arc4 context\n"); return -ENOMEM; } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c31f362fa098..889f9c71049b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -534,6 +534,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) seq_puts(s, ",signloosely"); if (tcon->nocase) seq_puts(s, ",nocase"); + if (tcon->nodelete) + seq_puts(s, ",nodelete"); if (tcon->local_lease) seq_puts(s, ",locallease"); if (tcon->retry) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index c9e2e6bbca13..c7a311d28d3d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -156,5 +156,5 @@ extern int cifs_truncate_page(struct address_space *mapping, loff_t from); extern const struct export_operations cifs_export_ops; #endif /* CONFIG_CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "2.26" +#define CIFS_VERSION "2.27" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 39b708d9d86d..e133bb3e172f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -562,6 +562,7 @@ struct smb_vol { bool override_gid:1; bool dynperm:1; bool noperm:1; + bool nodelete:1; bool mode_ace:1; bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool cifs_acl:1; @@ -1029,6 +1030,7 @@ struct cifs_ses { #define CIFS_MAX_CHANNELS 16 struct cifs_chan chans[CIFS_MAX_CHANNELS]; + struct cifs_chan *binding_chan; size_t chan_count; size_t chan_max; atomic_t chan_seq; /* round robin state */ @@ -1036,23 +1038,31 @@ struct cifs_ses { /* * When binding a new channel, we need to access the channel which isn't fully - * established yet (one past the established count) + * established yet. */ static inline struct cifs_chan *cifs_ses_binding_channel(struct cifs_ses *ses) { if (ses->binding) - return &ses->chans[ses->chan_count]; + return ses->binding_chan; else return NULL; } +/* + * Returns the server pointer of the session. When binding a new + * channel this returns the last channel which isn't fully established + * yet. + * + * This function should be use for negprot/sess.setup codepaths. For + * the other requests see cifs_pick_channel(). + */ static inline struct TCP_Server_Info *cifs_ses_server(struct cifs_ses *ses) { if (ses->binding) - return ses->chans[ses->chan_count].server; + return ses->binding_chan->server; else return ses->server; } @@ -1136,6 +1146,7 @@ struct cifs_tcon { bool retry:1; bool nocase:1; bool nohandlecache:1; /* if strange server resource prob can turn off */ + bool nodelete:1; bool seal:1; /* transport encryption for this mounted share */ bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol for this mount even if server would support */ @@ -1333,6 +1344,7 @@ struct cifs_io_parms { __u64 offset; unsigned int length; struct cifs_tcon *tcon; + struct TCP_Server_Info *server; }; struct cifs_aio_ctx { @@ -1380,6 +1392,7 @@ struct cifs_readdata { struct cifs_readdata *rdata, struct iov_iter *iter); struct kvec iov[2]; + struct TCP_Server_Info *server; #ifdef CONFIG_CIFS_SMB_DIRECT struct smbd_mr *mr; #endif @@ -1406,6 +1419,7 @@ struct cifs_writedata { pid_t pid; unsigned int bytes; int result; + struct TCP_Server_Info *server; #ifdef CONFIG_CIFS_SMB_DIRECT struct smbd_mr *mr; #endif diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 12a895e02db4..bd92070ca30c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -45,25 +45,25 @@ extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, unsigned int /* length */); extern unsigned int _get_xid(void); extern void _free_xid(unsigned int); -#define get_xid() \ -({ \ +#define get_xid() \ +({ \ unsigned int __xid = _get_xid(); \ - cifs_dbg(FYI, "CIFS VFS: in %s as Xid: %u with uid: %d\n", \ + cifs_dbg(FYI, "VFS: in %s as Xid: %u with uid: %d\n", \ __func__, __xid, \ from_kuid(&init_user_ns, current_fsuid())); \ - trace_smb3_enter(__xid, __func__); \ - __xid; \ + trace_smb3_enter(__xid, __func__); \ + __xid; \ }) -#define free_xid(curr_xid) \ -do { \ - _free_xid(curr_xid); \ - cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \ - __func__, curr_xid, (int)rc); \ - if (rc) \ +#define free_xid(curr_xid) \ +do { \ + _free_xid(curr_xid); \ + cifs_dbg(FYI, "VFS: leaving %s (xid = %u) rc = %d\n", \ + __func__, curr_xid, (int)rc); \ + if (rc) \ trace_smb3_exit_err(curr_xid, __func__, (int)rc); \ - else \ - trace_smb3_exit_done(curr_xid, __func__); \ + else \ + trace_smb3_exit_done(curr_xid, __func__); \ } while (0) extern int init_cifs_idmap(void); extern void exit_cifs_idmap(void); @@ -89,16 +89,20 @@ extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry); extern void cifs_wake_up_task(struct mid_q_entry *mid); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid); +extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs); extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); extern int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, mid_receive_t *receive, mid_callback_t *callback, mid_handle_t *handle, void *cbdata, const int flags, const struct cifs_credits *exist_credits); +extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses); extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov); extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, const int flags, const int num_rqst, struct smb_rqst *rqst, int *resp_buf_type, struct kvec *resp_iov); @@ -589,6 +593,8 @@ void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc); extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, unsigned int *len, unsigned int *offset); +struct cifs_chan * +cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server); int cifs_try_adding_channels(struct cifs_ses *ses); int cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface); @@ -616,6 +622,10 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, return dfs_cache_find(xid, ses, nls_codepage, remap, old_path, referral, NULL); } + +int match_target_ip(struct TCP_Server_Info *server, + const char *share, size_t share_len, + bool *result); #endif static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c index 37edbfb8e096..9e91a5a40aae 100644 --- a/fs/cifs/cifsroot.c +++ b/fs/cifs/cifsroot.c @@ -56,7 +56,7 @@ static int __init cifs_root_setup(char *line) /* len is strlen(unc) + '\0' */ len = s - line + 1; if (len > sizeof(root_dev)) { - printk(KERN_ERR "Root-CIFS: UNC path too long\n"); + pr_err("Root-CIFS: UNC path too long\n"); return 1; } strlcpy(root_dev, line, len); @@ -66,7 +66,7 @@ static int __init cifs_root_setup(char *line) sizeof(root_opts), "%s,%s", DEFAULT_MNT_OPTS, s + 1); if (n >= sizeof(root_opts)) { - printk(KERN_ERR "Root-CIFS: mount options string too long\n"); + pr_err("Root-CIFS: mount options string too long\n"); root_opts[sizeof(root_opts)-1] = '\0'; return 1; } @@ -83,7 +83,7 @@ __setup("cifsroot=", cifs_root_setup); int __init cifs_root_data(char **dev, char **opts) { if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) { - printk(KERN_ERR "Root-CIFS: no SMB server address\n"); + pr_err("Root-CIFS: no SMB server address\n"); return -1; } diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 5014a82391ff..bf41ee048396 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -129,6 +129,7 @@ static int __cifs_reconnect_tcon(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; @@ -141,15 +142,14 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc, if (!tree) return -ENOMEM; - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", - tcon->ses->server->hostname); - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - goto out; - } - if (!tcon->dfs_path) { - rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", + server->hostname); + rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); + } else { + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); + } goto out; } @@ -157,13 +157,13 @@ static int __cifs_reconnect_tcon(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); @@ -177,19 +177,38 @@ static int __cifs_reconnect_tcon(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; + } + + if (!target_match) { + cifs_dbg(FYI, "%s: skipping target\n", __func__); + continue; + } + } - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - if (!rc) { - rc = update_super_prepath(tcon, prefix, prefix_len); - break; + if (tcon->ipc) { + scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$", + (int)share_len, share); + rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); + } else { + scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, + share); + rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); + if (!rc) { + rc = update_super_prepath(tcon, prefix, + prefix_len); + break; + } } if (rc == -EREMOTE) break; @@ -262,8 +281,8 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) (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; } @@ -324,7 +343,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); if (rc) { - printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc); + pr_warn_once("reconnect tcon failed rc = %d\n", rc); goto out; } @@ -557,7 +576,7 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) /* If server requires signing, does client allow it? */ if (srv_sign_required) { if (!mnt_sign_enabled) { - cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!"); + cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n"); return -ENOTSUPP; } server->sign = true; @@ -566,14 +585,14 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) /* If client requires signing, does server allow it? */ if (mnt_sign_required) { if (!srv_sign_enabled) { - cifs_dbg(VFS, "Server does not support signing!"); + cifs_dbg(VFS, "Server does not support signing!\n"); return -ENOTSUPP; } server->sign = true; } if (cifs_rdma_enabled(server) && server->sign) - cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled"); + cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n"); return 0; } @@ -703,7 +722,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); if (should_set_ext_sec_flag(ses->sectype)) { - cifs_dbg(FYI, "Requesting extended security."); + cifs_dbg(FYI, "Requesting extended security\n"); pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; } @@ -2375,7 +2394,7 @@ int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, struct kvec *iov, int n_vec) { - int rc = -EACCES; + int rc; WRITE_REQ *pSMB = NULL; int wct; int smb_hdr_len; @@ -3868,7 +3887,7 @@ GetExtAttrRetry: struct file_chattr_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count != 16) { - cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n"); + cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n"); rc = -EIO; goto GetExtAttrOut; } @@ -4244,7 +4263,7 @@ QFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cifs_dbg(FYI, "Send error in QFileInfo = %d", rc); + cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4411,7 +4430,7 @@ UnixQFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc); + cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4493,7 +4512,7 @@ UnixQPathInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc); + cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4913,7 +4932,7 @@ GetInodeNumberRetry: struct file_internal_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count < 8) { - cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n"); + cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n"); rc = -EIO; goto GetInodeNumOut; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ad8fb53b3682..5fac34f192af 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -75,7 +75,7 @@ enum { Opt_forceuid, Opt_noforceuid, Opt_forcegid, Opt_noforcegid, Opt_noblocksend, Opt_noautotune, Opt_nolease, - Opt_hard, Opt_soft, Opt_perm, Opt_noperm, + Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete, Opt_mapposix, Opt_nomapposix, Opt_mapchars, Opt_nomapchars, Opt_sfu, Opt_nosfu, Opt_nodfs, Opt_posixpaths, @@ -141,6 +141,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_soft, "soft" }, { Opt_perm, "perm" }, { Opt_noperm, "noperm" }, + { Opt_nodelete, "nodelete" }, { Opt_mapchars, "mapchars" }, /* SFU style */ { Opt_nomapchars, "nomapchars" }, { Opt_mapposix, "mapposix" }, /* SFM style */ @@ -426,8 +427,7 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server, } static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb, - struct dfs_cache_tgt_list *tl, - struct dfs_cache_tgt_iterator **it) + struct dfs_cache_tgt_list *tl) { if (!cifs_sb->origin_fullpath) return -EOPNOTSUPP; @@ -472,7 +472,7 @@ cifs_reconnect(struct TCP_Server_Info *server) } else { cifs_sb = CIFS_SB(sb); - rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); + rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list); if (rc && (rc != -EOPNOTSUPP)) { cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", __func__); @@ -572,26 +572,26 @@ cifs_reconnect(struct TCP_Server_Info *server) try_to_freeze(); mutex_lock(&server->srv_mutex); +#ifdef CONFIG_CIFS_DFS_UPCALL /* * Set up next DFS target server (if any) for reconnect. If DFS * feature is disabled, then we will retry last server we * connected to before. */ + reconn_inval_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); +#endif + rc = reconn_set_ipaddr(server); + if (rc) { + cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", + __func__, rc); + } + if (cifs_rdma_enabled(server)) rc = smbd_reconnect(server); else rc = generic_ip_connect(server); if (rc) { cifs_dbg(FYI, "reconnect error %d\n", rc); -#ifdef CONFIG_CIFS_DFS_UPCALL - reconn_inval_dfs_target(server, cifs_sb, &tgt_list, - &tgt_it); -#endif - rc = reconn_set_ipaddr(server); - if (rc) { - cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", - __func__, rc); - } mutex_unlock(&server->srv_mutex); msleep(3000); } else { @@ -879,8 +879,7 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) * function has finished processing it is a bug. */ if (mid->mid_flags & MID_DELETED) - printk_once(KERN_WARNING - "trying to dequeue a deleted mid\n"); + pr_warn_once("trying to dequeue a deleted mid\n"); else { list_del_init(&mid->qhead); mid->mid_flags |= MID_DELETED; @@ -1229,9 +1228,8 @@ next_pdu: smb2_add_credits_from_hdr(bufs[i], server); cifs_dbg(FYI, "Received oplock break\n"); } else { - cifs_server_dbg(VFS, "No task to wake, unknown frame " - "received! NumMids %d\n", - atomic_read(&midCount)); + cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", + atomic_read(&midCount)); cifs_dump_mem("Received Data is: ", bufs[i], HEADER_SIZE(server)); smb2_add_credits_from_hdr(bufs[i], server); @@ -1476,9 +1474,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3) cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n"); return 1; } - cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 " - "is not recommended unless required for " - "access to very old servers\n"); + cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n"); vol->ops = &smb1_operations; vol->vals = &smb1_values; break; @@ -1545,7 +1541,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol) size_t len; if (unlikely(!devname || !*devname)) { - cifs_dbg(VFS, "Device name not specified.\n"); + cifs_dbg(VFS, "Device name not specified\n"); return -EINVAL; } @@ -1695,13 +1691,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case 0: break; case -ENOMEM: - cifs_dbg(VFS, "Unable to allocate memory for devname.\n"); + cifs_dbg(VFS, "Unable to allocate memory for devname\n"); goto cifs_parse_mount_err; case -EINVAL: - cifs_dbg(VFS, "Malformed UNC in devname.\n"); + cifs_dbg(VFS, "Malformed UNC in devname\n"); goto cifs_parse_mount_err; default: - cifs_dbg(VFS, "Unknown error parsing devname.\n"); + cifs_dbg(VFS, "Unknown error parsing devname\n"); goto cifs_parse_mount_err; } @@ -1761,6 +1757,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case Opt_noperm: vol->noperm = 1; break; + case Opt_nodelete: + vol->nodelete = 1; + break; case Opt_mapchars: vol->sfu_remap = true; vol->remap = false; /* disable SFM mapping */ @@ -1909,7 +1908,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, vol->seal = 1; break; case Opt_noac: - pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); + pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); break; case Opt_fsc: #ifndef CONFIG_CIFS_FSCACHE @@ -1965,9 +1964,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, break; case Opt_multichannel: vol->multichannel = true; + /* if number of channels not specified, default to 2 */ + if (vol->max_channels < 2) + vol->max_channels = 2; break; case Opt_nomultichannel: vol->multichannel = false; + vol->max_channels = 1; break; case Opt_compress: vol->compression = UNKNOWN_TYPE; @@ -2156,7 +2159,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (strnlen(string, CIFS_MAX_USERNAME_LEN) > CIFS_MAX_USERNAME_LEN) { - pr_warn("CIFS: username too long\n"); + pr_warn("username too long\n"); goto cifs_parse_mount_err; } @@ -2222,7 +2225,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, temp_len = strlen(value); vol->password = kzalloc(temp_len+1, GFP_KERNEL); if (vol->password == NULL) { - pr_warn("CIFS: no memory for password\n"); + pr_warn("no memory for password\n"); goto cifs_parse_mount_err; } @@ -2246,7 +2249,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (!cifs_convert_address(dstaddr, string, strlen(string))) { - pr_err("CIFS: bad ip= option (%s).\n", string); + pr_err("bad ip= option (%s)\n", string); goto cifs_parse_mount_err; } got_ip = true; @@ -2258,14 +2261,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) == CIFS_MAX_DOMAINNAME_LEN) { - pr_warn("CIFS: domain name too long\n"); + pr_warn("domain name too long\n"); goto cifs_parse_mount_err; } kfree(vol->domainname); vol->domainname = kstrdup(string, GFP_KERNEL); if (!vol->domainname) { - pr_warn("CIFS: no memory for domainname\n"); + pr_warn("no memory for domainname\n"); goto cifs_parse_mount_err; } cifs_dbg(FYI, "Domain name set\n"); @@ -2278,7 +2281,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (!cifs_convert_address( (struct sockaddr *)&vol->srcaddr, string, strlen(string))) { - pr_warn("CIFS: Could not parse srcaddr: %s\n", + pr_warn("Could not parse srcaddr: %s\n", string); goto cifs_parse_mount_err; } @@ -2289,7 +2292,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, goto out_nomem; if (strnlen(string, 1024) >= 65) { - pr_warn("CIFS: iocharset name too long.\n"); + pr_warn("iocharset name too long\n"); goto cifs_parse_mount_err; } @@ -2298,7 +2301,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, vol->iocharset = kstrdup(string, GFP_KERNEL); if (!vol->iocharset) { - pr_warn("CIFS: no memory for charset\n"); + pr_warn("no memory for charset\n"); goto cifs_parse_mount_err; } } @@ -2329,7 +2332,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, * set at top of the function */ if (i == RFC1001_NAME_LEN && string[i] != 0) - pr_warn("CIFS: netbiosname longer than 15 truncated.\n"); + pr_warn("netbiosname longer than 15 truncated\n"); break; case Opt_servern: /* servernetbiosname specified override *SMBSERVER */ @@ -2355,7 +2358,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, /* The string has 16th byte zero still from set at top of the function */ if (i == RFC1001_NAME_LEN && string[i] != 0) - pr_warn("CIFS: server netbiosname longer than 15 truncated.\n"); + pr_warn("server netbiosname longer than 15 truncated\n"); break; case Opt_ver: /* version of mount userspace tools, not dialect */ @@ -2366,17 +2369,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, /* If interface changes in mount.cifs bump to new ver */ if (strncasecmp(string, "1", 1) == 0) { if (strlen(string) > 1) { - pr_warn("Bad mount helper ver=%s. Did " - "you want SMB1 (CIFS) dialect " - "and mean to type vers=1.0 " - "instead?\n", string); + pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n", + string); goto cifs_parse_mount_err; } /* This is the default */ break; } /* For all other value, error */ - pr_warn("CIFS: Invalid mount helper version specified\n"); + pr_warn("Invalid mount helper version specified\n"); goto cifs_parse_mount_err; case Opt_vers: /* protocol version (dialect) */ @@ -2419,7 +2420,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } if (!sloppy && invalid) { - pr_err("CIFS: Unknown mount option \"%s\"\n", invalid); + pr_err("Unknown mount option \"%s\"\n", invalid); goto cifs_parse_mount_err; } @@ -2455,7 +2456,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, slash = strchr(&vol->UNC[2], '\\'); len = slash - &vol->UNC[2]; if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) { - pr_err("Unable to determine destination address.\n"); + pr_err("Unable to determine destination address\n"); goto cifs_parse_mount_err; } } @@ -2466,20 +2467,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (uid_specified) vol->override_uid = override_uid; else if (override_uid == 1) - pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n"); + pr_notice("ignoring forceuid mount option specified with no uid= option\n"); if (gid_specified) vol->override_gid = override_gid; else if (override_gid == 1) - pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n"); + pr_notice("ignoring forcegid mount option specified with no gid= option\n"); if (got_version == false) - pr_warn_once("No dialect specified on mount. Default has changed" - " to a more secure dialect, SMB2.1 or later (e.g. " - "SMB3.1.1), from CIFS (SMB1). To use the less secure " - "SMB1 dialect to access old servers which do not " - "support SMB3.1.1 (or even SMB3 or SMB2.1) specify " - "vers=1.0 on mount.\n"); + pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n"); kfree(mountdata_copy); return 0; @@ -2496,8 +2492,8 @@ cifs_parse_mount_err: * specified, or if srcaddr is specified and * matches the IP address of the rhs argument. */ -static bool -srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs) +bool +cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs) { switch (srcaddr->sa_family) { case AF_UNSPEC: @@ -2588,7 +2584,7 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr, return false; /* don't expect to be here */ } - if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) + if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr)) return false; return true; @@ -3197,8 +3193,8 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) strlen(ses->domainName), GFP_KERNEL); if (!vol->domainname) { - cifs_dbg(FYI, "Unable to allocate %zd bytes for " - "domain\n", len); + cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n", + len); rc = -ENOMEM; kfree(vol->username); vol->username = NULL; @@ -3363,6 +3359,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) return 0; if (tcon->no_lease != volume_info->no_lease) return 0; + if (tcon->nodelete != volume_info->nodelete) + return 0; return 1; } @@ -3519,10 +3517,9 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) if (volume_info->linux_ext) { if (ses->server->posix_ext_supported) { tcon->posix_extensions = true; - printk_once(KERN_WARNING - "SMB3.11 POSIX Extensions are experimental\n"); + pr_warn_once("SMB3.11 POSIX Extensions are experimental\n"); } else { - cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n"); + cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n"); rc = -EOPNOTSUPP; goto out_fail; } @@ -3580,6 +3577,16 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n"); } + if (volume_info->no_lease) { + if (ses->server->vals->protocol_id == 0) { + cifs_dbg(VFS, + "SMB2 or later required for nolease option\n"); + rc = -EOPNOTSUPP; + goto out_fail; + } else + tcon->no_lease = volume_info->no_lease; + } + /* * We can have only one retry value for a connection to a share so for * resources mounted more than once to the same server share the last @@ -3588,8 +3595,8 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) tcon->retry = volume_info->retry; tcon->nocase = volume_info->nocase; tcon->nohandlecache = volume_info->nohandlecache; + tcon->nodelete = volume_info->nodelete; tcon->local_lease = volume_info->local_lease; - tcon->no_lease = volume_info->no_lease; INIT_LIST_HEAD(&tcon->pending_opens); spin_lock(&cifs_tcp_ses_lock); @@ -4736,8 +4743,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, rc = cifs_are_all_path_components_accessible(server, xid, tcon, cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); if (rc != 0) { - cifs_server_dbg(VFS, "cannot query dirs between root and final path, " - "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); + cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; rc = 0; } diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index a67f88bf7ae1..df81c718d2fa 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -198,7 +198,7 @@ static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer, if (c != '0') return -EINVAL; - cifs_dbg(FYI, "clearing dfs cache"); + cifs_dbg(FYI, "clearing dfs cache\n"); down_write(&htable_rw_lock); flush_cache_ents(); @@ -234,8 +234,8 @@ static inline void dump_tgts(const struct cache_entry *ce) static inline void dump_ce(const struct cache_entry *ce) { - cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," - "interlink=%s,path_consumed=%d,expired=%s\n", ce->path, + cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,interlink=%s,path_consumed=%d,expired=%s\n", + ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ce->etime.tv_nsec, IS_INTERLINK_SET(ce->flags) ? "yes" : "no", @@ -453,11 +453,11 @@ static void remove_oldest_entry(void) } if (!to_del) { - cifs_dbg(FYI, "%s: no entry to remove", __func__); + cifs_dbg(FYI, "%s: no entry to remove\n", __func__); return; } - cifs_dbg(FYI, "%s: removing entry", __func__); + cifs_dbg(FYI, "%s: removing entry\n", __func__); dump_ce(to_del); flush_cache_ent(to_del); } @@ -696,8 +696,8 @@ static int __dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, } if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) { - cifs_dbg(FYI, "%s: reached max cache size (%d)", __func__, - CACHE_MAX_ENTRIES); + cifs_dbg(FYI, "%s: reached max cache size (%d)\n", + __func__, CACHE_MAX_ENTRIES); down_write(&htable_rw_lock); remove_oldest_entry(); up_write(&htable_rw_lock); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 17a4f49c34f5..8277859d12a3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -857,7 +857,7 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) tcon->need_reopen_files = false; - cifs_dbg(FYI, "Reopen persistent handles"); + cifs_dbg(FYI, "Reopen persistent handles\n"); INIT_LIST_HEAD(&tmp_list); /* list all files open on tree connection, reopen resilient handles */ @@ -1853,7 +1853,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, unsigned int xid; struct dentry *dentry = open_file->dentry; struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry)); - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n", write_size, *offset, dentry); @@ -2056,7 +2056,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) rc = cifs_get_writable_file(cifs_inode, flags, &cfile); if (rc) - cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc); + cifs_dbg(FYI, "Couldn't find writable handle rc=%d\n", rc); return cfile; } @@ -2292,8 +2292,6 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, struct address_space *mapping, struct writeback_control *wbc) { int rc; - struct TCP_Server_Info *server = - tlink_tcon(wdata->cfile->tlink)->ses->server; wdata->sync_mode = wbc->sync_mode; wdata->nr_pages = nr_pages; @@ -2305,14 +2303,15 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz; wdata->pid = wdata->cfile->pid; - rc = adjust_credits(server, &wdata->credits, wdata->bytes); + rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes); if (rc) return rc; if (wdata->cfile->invalidHandle) rc = -EAGAIN; else - rc = server->ops->async_writev(wdata, cifs_writedata_release); + rc = wdata->server->ops->async_writev(wdata, + cifs_writedata_release); return rc; } @@ -2349,7 +2348,8 @@ static int cifs_writepages(struct address_space *mapping, range_whole = true; scanned = true; } - server = cifs_sb_master_tcon(cifs_sb)->ses->server; + server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses); + retry: while (!done && index <= end) { unsigned int i, nr_pages, found_pages, wsize; @@ -2403,6 +2403,7 @@ retry: wdata->credits = credits_on_stack; wdata->cfile = cfile; + wdata->server = server; cfile = NULL; if (!wdata->cfile) { @@ -2806,8 +2807,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, unsigned int wsize; struct cifs_credits credits; int rc; - struct TCP_Server_Info *server = - tlink_tcon(wdata->cfile->tlink)->ses->server; + struct TCP_Server_Info *server = wdata->server; do { if (wdata->cfile->invalidHandle) { @@ -2893,7 +2893,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, else pid = current->tgid; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); xid = get_xid(); do { @@ -2923,11 +2923,9 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, from, &pagevec, cur_len, &start); if (result < 0) { cifs_dbg(VFS, - "direct_writev couldn't get user pages " - "(rc=%zd) iter type %d iov_offset %zd " - "count %zd\n", - result, iov_iter_type(from), - from->iov_offset, from->count); + "direct_writev couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n", + result, iov_iter_type(from), + from->iov_offset, from->count); dump_stack(); rc = result; @@ -2999,6 +2997,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, wdata->nr_pages = nr_pages; wdata->offset = (__u64)offset; wdata->cfile = cifsFileInfo_get(open_file); + wdata->server = server; wdata->pid = pid; wdata->bytes = cur_len; wdata->pagesz = PAGE_SIZE; @@ -3540,8 +3539,10 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, unsigned int rsize; struct cifs_credits credits; int rc; - struct TCP_Server_Info *server = - tlink_tcon(rdata->cfile->tlink)->ses->server; + struct TCP_Server_Info *server; + + /* XXX: should we pick a new channel here? */ + server = rdata->server; do { if (rdata->cfile->invalidHandle) { @@ -3620,7 +3621,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, size_t start; struct iov_iter direct_iov = ctx->iter; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) pid = open_file->pid; @@ -3654,12 +3655,10 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, cur_len, &start); if (result < 0) { cifs_dbg(VFS, - "couldn't get user pages (rc=%zd)" - " iter type %d" - " iov_offset %zd count %zd\n", - result, iov_iter_type(&direct_iov), - direct_iov.iov_offset, - direct_iov.count); + "Couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n", + result, iov_iter_type(&direct_iov), + direct_iov.iov_offset, + direct_iov.count); dump_stack(); rc = result; @@ -3706,6 +3705,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, rdata->tailsz = PAGE_SIZE; } + rdata->server = server; rdata->cfile = cifsFileInfo_get(open_file); rdata->nr_pages = npages; rdata->offset = offset; @@ -4018,7 +4018,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) unsigned int xid; char *cur_offset; struct cifsFileInfo *open_file; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; int buf_type = CIFS_NO_BUFFER; __u32 pid; @@ -4035,7 +4035,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) } open_file = file->private_data; tcon = tlink_tcon(open_file->tlink); - server = tcon->ses->server; + server = cifs_pick_channel(tcon->ses); if (!server->ops->sync_read) { free_xid(xid); @@ -4074,6 +4074,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) io_parms.tcon = tcon; io_parms.offset = *offset; io_parms.length = current_read_size; + io_parms.server = server; rc = server->ops->sync_read(xid, &open_file->fid, &io_parms, &bytes_read, &cur_offset, &buf_type); @@ -4376,7 +4377,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, pid = current->tgid; rc = 0; - server = tlink_tcon(open_file->tlink)->ses->server; + server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n", __func__, file, mapping, num_pages); @@ -4447,6 +4448,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } rdata->cfile = cifsFileInfo_get(open_file); + rdata->server = server; rdata->mapping = mapping; rdata->offset = offset; rdata->bytes = bytes; @@ -4828,7 +4830,7 @@ static int cifs_swap_activate(struct swap_info_struct *sis, } *span = sis->pages; - printk_once(KERN_WARNING "Swap support over SMB3 is experimental\n"); + pr_warn_once("Swap support over SMB3 is experimental\n"); /* * TODO: consider adding ACL (or documenting how) to prevent other diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 115d28e7c219..5072bcaf4be1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -448,7 +448,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, struct cifs_tcon *tcon; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; char buf[24]; unsigned int bytes_read; char *pbuf; @@ -1156,7 +1156,7 @@ struct inode *cifs_root_iget(struct super_block *sb) /* some servers mistakenly claim POSIX support */ if (rc != -EOPNOTSUPP) goto iget_no_retry; - cifs_dbg(VFS, "server does not support POSIX extensions"); + cifs_dbg(VFS, "server does not support POSIX extensions\n"); tcon->unix_ext = false; } @@ -1419,6 +1419,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) xid = get_xid(); + if (tcon->nodelete) { + rc = -EACCES; + goto unlink_out; + } + /* Unlink can be called from rename so we can not take the * sb->s_vfs_rename_mutex here */ full_path = build_path_from_dentry(dentry); @@ -1747,6 +1752,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) goto rmdir_exit; } + if (tcon->nodelete) { + rc = -EACCES; + cifs_put_tlink(tlink); + goto rmdir_exit; + } + rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); cifs_put_tlink(tlink); @@ -2000,7 +2011,7 @@ cifs_invalidate_mapping(struct inode *inode) if (inode->i_mapping && inode->i_mapping->nrpages != 0) { rc = invalidate_inode_pages2(inode->i_mapping); if (rc) - cifs_dbg(VFS, "%s: could not invalidate inode %p\n", + cifs_dbg(VFS, "%s: Could not invalidate inode %p\n", __func__, inode); } diff --git a/fs/cifs/link.c b/fs/cifs/link.c index a25ef35b023e..c381d2d03ef6 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -308,7 +308,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int oplock = 0; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; int buf_type = CIFS_NO_BUFFER; FILE_ALL_INFO file_info; @@ -352,7 +352,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int oplock = 0; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; oparms.tcon = tcon; oparms.cifs_sb = cifs_sb; @@ -389,7 +389,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int rc; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; int buf_type = CIFS_NO_BUFFER; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; @@ -450,7 +450,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int rc; struct cifs_fid fid; struct cifs_open_parms oparms; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct kvec iov[2]; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 550ce9020a3e..56791a692c8b 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -32,6 +32,9 @@ #include "cifs_unicode.h" #include "smb2pdu.h" #include "cifsfs.h" +#ifdef CONFIG_CIFS_DFS_UPCALL +#include "dns_resolve.h" +#endif extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; @@ -421,7 +424,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) if (data_offset > len - sizeof(struct file_notify_information)) { - cifs_dbg(FYI, "invalid data_offset %u\n", + cifs_dbg(FYI, "Invalid data_offset %u\n", data_offset); return true; } @@ -449,7 +452,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) large dirty files cached on the client */ if ((NT_STATUS_INVALID_HANDLE) == le32_to_cpu(pSMB->hdr.Status.CifsError)) { - cifs_dbg(FYI, "invalid handle on oplock break\n"); + cifs_dbg(FYI, "Invalid handle on oplock break\n"); return true; } else if (ERRbadfid == le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { @@ -530,9 +533,9 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; cifs_sb->mnt_cifs_serverino_autodisabled = true; - cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s.\n", + cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n", tcon ? tcon->treeName : "new server"); - cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS).\n"); + cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n"); cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n"); } @@ -874,7 +877,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) while (count && npages < max_pages) { rc = iov_iter_get_pages(iter, pages, count, max_pages, &start); if (rc < 0) { - cifs_dbg(VFS, "couldn't get user pages (rc=%zd)\n", rc); + cifs_dbg(VFS, "Couldn't get user pages (rc=%zd)\n", rc); break; } @@ -933,7 +936,7 @@ cifs_alloc_hash(const char *name, *shash = crypto_alloc_shash(name, 0, 0); if (IS_ERR(*shash)) { - cifs_dbg(VFS, "could not allocate crypto %s\n", name); + cifs_dbg(VFS, "Could not allocate crypto %s\n", name); rc = PTR_ERR(*shash); *shash = NULL; *sdesc = NULL; @@ -1083,6 +1086,51 @@ void cifs_put_tcp_super(struct super_block *sb) } #ifdef CONFIG_CIFS_DFS_UPCALL +int match_target_ip(struct TCP_Server_Info *server, + const char *share, size_t share_len, + bool *result) +{ + int rc; + char *target, *tip = NULL; + struct sockaddr tipaddr; + + *result = false; + + target = kzalloc(share_len + 3, GFP_KERNEL); + if (!target) { + rc = -ENOMEM; + goto out; + } + + scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share); + + cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2); + + rc = dns_resolve_server_name_to_ip(target, &tip); + if (rc < 0) + goto out; + + cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip); + + if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) { + cifs_dbg(VFS, "%s: failed to convert target ip address\n", + __func__); + rc = -EINVAL; + goto out; + } + + *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, + &tipaddr); + cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); + rc = 0; + +out: + kfree(target); + kfree(tip); + + return rc; +} + static void tcon_super_cb(struct super_block *sb, void *arg) { struct super_cb_data *sd = arg; diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 9b41436fb8db..b7ca4960d4ca 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -957,15 +957,15 @@ struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) sec = 2 * st->TwoSeconds; min = st->Minutes; if ((sec > 59) || (min > 59)) - cifs_dbg(VFS, "illegal time min %d sec %lld\n", min, sec); + cifs_dbg(VFS, "Invalid time min %d sec %lld\n", min, sec); sec += (min * 60); sec += 60 * 60 * st->Hours; if (st->Hours > 24) - cifs_dbg(VFS, "illegal hours %d\n", st->Hours); + cifs_dbg(VFS, "Invalid hours %d\n", st->Hours); day = sd->Day; month = sd->Month; if (day < 1 || day > 31 || month < 1 || month > 12) { - cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, day); + cifs_dbg(VFS, "Invalid date, month %d day: %d\n", month, day); day = clamp(day, 1, 31); month = clamp(month, 1, 12); } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 50f776a8d4ba..6df0922e7e30 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -53,7 +53,7 @@ static void dump_cifs_file_struct(struct file *file, char *label) return; } if (cf->invalidHandle) - cifs_dbg(FYI, "invalid handle\n"); + cifs_dbg(FYI, "Invalid handle\n"); if (cf->srch_inf.endOfSearch) cifs_dbg(FYI, "end of search\n"); if (cf->srch_inf.emptyDir) @@ -246,7 +246,7 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info, */ fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT; - cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o", + cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o\n", le32_to_cpu(info->DeviceId), le32_to_cpu(info->ReparseTag), le32_to_cpu(info->Mode)); @@ -478,7 +478,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset); if (old_entry + next_offset < old_entry) { - cifs_dbg(VFS, "invalid offset %u\n", next_offset); + cifs_dbg(VFS, "Invalid offset %u\n", next_offset); return NULL; } new_entry = old_entry + next_offset; @@ -515,7 +515,7 @@ static void cifs_fill_dirent_posix(struct cifs_dirent *de, /* payload should have already been checked at this point */ if (posix_info_parse(info, NULL, &parsed) < 0) { - cifs_dbg(VFS, "invalid POSIX info payload"); + cifs_dbg(VFS, "Invalid POSIX info payload\n"); return; } @@ -968,7 +968,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) } else if (current_entry != NULL) { cifs_dbg(FYI, "entry %lld found\n", ctx->pos); } else { - cifs_dbg(FYI, "could not find entry\n"); + cifs_dbg(FYI, "Could not find entry\n"); goto rddir2_exit; } cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 43a88e26d26b..5d05bd2822d2 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -122,7 +122,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses) tries++; if (tries > 3*ses->chan_max) { - cifs_dbg(FYI, "too many attempt at opening channels (%d channels left to open)\n", + cifs_dbg(FYI, "too many channel open attempts (%d channels left to open)\n", left); break; } @@ -150,6 +150,22 @@ int cifs_try_adding_channels(struct cifs_ses *ses) return ses->chan_count - old_chan_count; } +/* + * If server is a channel of ses, return the corresponding enclosing + * cifs_chan otherwise return NULL. + */ +struct cifs_chan * +cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server) +{ + int i; + + for (i = 0; i < ses->chan_count; i++) { + if (ses->chans[i].server == server) + return &ses->chans[i]; + } + return NULL; +} + int cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) { @@ -162,12 +178,14 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) int rc; unsigned int xid = get_xid(); - cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ", - ses, iface->speed, iface->rdma_capable ? "yes" : "no"); if (iface->sockaddr.ss_family == AF_INET) - cifs_dbg(FYI, "ip:%pI4)\n", &ipv4->sin_addr); + cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n", + ses, iface->speed, iface->rdma_capable ? "yes" : "no", + &ipv4->sin_addr); else - cifs_dbg(FYI, "ip:%pI6)\n", &ipv6->sin6_addr); + cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n", + ses, iface->speed, iface->rdma_capable ? "yes" : "no", + &ipv6->sin6_addr); /* * Setup a smb_vol with mostly the same info as the existing @@ -198,7 +216,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) vol.UNC = unc; vol.prepath = ""; - /* Re-use same version as master connection */ + /* Reuse same version as master connection */ vol.vals = ses->server->vals; vol.ops = ses->server->ops; @@ -229,7 +247,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) mutex_lock(&ses->session_mutex); - chan = &ses->chans[ses->chan_count]; + chan = ses->binding_chan = &ses->chans[ses->chan_count]; chan->server = cifs_get_tcp_session(&vol); if (IS_ERR(chan->server)) { rc = PTR_ERR(chan->server); @@ -261,7 +279,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) goto out; /* success, put it on the list - * XXX: sharing ses between 2 tcp server is not possible, the + * XXX: sharing ses between 2 tcp servers is not possible, the * way "internal" linked lists works in linux makes element * only able to belong to one list * @@ -274,6 +292,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) atomic_set(&ses->chan_seq, 0); out: ses->binding = false; + ses->binding_chan = NULL; mutex_unlock(&ses->session_mutex); if (rc && chan->server) @@ -569,15 +588,15 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); tilen = le16_to_cpu(pblob->TargetInfoArray.Length); if (tioffset > blob_len || tioffset + tilen > blob_len) { - cifs_dbg(VFS, "tioffset + tilen too high %u + %u", - tioffset, tilen); + cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n", + tioffset, tilen); return -EINVAL; } if (tilen) { ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen, GFP_KERNEL); if (!ses->auth_key.response) { - cifs_dbg(VFS, "Challenge target info alloc failure"); + cifs_dbg(VFS, "Challenge target info alloc failure\n"); return -ENOMEM; } ses->auth_key.len = tilen; @@ -970,7 +989,7 @@ sess_auth_lanman(struct sess_data *sess_data) /* Calculate hash with password and copy into bcc_ptr. * Encryption Key (stored as in cryptkey) gets used if the - * security mode bit in Negottiate Protocol response states + * security mode bit in Negotiate Protocol response states * to use challenge/response method (i.e. Password bit is 1). */ rc = calc_lanman_hash(ses->password, ses->server->cryptkey, @@ -1303,9 +1322,8 @@ sess_auth_kerberos(struct sess_data *sess_data) * sending us a response in an expected form */ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { - cifs_dbg(VFS, - "incorrect version of cifs.upcall (expected %d but got %d)", - CIFS_SPNEGO_UPCALL_VERSION, msg->version); + cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n", + CIFS_SPNEGO_UPCALL_VERSION, msg->version); rc = -EKEYREJECTED; goto out_put_spnego_key; } @@ -1313,8 +1331,8 @@ sess_auth_kerberos(struct 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", - msg->sesskey_len); + cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n", + msg->sesskey_len); rc = -ENOMEM; goto out_put_spnego_key; } @@ -1657,8 +1675,7 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data) type = cifs_select_sectype(ses->server, 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; } diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index b130efaf8feb..197ed455e657 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -247,7 +247,7 @@ check2ndT2(char *buf) /* check for plausible wct, bcc and t2 data and parm sizes */ /* check for parm and data offset going beyond end of smb */ if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ - cifs_dbg(FYI, "invalid transact2 word count\n"); + cifs_dbg(FYI, "Invalid transact2 word count\n"); return -EINVAL; } diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index a8c301ae00ed..0a116fc490a9 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -47,6 +47,18 @@ free_set_inf_compound(struct smb_rqst *rqst) } +struct cop_vars { + struct cifs_open_parms oparms; + struct kvec rsp_iov[3]; + struct smb_rqst rqst[3]; + struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; + struct kvec qi_iov[1]; + struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; + struct kvec close_iov[1]; + struct smb2_file_rename_info rename_info; + struct smb2_file_link_info link_info; +}; + static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, @@ -54,35 +66,36 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, __u32 create_options, umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile) { + struct cop_vars *vars = NULL; + struct kvec *rsp_iov; + struct smb_rqst *rqst; int rc; __le16 *utf16_path = NULL; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; - struct cifs_open_parms oparms; struct cifs_fid fid; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server; int num_rqst = 0; - struct smb_rqst rqst[3]; int resp_buftype[3]; - struct kvec rsp_iov[3]; - struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; - struct kvec qi_iov[1]; - struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; - struct kvec close_iov[1]; struct smb2_query_info_rsp *qi_rsp = NULL; int flags = 0; __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0}; unsigned int size[2]; void *data[2]; - struct smb2_file_rename_info rename_info; - struct smb2_file_link_info link_info; int len; + vars = kzalloc(sizeof(*vars), GFP_ATOMIC); + if (vars == NULL) + return -ENOMEM; + rqst = &vars->rqst[0]; + rsp_iov = &vars->rsp_iov[0]; + + server = cifs_pick_channel(ses); + if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; - memset(rqst, 0, sizeof(rqst)); resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; - memset(rsp_iov, 0, sizeof(rsp_iov)); /* We already have a handle so we can skip the open */ if (cfile) @@ -95,19 +108,18 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, goto finished; } - memset(&oparms, 0, sizeof(struct cifs_open_parms)); - oparms.tcon = tcon; - oparms.desired_access = desired_access; - oparms.disposition = create_disposition; - oparms.create_options = cifs_create_options(cifs_sb, create_options); - oparms.fid = &fid; - oparms.reconnect = false; - oparms.mode = mode; - - memset(&open_iov, 0, sizeof(open_iov)); - rqst[num_rqst].rq_iov = open_iov; + vars->oparms.tcon = tcon; + vars->oparms.desired_access = desired_access; + vars->oparms.disposition = create_disposition; + vars->oparms.create_options = cifs_create_options(cifs_sb, create_options); + vars->oparms.fid = &fid; + vars->oparms.reconnect = false; + vars->oparms.mode = mode; + + rqst[num_rqst].rq_iov = &vars->open_iov[0]; rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE; - rc = SMB2_open_init(tcon, &rqst[num_rqst], &oplock, &oparms, + rc = SMB2_open_init(tcon, server, + &rqst[num_rqst], &oplock, &vars->oparms, utf16_path); kfree(utf16_path); if (rc) @@ -121,12 +133,12 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, /* Operation */ switch (command) { case SMB2_OP_QUERY_INFO: - memset(&qi_iov, 0, sizeof(qi_iov)); - rqst[num_rqst].rq_iov = qi_iov; + rqst[num_rqst].rq_iov = &vars->qi_iov[0]; rqst[num_rqst].rq_nvec = 1; if (cfile) - rc = SMB2_query_info_init(tcon, &rqst[num_rqst], + rc = SMB2_query_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, FILE_ALL_INFORMATION, @@ -134,10 +146,11 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 0, NULL); else { - rc = SMB2_query_info_init(tcon, &rqst[num_rqst], + rc = SMB2_query_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, - FILE_ALL_INFORMATION, + FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 0, NULL); @@ -164,14 +177,14 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path); break; case SMB2_OP_RMDIR: - memset(&si_iov, 0, sizeof(si_iov)); - rqst[num_rqst].rq_iov = si_iov; + rqst[num_rqst].rq_iov = &vars->si_iov[0]; rqst[num_rqst].rq_nvec = 1; size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ data[0] = &delete_pending[0]; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -182,14 +195,14 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path); break; case SMB2_OP_SET_EOF: - memset(&si_iov, 0, sizeof(si_iov)); - rqst[num_rqst].rq_iov = si_iov; + rqst[num_rqst].rq_iov = &vars->si_iov[0]; rqst[num_rqst].rq_nvec = 1; size[0] = 8; /* sizeof __le64 */ data[0] = ptr; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -200,8 +213,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); break; case SMB2_OP_SET_INFO: - memset(&si_iov, 0, sizeof(si_iov)); - rqst[num_rqst].rq_iov = si_iov; + rqst[num_rqst].rq_iov = &vars->si_iov[0]; rqst[num_rqst].rq_nvec = 1; @@ -209,13 +221,15 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, data[0] = ptr; if (cfile) - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); else { - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_BASIC_INFORMATION, @@ -233,30 +247,31 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, full_path); break; case SMB2_OP_RENAME: - memset(&si_iov, 0, sizeof(si_iov)); - rqst[num_rqst].rq_iov = si_iov; + rqst[num_rqst].rq_iov = &vars->si_iov[0]; rqst[num_rqst].rq_nvec = 2; len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); - rename_info.ReplaceIfExists = 1; - rename_info.RootDirectory = 0; - rename_info.FileNameLength = cpu_to_le32(len); + vars->rename_info.ReplaceIfExists = 1; + vars->rename_info.RootDirectory = 0; + vars->rename_info.FileNameLength = cpu_to_le32(len); size[0] = sizeof(struct smb2_file_rename_info); - data[0] = &rename_info; + data[0] = &vars->rename_info; size[1] = len + 2 /* null */; data[1] = (__le16 *)ptr; if (cfile) - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], cfile->fid.persistent_fid, cfile->fid.volatile_fid, current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); else { - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -271,23 +286,23 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); break; case SMB2_OP_HARDLINK: - memset(&si_iov, 0, sizeof(si_iov)); - rqst[num_rqst].rq_iov = si_iov; + rqst[num_rqst].rq_iov = &vars->si_iov[0]; rqst[num_rqst].rq_nvec = 2; len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); - link_info.ReplaceIfExists = 0; - link_info.RootDirectory = 0; - link_info.FileNameLength = cpu_to_le32(len); + vars->link_info.ReplaceIfExists = 0; + vars->link_info.RootDirectory = 0; + vars->link_info.FileNameLength = cpu_to_le32(len); size[0] = sizeof(struct smb2_file_link_info); - data[0] = &link_info; + data[0] = &vars->link_info; size[1] = len + 2 /* null */; data[1] = (__le16 *)ptr; - rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -308,10 +323,10 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, if (cfile) goto after_close; /* Close */ - memset(&close_iov, 0, sizeof(close_iov)); - rqst[num_rqst].rq_iov = close_iov; + rqst[num_rqst].rq_iov = &vars->close_iov[0]; rqst[num_rqst].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, + rc = SMB2_close_init(tcon, server, + &rqst[num_rqst], COMPOUND_FID, COMPOUND_FID, false); smb2_set_related(&rqst[num_rqst]); if (rc) @@ -322,11 +337,13 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, if (cfile) { cifsFileInfo_put(cfile); cfile = NULL; - rc = compound_send_recv(xid, ses, flags, num_rqst - 2, + rc = compound_send_recv(xid, ses, server, + flags, num_rqst - 2, &rqst[1], &resp_buftype[1], &rsp_iov[1]); } else - rc = compound_send_recv(xid, ses, flags, num_rqst, + rc = compound_send_recv(xid, ses, server, + flags, num_rqst, rqst, resp_buftype, rsp_iov); @@ -336,8 +353,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, SMB2_open_free(&rqst[0]); 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; } @@ -420,6 +436,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); + kfree(vars); return rc; } diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 497afb0b9960..6a39451973f8 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -110,14 +110,14 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, /* Make sure that negotiate contexts start after gss security blob */ nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); if (nc_offset < non_ctxlen) { - printk_once(KERN_WARNING "invalid negotiate context offset\n"); + pr_warn_once("Invalid negotiate context offset\n"); return 0; } size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; /* Verify that at least minimal negotiate contexts fit within frame */ if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { - printk_once(KERN_WARNING "negotiate context goes beyond end\n"); + pr_warn_once("negotiate context goes beyond end\n"); return 0; } @@ -190,14 +190,14 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) return 1; if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { - cifs_dbg(VFS, "Illegal structure size %u\n", + cifs_dbg(VFS, "Invalid structure size %u\n", le16_to_cpu(shdr->StructureSize)); return 1; } command = le16_to_cpu(shdr->Command); if (command >= NUMBER_OF_SMB2_COMMANDS) { - cifs_dbg(VFS, "Illegal SMB2 command %d\n", command); + cifs_dbg(VFS, "Invalid SMB2 command %d\n", command); return 1; } @@ -205,7 +205,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 || pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { /* error packets have 9 byte structure size */ - cifs_dbg(VFS, "Illegal response size %u for command %d\n", + cifs_dbg(VFS, "Invalid response size %u for command %d\n", le16_to_cpu(pdu->StructureSize2), command); return 1; } else if (command == SMB2_OPLOCK_BREAK_HE @@ -213,7 +213,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) && (le16_to_cpu(pdu->StructureSize2) != 44) && (le16_to_cpu(pdu->StructureSize2) != 36)) { /* special case for SMB2.1 lease break message */ - cifs_dbg(VFS, "Illegal response size %d for oplock break\n", + cifs_dbg(VFS, "Invalid response size %d for oplock break\n", le16_to_cpu(pdu->StructureSize2)); return 1; } @@ -864,14 +864,14 @@ ok: d = server->secmech.sdescsha512; rc = crypto_shash_init(&d->shash); if (rc) { - cifs_dbg(VFS, "%s: could not init sha512 shash\n", __func__); + cifs_dbg(VFS, "%s: Could not init sha512 shash\n", __func__); return rc; } rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash, SMB2_PREAUTH_HASH_SIZE); if (rc) { - cifs_dbg(VFS, "%s: could not update sha512 shash\n", __func__); + cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__); return rc; } @@ -879,7 +879,7 @@ ok: rc = crypto_shash_update(&d->shash, iov[i].iov_base, iov[i].iov_len); if (rc) { - cifs_dbg(VFS, "%s: could not update sha512 shash\n", + cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__); return rc; } @@ -887,7 +887,7 @@ ok: rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash); if (rc) { - cifs_dbg(VFS, "%s: could not finalize sha512 shash\n", + cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n", __func__); return rc; } diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 300ade2acc41..736d86b8a910 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -80,7 +80,7 @@ smb2_add_credits(struct TCP_Server_Info *server, if (*val > 65000) { *val = 65000; /* Don't get near 64K credits, avoid srv bugs */ - printk_once(KERN_WARNING "server overflowed SMB3 credits\n"); + pr_warn_once("server overflowed SMB3 credits\n"); } server->in_flight--; if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP) @@ -709,7 +709,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, oparms.fid = pfid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, &utf16_path); if (rc) goto oshr_free; smb2_set_next_command(tcon, &rqst[0]); @@ -718,7 +719,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qi_iov; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + @@ -728,7 +730,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, smb2_set_related(&rqst[1]); - rc = compound_send_recv(xid, ses, flags, 2, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 2, rqst, resp_buftype, rsp_iov); mutex_lock(&tcon->crfid.fid_mutex); @@ -768,8 +771,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, if (rc) { if (rc == -EREMCHG) { tcon->need_reconnect = true; - printk_once(KERN_WARNING "server share %s deleted\n", - tcon->treeName); + pr_warn_once("server share %s deleted\n", + tcon->treeName); } goto oshr_exit; } @@ -1103,6 +1106,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb) { struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); __le16 *utf16_path = NULL; int ea_name_len = strlen(ea_name); int flags = 0; @@ -1191,7 +1195,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto sea_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -1217,7 +1222,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, size[0] = len; data[0] = ea; - rc = SMB2_set_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_set_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); @@ -1229,10 +1235,12 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, memset(&close_iov, 0, sizeof(close_iov)); rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); /* no need to bump num_remote_opens because handle immediately closed */ @@ -1453,6 +1461,16 @@ req_res_key_exit: return rc; } +struct iqi_vars { + struct smb_rqst rqst[3]; + struct kvec rsp_iov[3]; + struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; + struct kvec qi_iov[1]; + struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; + struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; + struct kvec close_iov[1]; +}; + static int smb2_ioctl_query_info(const unsigned int xid, struct cifs_tcon *tcon, @@ -1460,7 +1478,11 @@ smb2_ioctl_query_info(const unsigned int xid, __le16 *path, int is_dir, unsigned long p) { + struct iqi_vars *vars; + struct smb_rqst *rqst; + struct kvec *rsp_iov; struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); char __user *arg = (char __user *)p; struct smb_query_info qi; struct smb_query_info __user *pqi; @@ -1469,45 +1491,47 @@ smb2_ioctl_query_info(const unsigned int xid, struct smb2_query_info_rsp *qi_rsp = NULL; struct smb2_ioctl_rsp *io_rsp = NULL; void *buffer = NULL; - struct smb_rqst rqst[3]; int resp_buftype[3]; - struct kvec rsp_iov[3]; - struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; struct cifs_open_parms oparms; u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_fid fid; - struct kvec qi_iov[1]; - struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; - struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; - struct kvec close_iov[1]; unsigned int size[2]; void *data[2]; int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR; - memset(rqst, 0, sizeof(rqst)); + vars = kzalloc(sizeof(*vars), GFP_ATOMIC); + if (vars == NULL) + return -ENOMEM; + rqst = &vars->rqst[0]; + rsp_iov = &vars->rsp_iov[0]; + resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; - memset(rsp_iov, 0, sizeof(rsp_iov)); if (copy_from_user(&qi, arg, sizeof(struct smb_query_info))) - return -EFAULT; + goto e_fault; - if (qi.output_buffer_length > 1024) + if (qi.output_buffer_length > 1024) { + kfree(vars); return -EINVAL; + } - if (!ses || !(ses->server)) + if (!ses || !server) { + kfree(vars); return -EIO; + } if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; buffer = memdup_user(arg + sizeof(struct smb_query_info), qi.output_buffer_length); - if (IS_ERR(buffer)) + if (IS_ERR(buffer)) { + kfree(vars); return PTR_ERR(buffer); + } /* Open */ - memset(&open_iov, 0, sizeof(open_iov)); - rqst[0].rq_iov = open_iov; + rqst[0].rq_iov = &vars->open_iov[0]; rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; memset(&oparms, 0, sizeof(oparms)); @@ -1538,7 +1562,8 @@ smb2_ioctl_query_info(const unsigned int xid, oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; } - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, path); if (rc) goto iqinf_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -1549,11 +1574,11 @@ smb2_ioctl_query_info(const unsigned int xid, if (!capable(CAP_SYS_ADMIN)) rc = -EPERM; else { - memset(&io_iov, 0, sizeof(io_iov)); - rqst[1].rq_iov = io_iov; + rqst[1].rq_iov = &vars->io_iov[0]; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst[1], + rc = SMB2_ioctl_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, qi.info_type, true, buffer, qi.output_buffer_length, @@ -1566,31 +1591,32 @@ smb2_ioctl_query_info(const unsigned int xid, if (!capable(CAP_SYS_ADMIN)) rc = -EPERM; else { - memset(&si_iov, 0, sizeof(si_iov)); - rqst[1].rq_iov = si_iov; + rqst[1].rq_iov = &vars->si_iov[0]; rqst[1].rq_nvec = 1; size[0] = 8; data[0] = buffer; - rc = SMB2_set_info_init(tcon, &rqst[1], + rc = SMB2_set_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, current->tgid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, 0, data, size); } } else if (qi.flags == PASSTHRU_QUERY_INFO) { - memset(&qi_iov, 0, sizeof(qi_iov)); - rqst[1].rq_iov = qi_iov; + rqst[1].rq_iov = &vars->qi_iov[0]; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, qi.file_info_class, qi.info_type, qi.additional_information, qi.input_buffer_length, qi.output_buffer_length, buffer); } else { /* unknown flags */ - cifs_tcon_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); + cifs_tcon_dbg(VFS, "Invalid passthru query flags: 0x%x\n", + qi.flags); rc = -EINVAL; } @@ -1600,16 +1626,17 @@ smb2_ioctl_query_info(const unsigned int xid, smb2_set_related(&rqst[1]); /* Close */ - memset(&close_iov, 0, sizeof(close_iov)); - rqst[2].rq_iov = close_iov; + rqst[2].rq_iov = &vars->close_iov[0]; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto iqinf_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); if (rc) goto iqinf_exit; @@ -1650,6 +1677,7 @@ smb2_ioctl_query_info(const unsigned int xid, } iqinf_exit: + kfree(vars); kfree(buffer); SMB2_open_free(&rqst[0]); if (qi.flags & PASSTHRU_FSCTL) @@ -1720,7 +1748,7 @@ smb2_copychunk_range(const unsigned int xid, if (rc == 0) { if (ret_data_len != sizeof(struct copychunk_ioctl_rsp)) { - cifs_tcon_dbg(VFS, "invalid cchunk response size\n"); + cifs_tcon_dbg(VFS, "Invalid cchunk response size\n"); rc = -EIO; goto cchunk_out; } @@ -1734,12 +1762,12 @@ smb2_copychunk_range(const unsigned int xid, */ if (le32_to_cpu(retbuf->TotalBytesWritten) > le32_to_cpu(pcchunk->Length)) { - cifs_tcon_dbg(VFS, "invalid copy chunk response\n"); + cifs_tcon_dbg(VFS, "Invalid copy chunk response\n"); rc = -EIO; goto cchunk_out; } if (le32_to_cpu(retbuf->ChunksWritten) != 1) { - cifs_tcon_dbg(VFS, "invalid num chunks written\n"); + cifs_tcon_dbg(VFS, "Invalid num chunks written\n"); rc = -EIO; goto cchunk_out; } @@ -2160,6 +2188,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_open_parms oparms; struct smb2_query_directory_rsp *qd_rsp = NULL; struct smb2_create_rsp *op_rsp = NULL; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (!utf16_path) @@ -2184,7 +2213,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto qdf_free; smb2_set_next_command(tcon, &rqst[0]); @@ -2197,7 +2227,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qd_iov; rqst[1].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; - rc = SMB2_query_directory_init(xid, tcon, &rqst[1], + rc = SMB2_query_directory_init(xid, tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, 0, srch_inf->info_level); if (rc) @@ -2205,7 +2236,8 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, smb2_set_related(&rqst[1]); - rc = compound_send_recv(xid, tcon->ses, flags, 2, rqst, + rc = compound_send_recv(xid, tcon->ses, server, + flags, 2, rqst, resp_buftype, rsp_iov); /* If the open failed there is nothing to do */ @@ -2410,6 +2442,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb) { struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = cifs_pick_channel(ses); int flags = 0; struct smb_rqst rqst[3]; int resp_buftype[3]; @@ -2440,7 +2473,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto qic_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -2449,7 +2483,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = qi_iov; rqst[1].rq_nvec = 1; - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, COMPOUND_FID, + rc = SMB2_query_info_init(tcon, server, + &rqst[1], COMPOUND_FID, COMPOUND_FID, class, type, 0, output_len, 0, NULL); @@ -2462,19 +2497,21 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto qic_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, ses, flags, 3, rqst, + rc = compound_send_recv(xid, ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); if (rc) { free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); if (rc == -EREMCHG) { tcon->need_reconnect = true; - printk_once(KERN_WARNING "server share %s deleted\n", - tcon->treeName); + pr_warn_once("server share %s deleted\n", + tcon->treeName); } goto qic_exit; } @@ -2754,15 +2791,15 @@ parse_reparse_point(struct reparse_data_buffer *buf, struct cifs_sb_info *cifs_sb) { if (plen < sizeof(struct reparse_data_buffer)) { - cifs_dbg(VFS, "reparse buffer is too small. Must be " - "at least 8 bytes but was %d\n", plen); + cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n", + plen); return -EIO; } if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(struct reparse_data_buffer)) { - cifs_dbg(VFS, "srv returned invalid reparse buf " - "length: %d\n", plen); + cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n", + plen); return -EIO; } @@ -2777,8 +2814,8 @@ parse_reparse_point(struct reparse_data_buffer *buf, (struct reparse_symlink_data_buffer *)buf, plen, target_path, cifs_sb); default: - cifs_dbg(VFS, "srv returned unknown symlink buffer " - "tag:0x%08x\n", le32_to_cpu(buf->ReparseTag)); + cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n", + le32_to_cpu(buf->ReparseTag)); return -EOPNOTSUPP; } } @@ -2799,6 +2836,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, struct kvec err_iov = {NULL, 0}; struct smb2_err_rsp *err_buf = NULL; struct smb2_symlink_err_rsp *symlink; + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); unsigned int sub_len; unsigned int sub_offset; unsigned int print_len; @@ -2844,7 +2882,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, oparms.fid = &fid; oparms.reconnect = false; - rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); + rc = SMB2_open_init(tcon, server, + &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto querty_exit; smb2_set_next_command(tcon, &rqst[0]); @@ -2855,7 +2894,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rqst[1].rq_iov = io_iov; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; - rc = SMB2_ioctl_init(tcon, &rqst[1], fid.persistent_fid, + rc = SMB2_ioctl_init(tcon, server, + &rqst[1], fid.persistent_fid, fid.volatile_fid, FSCTL_GET_REPARSE_POINT, true /* is_fctl */, NULL, 0, CIFSMaxBufSize - @@ -2873,13 +2913,15 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rqst[2].rq_iov = close_iov; rqst[2].rq_nvec = 1; - rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + rc = SMB2_close_init(tcon, server, + &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto querty_exit; smb2_set_related(&rqst[2]); - rc = compound_send_recv(xid, tcon->ses, flags, 3, rqst, + rc = compound_send_recv(xid, tcon->ses, server, + flags, 3, rqst, resp_buftype, rsp_iov); create_rsp = rsp_iov[0].iov_base; @@ -4573,7 +4615,7 @@ smb2_make_node(unsigned int xid, struct inode *inode, struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); int rc = -EPERM; FILE_ALL_INFO *buf = NULL; - struct cifs_io_parms io_parms; + struct cifs_io_parms io_parms = {0}; __u32 oplock = 0; struct cifs_fid fid; struct cifs_open_parms oparms; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index b30aa3cdd845..ded96b529a4d 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,7 @@ 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_response_size, SMB2_MAX_BUFFER_SIZE)); if (is_fsctl) req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); else @@ -2960,12 +3011,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 +3027,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 +3046,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 +3141,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 +3150,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 +3182,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 +3192,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 +3208,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 +3283,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 +3315,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 +3326,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 +3379,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 +3391,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 +3401,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) { @@ -3426,15 +3487,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 +3524,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 +3533,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 +3544,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 +3643,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 +3683,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 +3711,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 +3741,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 +3758,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 +3793,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 +3828,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 +3885,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 +3897,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 +3978,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 +4022,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 +4054,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 +4072,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 +4129,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 +4193,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 +4215,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 +4363,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 +4409,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 +4584,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 +4600,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 +4727,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 +4744,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 +4758,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 +4803,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 +4866,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 +4886,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 +4896,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 +4960,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 +4968,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 +4990,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 +5034,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 +5045,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 +5079,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 +5097,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 +5130,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 +5148,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 +5181,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 +5202,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 +5215,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 +5269,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 +5300,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 +5346,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 +5373,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; diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 10acf90f858d..3b0e6acf9d7d 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -143,8 +143,17 @@ struct smb2_transform_hdr { __u64 SessionId; } __packed; +/* See MS-SMB2 2.2.42 */ +struct smb2_compression_transform_hdr { + __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ + __le32 OriginalCompressedSegmentSize; + __le16 CompressionAlgorithm; + __le16 Flags; + __le16 Length; /* if chained it is length, else offset */ +} __packed; + /* See MS-SMB2 2.2.42.1 */ -struct compression_playload_header { +struct compression_payload_header { __le16 AlgorithmId; __le16 Reserved; __le32 Length; @@ -333,7 +342,7 @@ struct smb2_encryption_neg_context { #define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002) #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003) /* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */ -#define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) +#define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */ /* Compression Flags */ #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000) diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 087d5f14320b..71ba74792c9e 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -143,7 +143,9 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, struct smb2_file_all_info *buf, struct create_posix_rsp *posix, struct kvec *err_iov, int *resp_buftype); -extern int SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +extern int 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); extern void SMB2_open_free(struct smb_rqst *rqst); @@ -151,7 +153,9 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, u32 maxoutlen, char **out_data, u32 *plen /* returned data len */); -extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +extern int 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); @@ -165,19 +169,25 @@ extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, struct smb2_file_network_open_info *pbuf); extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); -extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, - u64 persistent_fid, u64 volatile_fid, bool query_attrs); +extern int 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); extern void SMB2_close_free(struct smb_rqst *rqst); extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id); extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, u64 persistent_file_id, u64 volatile_file_id); extern void SMB2_flush_free(struct smb_rqst *rqst); extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_file_id, u64 volatile_file_id, struct smb2_file_all_info *data); -extern int SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +extern int 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, @@ -201,6 +211,7 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, int index, struct cifs_search_info *srch_inf); extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon, + struct TCP_Server_Info *server, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, int index, int info_level); @@ -208,7 +219,9 @@ extern void SMB2_query_directory_free(struct smb_rqst *rqst); extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 pid, __le64 *eof); -extern int SMB2_set_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +extern int 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); diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 1a5834a5d597..b029ed31ef91 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -294,15 +294,12 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc) static void dump_smbd_negotiate_resp(struct smbd_negotiate_resp *resp) { - log_rdma_event(INFO, "resp message min_version %u max_version %u " - "negotiated_version %u credits_requested %u " - "credits_granted %u status %u max_readwrite_size %u " - "preferred_send_size %u max_receive_size %u " - "max_fragmented_size %u\n", - resp->min_version, resp->max_version, resp->negotiated_version, - resp->credits_requested, resp->credits_granted, resp->status, - resp->max_readwrite_size, resp->preferred_send_size, - resp->max_receive_size, resp->max_fragmented_size); + log_rdma_event(INFO, "resp message min_version %u max_version %u negotiated_version %u credits_requested %u credits_granted %u status %u max_readwrite_size %u preferred_send_size %u max_receive_size %u max_fragmented_size %u\n", + resp->min_version, resp->max_version, + resp->negotiated_version, resp->credits_requested, + resp->credits_granted, resp->status, + resp->max_readwrite_size, resp->preferred_send_size, + resp->max_receive_size, resp->max_fragmented_size); } /* @@ -450,10 +447,9 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) struct smbd_connection *info = response->info; int data_length = 0; - log_rdma_recv(INFO, "response=%p type=%d wc status=%d wc opcode %d " - "byte_len=%d pkey_index=%x\n", - response, response->type, wc->status, wc->opcode, - wc->byte_len, wc->pkey_index); + log_rdma_recv(INFO, "response=%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%x\n", + response, response->type, wc->status, wc->opcode, + wc->byte_len, wc->pkey_index); if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { log_rdma_recv(INFO, "wc->status=%d opcode=%d\n", @@ -519,12 +515,11 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) wake_up_interruptible(&info->wait_send_queue); } - log_incoming(INFO, "data flags %d data_offset %d " - "data_length %d remaining_data_length %d\n", - le16_to_cpu(data_transfer->flags), - le32_to_cpu(data_transfer->data_offset), - le32_to_cpu(data_transfer->data_length), - le32_to_cpu(data_transfer->remaining_data_length)); + log_incoming(INFO, "data flags %d data_offset %d data_length %d remaining_data_length %d\n", + le16_to_cpu(data_transfer->flags), + le32_to_cpu(data_transfer->data_offset), + le32_to_cpu(data_transfer->data_length), + le32_to_cpu(data_transfer->remaining_data_length)); /* Send a KEEP_ALIVE response right away if requested */ info->keep_alive_requested = KEEP_ALIVE_NONE; @@ -632,14 +627,10 @@ static int smbd_ia_open( } if (!frwr_is_supported(&info->id->device->attrs)) { - log_rdma_event(ERR, - "Fast Registration Work Requests " - "(FRWR) is not supported\n"); - log_rdma_event(ERR, - "Device capability flags = %llx " - "max_fast_reg_page_list_len = %u\n", - info->id->device->attrs.device_cap_flags, - info->id->device->attrs.max_fast_reg_page_list_len); + log_rdma_event(ERR, "Fast Registration Work Requests (FRWR) is not supported\n"); + log_rdma_event(ERR, "Device capability flags = %llx max_fast_reg_page_list_len = %u\n", + info->id->device->attrs.device_cap_flags, + info->id->device->attrs.max_fast_reg_page_list_len); rc = -EPROTONOSUPPORT; goto out2; } @@ -898,13 +889,12 @@ wait_send_queue: packet->remaining_data_length = cpu_to_le32(remaining_data_length); packet->padding = 0; - log_outgoing(INFO, "credits_requested=%d credits_granted=%d " - "data_offset=%d data_length=%d remaining_data_length=%d\n", - le16_to_cpu(packet->credits_requested), - le16_to_cpu(packet->credits_granted), - le32_to_cpu(packet->data_offset), - le32_to_cpu(packet->data_length), - le32_to_cpu(packet->remaining_data_length)); + log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n", + le16_to_cpu(packet->credits_requested), + le16_to_cpu(packet->credits_granted), + le32_to_cpu(packet->data_offset), + le32_to_cpu(packet->data_length), + le32_to_cpu(packet->remaining_data_length)); /* Map the packet to DMA */ header_length = sizeof(struct smbd_data_transfer); @@ -1078,11 +1068,9 @@ static int smbd_negotiate(struct smbd_connection *info) response->type = SMBD_NEGOTIATE_RESP; rc = smbd_post_recv(info, response); - log_rdma_event(INFO, - "smbd_post_recv rc=%d iov.addr=%llx iov.length=%x " - "iov.lkey=%x\n", - rc, response->sge.addr, - response->sge.length, response->sge.lkey); + log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=%llx iov.length=%x iov.lkey=%x\n", + rc, response->sge.addr, + response->sge.length, response->sge.lkey); if (rc) return rc; @@ -1540,25 +1528,19 @@ static struct smbd_connection *_smbd_get_connection( if (smbd_send_credit_target > info->id->device->attrs.max_cqe || smbd_send_credit_target > info->id->device->attrs.max_qp_wr) { - log_rdma_event(ERR, - "consider lowering send_credit_target = %d. " - "Possible CQE overrun, device " - "reporting max_cpe %d max_qp_wr %d\n", - smbd_send_credit_target, - info->id->device->attrs.max_cqe, - info->id->device->attrs.max_qp_wr); + log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n", + smbd_send_credit_target, + info->id->device->attrs.max_cqe, + info->id->device->attrs.max_qp_wr); goto config_failed; } if (smbd_receive_credit_max > info->id->device->attrs.max_cqe || smbd_receive_credit_max > info->id->device->attrs.max_qp_wr) { - log_rdma_event(ERR, - "consider lowering receive_credit_max = %d. " - "Possible CQE overrun, device " - "reporting max_cpe %d max_qp_wr %d\n", - smbd_receive_credit_max, - info->id->device->attrs.max_cqe, - info->id->device->attrs.max_qp_wr); + log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n", + smbd_receive_credit_max, + info->id->device->attrs.max_cqe, + info->id->device->attrs.max_qp_wr); goto config_failed; } @@ -1865,11 +1847,9 @@ again: to_read -= to_copy; data_read += to_copy; - log_read(INFO, "_get_first_reassembly memcpy %d bytes " - "data_transfer_length-offset=%d after that " - "to_read=%d data_read=%d offset=%d\n", - to_copy, data_length - offset, - to_read, data_read, offset); + log_read(INFO, "_get_first_reassembly memcpy %d bytes data_transfer_length-offset=%d after that to_read=%d data_read=%d offset=%d\n", + to_copy, data_length - offset, + to_read, data_read, offset); } spin_lock_irq(&info->reassembly_queue_lock); @@ -1878,10 +1858,9 @@ again: spin_unlock_irq(&info->reassembly_queue_lock); info->first_entry_offset = offset; - log_read(INFO, "returning to thread data_read=%d " - "reassembly_data_length=%d first_entry_offset=%d\n", - data_read, info->reassembly_data_length, - info->first_entry_offset); + log_read(INFO, "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n", + data_read, info->reassembly_data_length, + info->first_entry_offset); read_rfc1002_done: return data_read; } @@ -1952,7 +1931,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) if (iov_iter_rw(&msg->msg_iter) == WRITE) { /* It's a bug in upper layer to get there */ - cifs_dbg(VFS, "CIFS: invalid msg iter dir %u\n", + cifs_dbg(VFS, "Invalid msg iter dir %u\n", iov_iter_rw(&msg->msg_iter)); rc = -EINVAL; goto out; @@ -1974,7 +1953,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg) default: /* It's a bug in upper layer to get there */ - cifs_dbg(VFS, "CIFS: invalid msg type %d\n", + cifs_dbg(VFS, "Invalid msg type %d\n", iov_iter_type(&msg->msg_iter)); rc = -EINVAL; } @@ -2043,10 +2022,9 @@ next_rqst: dump_smb(iov[i].iov_base, iov[i].iov_len); - log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d " - "rq_tailsz=%d buflen=%lu\n", - rqst_idx, rqst->rq_nvec, rqst->rq_npages, rqst->rq_pagesz, - rqst->rq_tailsz, smb_rqst_len(server, rqst)); + log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n", + rqst_idx, rqst->rq_nvec, rqst->rq_npages, rqst->rq_pagesz, + rqst->rq_tailsz, smb_rqst_len(server, rqst)); start = i = 0; buflen = 0; @@ -2056,11 +2034,9 @@ next_rqst: if (i > start) { remaining_data_length -= (buflen-iov[i].iov_len); - log_write(INFO, "sending iov[] from start=%d " - "i=%d nvecs=%d " - "remaining_data_length=%d\n", - start, i, i-start, - remaining_data_length); + log_write(INFO, "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n", + start, i, i - start, + remaining_data_length); rc = smbd_post_send_data( info, &iov[start], i-start, remaining_data_length); @@ -2069,10 +2045,9 @@ next_rqst: } else { /* iov[start] is too big, break it */ nvecs = (buflen+max_iov_size-1)/max_iov_size; - log_write(INFO, "iov[%d] iov_base=%p buflen=%d" - " break to %d vectors\n", - start, iov[start].iov_base, - buflen, nvecs); + log_write(INFO, "iov[%d] iov_base=%p buflen=%d break to %d vectors\n", + start, iov[start].iov_base, + buflen, nvecs); for (j = 0; j < nvecs; j++) { vec.iov_base = (char *)iov[start].iov_base + @@ -2084,11 +2059,9 @@ next_rqst: max_iov_size*(nvecs-1); remaining_data_length -= vec.iov_len; log_write(INFO, - "sending vec j=%d iov_base=%p" - " iov_len=%zu " - "remaining_data_length=%d\n", - j, vec.iov_base, vec.iov_len, - remaining_data_length); + "sending vec j=%d iov_base=%p iov_len=%zu remaining_data_length=%d\n", + j, vec.iov_base, vec.iov_len, + remaining_data_length); rc = smbd_post_send_data( info, &vec, 1, remaining_data_length); @@ -2106,11 +2079,9 @@ next_rqst: if (i == rqst->rq_nvec) { /* send out all remaining vecs */ remaining_data_length -= buflen; - log_write(INFO, - "sending iov[] from start=%d i=%d " - "nvecs=%d remaining_data_length=%d\n", - start, i, i-start, - remaining_data_length); + log_write(INFO, "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n", + start, i, i - start, + remaining_data_length); rc = smbd_post_send_data(info, &iov[start], i-start, remaining_data_length); if (rc) @@ -2134,10 +2105,9 @@ next_rqst: if (j == nvecs-1) size = buflen - j*max_iov_size; remaining_data_length -= size; - log_write(INFO, "sending pages i=%d offset=%d size=%d" - " remaining_data_length=%d\n", - i, j*max_iov_size+offset, size, - remaining_data_length); + log_write(INFO, "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n", + i, j * max_iov_size + offset, size, + remaining_data_length); rc = smbd_post_send_page( info, rqst->rq_pages[i], j*max_iov_size + offset, @@ -2211,11 +2181,9 @@ static void smbd_mr_recovery_work(struct work_struct *work) info->pd, info->mr_type, info->max_frmr_depth); if (IS_ERR(smbdirect_mr->mr)) { - log_rdma_mr(ERR, - "ib_alloc_mr failed mr_type=%x " - "max_frmr_depth=%x\n", - info->mr_type, - info->max_frmr_depth); + log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n", + info->mr_type, + info->max_frmr_depth); smbd_disconnect_rdma_connection(info); continue; } @@ -2278,9 +2246,8 @@ static int allocate_mr_list(struct smbd_connection *info) smbdirect_mr->mr = ib_alloc_mr(info->pd, info->mr_type, info->max_frmr_depth); if (IS_ERR(smbdirect_mr->mr)) { - log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x " - "max_frmr_depth=%x\n", - info->mr_type, info->max_frmr_depth); + log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n", + info->mr_type, info->max_frmr_depth); goto out; } smbdirect_mr->sgl = kcalloc( diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 99760063e000..d11e31064679 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -112,7 +112,7 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) #ifdef CONFIG_CIFS_STATS2 now = jiffies; if (now < midEntry->when_alloc) - cifs_server_dbg(VFS, "invalid mid allocation time\n"); + cifs_server_dbg(VFS, "Invalid mid allocation time\n"); roundtrip_time = now - midEntry->when_alloc; if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { @@ -151,12 +151,12 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid, midEntry->when_sent, midEntry->when_received); if (cifsFYI & CIFS_TIMER) { - pr_debug(" CIFS slow rsp: cmd %d mid %llu", - midEntry->command, midEntry->mid); - cifs_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n", - now - midEntry->when_alloc, - now - midEntry->when_sent, - now - midEntry->when_received); + pr_debug("slow rsp: cmd %d mid %llu", + midEntry->command, midEntry->mid); + cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n", + now - midEntry->when_alloc, + now - midEntry->when_sent, + now - midEntry->when_received); } } #endif @@ -473,8 +473,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, return -ENOMEM; if (!server->ops->init_transform_rq) { - cifs_server_dbg(VFS, "Encryption requested but transform " - "callback is missing\n"); + cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n"); return -EIO; } @@ -989,8 +988,35 @@ cifs_cancelled_callback(struct mid_q_entry *mid) DeleteMidQEntry(mid); } +/* + * Return a channel (master if none) of @ses that can be used to send + * regular requests. + * + * If we are currently binding a new channel (negprot/sess.setup), + * return the new incomplete channel. + */ +struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses) +{ + uint index = 0; + + if (!ses) + return NULL; + + if (!ses->binding) { + /* round robin */ + if (ses->chan_count > 1) { + index = (uint)atomic_inc_return(&ses->chan_seq); + index %= ses->chan_count; + } + return ses->chans[index].server; + } else { + return cifs_ses_server(ses); + } +} + int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, const int flags, const int num_rqst, struct smb_rqst *rqst, int *resp_buf_type, struct kvec *resp_iov) { @@ -1002,30 +1028,17 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, }; unsigned int instance; char *buf; - struct TCP_Server_Info *server; optype = flags & CIFS_OP_MASK; for (i = 0; i < num_rqst; i++) resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */ - if ((ses == NULL) || (ses->server == NULL)) { + if (!ses || !ses->server || !server) { cifs_dbg(VFS, "Null session\n"); return -EIO; } - if (!ses->binding) { - uint index = 0; - - if (ses->chan_count > 1) { - index = (uint)atomic_inc_return(&ses->chan_seq); - index %= ses->chan_count; - } - server = ses->chans[index].server; - } else { - server = cifs_ses_server(ses); - } - if (server->tcpStatus == CifsExiting) return -ENOENT; @@ -1220,11 +1233,12 @@ out: int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov) { - return compound_send_recv(xid, ses, flags, 1, rqst, resp_buf_type, - resp_iov); + return compound_send_recv(xid, ses, server, flags, 1, + rqst, resp_buf_type, resp_iov); } int @@ -1259,7 +1273,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, rqst.rq_iov = new_iov; rqst.rq_nvec = n_vec + 1; - rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); + rc = cifs_send_recv(xid, ses, ses->server, + &rqst, resp_buf_type, flags, resp_iov); if (n_vec + 1 > CIFS_MAX_IOV_SIZE) kfree(new_iov); return rc; @@ -1296,8 +1311,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, use ses->maxReq */ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", - len); + cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", + len); return -EIO; } @@ -1437,8 +1452,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, use ses->maxReq */ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cifs_tcon_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", - len); + cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", + len); return -EIO; } |