diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-05 16:40:53 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-05 16:40:53 -0700 |
commit | 3803d5e4d3ce2600ffddc16a1999798bc719042d (patch) | |
tree | 4bd971c4931a8f11d9608548bdd7fd304d07881d /fs | |
parent | 9daa0a27a0bce6596be287fb1df372ff80bb1087 (diff) | |
parent | 331cc667a99c633abbbebeab4675beae713fb331 (diff) |
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')
-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; } |