Commit 3803d5e4 authored by Linus Torvalds's avatar Linus Torvalds

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()
  ...
parents 9daa0a27 331cc667
...@@ -221,6 +221,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -221,6 +221,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
int i, j; int i, j;
const char *security_types[] = {"Unspecified", "LANMAN", "NTLM",
"NTLMv2", "RawNTLMSSP", "Kerberos"};
seq_puts(m, seq_puts(m,
"Display Internal CIFS Data Structures for Debugging\n" "Display Internal CIFS Data Structures for Debugging\n"
...@@ -375,6 +377,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -375,6 +377,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
ses->ses_count, ses->serverOS, ses->serverNOS, ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->status); ses->capabilities, ses->status);
} }
seq_printf(m,"Security type: %s\n",
security_types[server->ops->select_sectype(server, ses->sectype)]);
if (server->rdma) if (server->rdma)
seq_printf(m, "RDMA\n\t"); seq_printf(m, "RDMA\n\t");
seq_printf(m, "TCP status: %d Instance: %d\n\tLocal Users To " seq_printf(m, "TCP status: %d Instance: %d\n\tLocal Users To "
......
...@@ -8,6 +8,12 @@ ...@@ -8,6 +8,12 @@
#ifndef _H_CIFS_DEBUG #ifndef _H_CIFS_DEBUG
#define _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_mem(char *label, void *data, int length);
void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info); void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info);
void cifs_dump_mids(struct TCP_Server_Info *); void cifs_dump_mids(struct TCP_Server_Info *);
...@@ -46,92 +52,81 @@ extern int cifsFYI; ...@@ -46,92 +52,81 @@ extern int cifsFYI;
*/ */
/* Information level messages, minor events */ /* Information level messages, minor events */
#define cifs_info_func(ratefunc, fmt, ...) \ #define cifs_info_func(ratefunc, fmt, ...) \
do { \ pr_info_ ## ratefunc(fmt, ##__VA_ARGS__)
pr_info_ ## ratefunc("CIFS: " fmt, ##__VA_ARGS__); \
} while (0)
#define cifs_info(fmt, ...) \ #define cifs_info(fmt, ...) \
do { \ cifs_info_func(ratelimited, fmt, ##__VA_ARGS__)
cifs_info_func(ratelimited, fmt, ##__VA_ARGS__); \
} while (0)
/* information message: e.g., configuration, major event */ /* information message: e.g., configuration, major event */
#define cifs_dbg_func(ratefunc, type, fmt, ...) \ #define cifs_dbg_func(ratefunc, type, fmt, ...) \
do { \ do { \
if ((type) & FYI && cifsFYI & CIFS_INFO) { \ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
pr_debug_ ## ratefunc("%s: " \ pr_debug_ ## ratefunc("%s: " fmt, \
fmt, __FILE__, ##__VA_ARGS__); \ __FILE__, ##__VA_ARGS__); \
} else if ((type) & VFS) { \ } else if ((type) & VFS) { \
pr_err_ ## ratefunc("CIFS VFS: " \ pr_err_ ## ratefunc("VFS: " fmt, ##__VA_ARGS__); \
fmt, ##__VA_ARGS__); \ } else if ((type) & NOISY && (NOISY != 0)) { \
} else if ((type) & NOISY && (NOISY != 0)) { \ pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \
pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \ } \
} \
} while (0) } while (0)
#define cifs_dbg(type, fmt, ...) \ #define cifs_dbg(type, fmt, ...) \
do { \ do { \
if ((type) & ONCE) \ if ((type) & ONCE) \
cifs_dbg_func(once, \ cifs_dbg_func(once, type, fmt, ##__VA_ARGS__); \
type, fmt, ##__VA_ARGS__); \ else \
else \ cifs_dbg_func(ratelimited, type, fmt, ##__VA_ARGS__); \
cifs_dbg_func(ratelimited, \
type, fmt, ##__VA_ARGS__); \
} while (0) } while (0)
#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ #define cifs_server_dbg_func(ratefunc, type, fmt, ...) \
do { \ do { \
const char *sn = ""; \ const char *sn = ""; \
if (server && server->hostname) \ if (server && server->hostname) \
sn = server->hostname; \ sn = server->hostname; \
if ((type) & FYI && cifsFYI & CIFS_INFO) { \ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \ pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \
__FILE__, sn, ##__VA_ARGS__); \ __FILE__, sn, ##__VA_ARGS__); \
} else if ((type) & VFS) { \ } else if ((type) & VFS) { \
pr_err_ ## ratefunc("CIFS VFS: \\\\%s " fmt, \ pr_err_ ## ratefunc("VFS: \\\\%s " fmt, \
sn, ##__VA_ARGS__); \ sn, ##__VA_ARGS__); \
} else if ((type) & NOISY && (NOISY != 0)) { \ } else if ((type) & NOISY && (NOISY != 0)) { \
pr_debug_ ## ratefunc("\\\\%s " fmt, \ pr_debug_ ## ratefunc("\\\\%s " fmt, \
sn, ##__VA_ARGS__); \ sn, ##__VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define cifs_server_dbg(type, fmt, ...) \ #define cifs_server_dbg(type, fmt, ...) \
do { \ do { \
if ((type) & ONCE) \ if ((type) & ONCE) \
cifs_server_dbg_func(once, \ cifs_server_dbg_func(once, type, fmt, ##__VA_ARGS__); \
type, fmt, ##__VA_ARGS__); \ else \
else \ cifs_server_dbg_func(ratelimited, type, fmt, \
cifs_server_dbg_func(ratelimited, \ ##__VA_ARGS__); \
type, fmt, ##__VA_ARGS__); \
} while (0) } while (0)
#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \ #define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \
do { \ do { \
const char *tn = ""; \ const char *tn = ""; \
if (tcon && tcon->treeName) \ if (tcon && tcon->treeName) \
tn = tcon->treeName; \ tn = tcon->treeName; \
if ((type) & FYI && cifsFYI & CIFS_INFO) { \ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
pr_debug_ ## ratefunc("%s: %s " fmt, \ pr_debug_ ## ratefunc("%s: %s " fmt, \
__FILE__, tn, ##__VA_ARGS__); \ __FILE__, tn, ##__VA_ARGS__); \
} else if ((type) & VFS) { \ } else if ((type) & VFS) { \
pr_err_ ## ratefunc("CIFS VFS: %s " fmt, \ pr_err_ ## ratefunc("VFS: %s " fmt, tn, ##__VA_ARGS__); \
tn, ##__VA_ARGS__); \ } else if ((type) & NOISY && (NOISY != 0)) { \
} else if ((type) & NOISY && (NOISY != 0)) { \ pr_debug_ ## ratefunc("%s " fmt, tn, ##__VA_ARGS__); \
pr_debug_ ## ratefunc("%s " fmt, \ } \
tn, ##__VA_ARGS__); \
} \
} while (0) } while (0)
#define cifs_tcon_dbg(type, fmt, ...) \ #define cifs_tcon_dbg(type, fmt, ...) \
do { \ do { \
if ((type) & ONCE) \ if ((type) & ONCE) \
cifs_tcon_dbg_func(once, \ cifs_tcon_dbg_func(once, type, fmt, ##__VA_ARGS__); \
type, fmt, ##__VA_ARGS__); \ else \
else \ cifs_tcon_dbg_func(ratelimited, type, fmt, \
cifs_tcon_dbg_func(ratelimited, \ ##__VA_ARGS__); \
type, fmt, ##__VA_ARGS__); \
} while (0) } while (0)
/* /*
...@@ -159,9 +154,7 @@ do { \ ...@@ -159,9 +154,7 @@ do { \
} while (0) } while (0)
#define cifs_info(fmt, ...) \ #define cifs_info(fmt, ...) \
do { \ pr_info(fmt, ##__VA_ARGS__)
pr_info("CIFS: "fmt, ##__VA_ARGS__); \
} while (0)
#endif #endif
#endif /* _H_CIFS_DEBUG */ #endif /* _H_CIFS_DEBUG */
...@@ -520,7 +520,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, ...@@ -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); rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
if (rc) { if (rc) {
cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__); cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
return rc; return rc;
} }
...@@ -624,7 +624,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) ...@@ -624,7 +624,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
if (rc) { if (rc) {
cifs_dbg(VFS, "%s: could not init hmacmd5\n", __func__); cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
return rc; return rc;
} }
...@@ -723,7 +723,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -723,7 +723,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
/* calculate ntlmv2_hash */ /* calculate ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
if (rc) { 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; goto unlock;
} }
...@@ -783,7 +783,7 @@ calc_seckey(struct cifs_ses *ses) ...@@ -783,7 +783,7 @@ calc_seckey(struct cifs_ses *ses)
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL); ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
if (!ctx_arc4) { if (!ctx_arc4) {
cifs_dbg(VFS, "could not allocate arc4 context\n"); cifs_dbg(VFS, "Could not allocate arc4 context\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -534,6 +534,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -534,6 +534,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",signloosely"); seq_puts(s, ",signloosely");
if (tcon->nocase) if (tcon->nocase)
seq_puts(s, ",nocase"); seq_puts(s, ",nocase");
if (tcon->nodelete)
seq_puts(s, ",nodelete");
if (tcon->local_lease) if (tcon->local_lease)
seq_puts(s, ",locallease"); seq_puts(s, ",locallease");
if (tcon->retry) if (tcon->retry)
......
...@@ -156,5 +156,5 @@ extern int cifs_truncate_page(struct address_space *mapping, loff_t from); ...@@ -156,5 +156,5 @@ extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.26" #define CIFS_VERSION "2.27"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -562,6 +562,7 @@ struct smb_vol { ...@@ -562,6 +562,7 @@ struct smb_vol {
bool override_gid:1; bool override_gid:1;
bool dynperm:1; bool dynperm:1;
bool noperm:1; bool noperm:1;
bool nodelete:1;
bool mode_ace:1; bool mode_ace:1;
bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool no_psx_acl:1; /* set if posix acl support should be disabled */
bool cifs_acl:1; bool cifs_acl:1;
...@@ -1029,6 +1030,7 @@ struct cifs_ses { ...@@ -1029,6 +1030,7 @@ struct cifs_ses {
#define CIFS_MAX_CHANNELS 16 #define CIFS_MAX_CHANNELS 16
struct cifs_chan chans[CIFS_MAX_CHANNELS]; struct cifs_chan chans[CIFS_MAX_CHANNELS];
struct cifs_chan *binding_chan;
size_t chan_count; size_t chan_count;
size_t chan_max; size_t chan_max;
atomic_t chan_seq; /* round robin state */ atomic_t chan_seq; /* round robin state */
...@@ -1036,23 +1038,31 @@ struct cifs_ses { ...@@ -1036,23 +1038,31 @@ struct cifs_ses {
/* /*
* When binding a new channel, we need to access the channel which isn't fully * 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 static inline
struct cifs_chan *cifs_ses_binding_channel(struct cifs_ses *ses) struct cifs_chan *cifs_ses_binding_channel(struct cifs_ses *ses)
{ {
if (ses->binding) if (ses->binding)
return &ses->chans[ses->chan_count]; return ses->binding_chan;
else else
return NULL; 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 static inline
struct TCP_Server_Info *cifs_ses_server(struct cifs_ses *ses) struct TCP_Server_Info *cifs_ses_server(struct cifs_ses *ses)
{ {
if (ses->binding) if (ses->binding)
return ses->chans[ses->chan_count].server; return ses->binding_chan->server;
else else
return ses->server; return ses->server;
} }
...@@ -1136,6 +1146,7 @@ struct cifs_tcon { ...@@ -1136,6 +1146,7 @@ struct cifs_tcon {
bool retry:1; bool retry:1;
bool nocase:1; bool nocase:1;
bool nohandlecache:1; /* if strange server resource prob can turn off */ bool nohandlecache:1; /* if strange server resource prob can turn off */
bool nodelete:1;
bool seal:1; /* transport encryption for this mounted share */ bool seal:1; /* transport encryption for this mounted share */
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
for this mount even if server would support */ for this mount even if server would support */
...@@ -1333,6 +1344,7 @@ struct cifs_io_parms { ...@@ -1333,6 +1344,7 @@ struct cifs_io_parms {
__u64 offset; __u64 offset;
unsigned int length; unsigned int length;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
}; };
struct cifs_aio_ctx { struct cifs_aio_ctx {
...@@ -1380,6 +1392,7 @@ struct cifs_readdata { ...@@ -1380,6 +1392,7 @@ struct cifs_readdata {
struct cifs_readdata *rdata, struct cifs_readdata *rdata,
struct iov_iter *iter); struct iov_iter *iter);
struct kvec iov[2]; struct kvec iov[2];
struct TCP_Server_Info *server;
#ifdef CONFIG_CIFS_SMB_DIRECT #ifdef CONFIG_CIFS_SMB_DIRECT
struct smbd_mr *mr; struct smbd_mr *mr;
#endif #endif
...@@ -1406,6 +1419,7 @@ struct cifs_writedata { ...@@ -1406,6 +1419,7 @@ struct cifs_writedata {
pid_t pid; pid_t pid;
unsigned int bytes; unsigned int bytes;
int result; int result;
struct TCP_Server_Info *server;
#ifdef CONFIG_CIFS_SMB_DIRECT #ifdef CONFIG_CIFS_SMB_DIRECT
struct smbd_mr *mr; struct smbd_mr *mr;
#endif #endif
......
...@@ -45,25 +45,25 @@ extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, ...@@ -45,25 +45,25 @@ extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
unsigned int /* length */); unsigned int /* length */);
extern unsigned int _get_xid(void); extern unsigned int _get_xid(void);
extern void _free_xid(unsigned int); extern void _free_xid(unsigned int);
#define get_xid() \ #define get_xid() \
({ \ ({ \
unsigned int __xid = _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, \ __func__, __xid, \
from_kuid(&init_user_ns, current_fsuid())); \ from_kuid(&init_user_ns, current_fsuid())); \
trace_smb3_enter(__xid, __func__); \ trace_smb3_enter(__xid, __func__); \
__xid; \ __xid; \
}) })
#define free_xid(curr_xid) \ #define free_xid(curr_xid) \
do { \ do { \
_free_xid(curr_xid); \ _free_xid(curr_xid); \
cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \ cifs_dbg(FYI, "VFS: leaving %s (xid = %u) rc = %d\n", \
__func__, curr_xid, (int)rc); \ __func__, curr_xid, (int)rc); \
if (rc) \ if (rc) \
trace_smb3_exit_err(curr_xid, __func__, (int)rc); \ trace_smb3_exit_err(curr_xid, __func__, (int)rc); \
else \ else \
trace_smb3_exit_done(curr_xid, __func__); \ trace_smb3_exit_done(curr_xid, __func__); \
} while (0) } while (0)
extern int init_cifs_idmap(void); extern int init_cifs_idmap(void);
extern void exit_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); ...@@ -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 void cifs_wake_up_task(struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server, extern int cifs_handle_standard(struct TCP_Server_Info *server,
struct mid_q_entry *mid); 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_discard_remaining_data(struct TCP_Server_Info *server);
extern int cifs_call_async(struct TCP_Server_Info *server, extern int cifs_call_async(struct TCP_Server_Info *server,
struct smb_rqst *rqst, struct smb_rqst *rqst,
mid_receive_t *receive, mid_callback_t *callback, mid_receive_t *receive, mid_callback_t *callback,
mid_handle_t *handle, void *cbdata, const int flags, mid_handle_t *handle, void *cbdata, const int flags,
const struct cifs_credits *exist_credits); 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, 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, struct smb_rqst *rqst, int *resp_buf_type,
const int flags, struct kvec *resp_iov); const int flags, struct kvec *resp_iov);
extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, 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, const int flags, const int num_rqst,
struct smb_rqst *rqst, int *resp_buf_type, struct smb_rqst *rqst, int *resp_buf_type,
struct kvec *resp_iov); struct kvec *resp_iov);
...@@ -589,6 +593,8 @@ void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc); ...@@ -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, extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset); 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_try_adding_channels(struct cifs_ses *ses);
int cifs_ses_add_channel(struct cifs_ses *ses, int cifs_ses_add_channel(struct cifs_ses *ses,
struct cifs_server_iface *iface); struct cifs_server_iface *iface);
...@@ -616,6 +622,10 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, ...@@ -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, return dfs_cache_find(xid, ses, nls_codepage, remap, old_path,
referral, NULL); referral, NULL);
} }
int match_target_ip(struct TCP_Server_Info *server,
const char *share, size_t share_len,
bool *result);
#endif #endif
static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
......
...@@ -56,7 +56,7 @@ static int __init cifs_root_setup(char *line) ...@@ -56,7 +56,7 @@ static int __init cifs_root_setup(char *line)
/* len is strlen(unc) + '\0' */ /* len is strlen(unc) + '\0' */
len = s - line + 1; len = s - line + 1;
if (len > sizeof(root_dev)) { 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; return 1;
} }
strlcpy(root_dev, line, len); strlcpy(root_dev, line, len);
...@@ -66,7 +66,7 @@ static int __init cifs_root_setup(char *line) ...@@ -66,7 +66,7 @@ static int __init cifs_root_setup(char *line)
sizeof(root_opts), "%s,%s", sizeof(root_opts), "%s,%s",
DEFAULT_MNT_OPTS, s + 1); DEFAULT_MNT_OPTS, s + 1);
if (n >= sizeof(root_opts)) { 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'; root_opts[sizeof(root_opts)-1] = '\0';
return 1; return 1;
} }
...@@ -83,7 +83,7 @@ __setup("cifsroot=", cifs_root_setup); ...@@ -83,7 +83,7 @@ __setup("cifsroot=", cifs_root_setup);
int __init cifs_root_data(char **dev, char **opts) int __init cifs_root_data(char **dev, char **opts)
{ {
if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) { 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; return -1;
} }
......
...@@ -129,6 +129,7 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc, ...@@ -129,6 +129,7 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
struct cifs_tcon *tcon) struct cifs_tcon *tcon)
{ {
int rc; int rc;
struct TCP_Server_Info *server = tcon->ses->server;
struct dfs_cache_tgt_list tl; struct dfs_cache_tgt_list tl;
struct dfs_cache_tgt_iterator *it = NULL; struct dfs_cache_tgt_iterator *it = NULL;
char *tree; char *tree;
...@@ -141,15 +142,14 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc, ...@@ -141,15 +142,14 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
if (!tree) if (!tree)
return -ENOMEM; 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) { 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; goto out;
} }
...@@ -157,13 +157,13 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc, ...@@ -157,13 +157,13 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
if (rc) if (rc)
goto out; goto out;
extract_unc_hostname(tcon->ses->server->hostname, &tcp_host, extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
&tcp_host_len);
for (it = dfs_cache_get_tgt_iterator(&tl); it; for (it = dfs_cache_get_tgt_iterator(&tl); it;
it = dfs_cache_get_next_tgt(&tl, it)) { it = dfs_cache_get_next_tgt(&tl, it)) {
const char *share, *prefix; const char *share, *prefix;
size_t share_len, prefix_len; size_t share_len, prefix_len;
bool target_match;
rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix,
&prefix_len); &prefix_len);
...@@ -177,19 +177,38 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc, ...@@ -177,19 +177,38 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
if (dfs_host_len != tcp_host_len if (dfs_host_len != tcp_host_len
|| strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { || 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__, __func__,
(int)dfs_host_len, dfs_host, (int)dfs_host_len, dfs_host,
(int)tcp_host_len, tcp_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 (tcon->ipc) {
if (!rc) { scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$",
rc = update_super_prepath(tcon, prefix, prefix_len); (int)share_len, share);
break; 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) if (rc == -EREMOTE)
break; break;
...@@ -262,8 +281,8 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -262,8 +281,8 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
(server->tcpStatus != CifsNeedReconnect), (server->tcpStatus != CifsNeedReconnect),
10 * HZ); 10 * HZ);
if (rc < 0) { if (rc < 0) {
cifs_dbg(FYI, "%s: aborting reconnect due to a received" cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
" signal by the process\n", __func__); __func__);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
...@@ -324,7 +343,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -324,7 +343,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
if (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; goto out;
} }
...@@ -557,7 +576,7 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) ...@@ -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 server requires signing, does client allow it? */
if (srv_sign_required) { if (srv_sign_required) {
if (!mnt_sign_enabled) { 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; return -ENOTSUPP;
} }
server->sign = true; server->sign = true;
...@@ -566,14 +585,14 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) ...@@ -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 client requires signing, does server allow it? */
if (mnt_sign_required) { if (mnt_sign_required) {
if (!srv_sign_enabled) { if (!srv_sign_enabled) {
cifs_dbg(VFS, "Server does not support signing!"); cifs_dbg(VFS, "Server does not support signing!\n");
return -ENOTSUPP; return -ENOTSUPP;
} }
server->sign = true; server->sign = true;
} }
if (cifs_rdma_enabled(server) && server->sign) 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; return 0;
} }
...@@ -703,7 +722,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -703,7 +722,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
if (should_set_ext_sec_flag(ses->sectype)) { 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; pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
} }
...@@ -2375,7 +2394,7 @@ int ...@@ -2375,7 +2394,7 @@ int
CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, struct kvec *iov, int n_vec) unsigned int *nbytes, struct kvec *iov, int n_vec)
{ {
int rc = -EACCES; int rc;
WRITE_REQ *pSMB = NULL; WRITE_REQ *pSMB = NULL;
int wct; int wct;
int smb_hdr_len; int smb_hdr_len;
...@@ -3868,7 +3887,7 @@ CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3868,7 +3887,7 @@ CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
struct file_chattr_info *pfinfo; struct file_chattr_info *pfinfo;
/* BB Do we need a cast or hash here ? */ /* BB Do we need a cast or hash here ? */
if (count != 16) { if (count != 16) {
cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n"); cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
rc = -EIO; rc = -EIO;
goto GetExtAttrOut; goto GetExtAttrOut;
} }
...@@ -4244,7 +4263,7 @@ CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4244,7 +4263,7 @@ CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cifs_dbg(FYI, "Send error in QFileInfo = %d", rc); cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
} else { /* decode response */ } else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr); rc = validate_t2((struct smb_t2_rsp *)pSMBr);
...@@ -4411,7 +4430,7 @@ CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4411,7 +4430,7 @@ CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc); cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
} else { /* decode response */ } else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr); rc = validate_t2((struct smb_t2_rsp *)pSMBr);
...@@ -4493,7 +4512,7 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4493,7 +4512,7 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc); cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
} else { /* decode response */ } else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr); rc = validate_t2((struct smb_t2_rsp *)pSMBr);
...@@ -4913,7 +4932,7 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4913,7 +4932,7 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
struct file_internal_info *pfinfo; struct file_internal_info *pfinfo;
/* BB Do we need a cast or hash here ? */ /* BB Do we need a cast or hash here ? */
if (count < 8) { if (count < 8) {
cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n"); cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
rc = -EIO; rc = -EIO;
goto GetInodeNumOut; goto GetInodeNumOut;
} }
......
This diff is collapsed.
...@@ -198,7 +198,7 @@ static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer, ...@@ -198,7 +198,7 @@ static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer,
if (c != '0') if (c != '0')
return -EINVAL; return -EINVAL;
cifs_dbg(FYI, "clearing dfs cache"); cifs_dbg(FYI, "clearing dfs cache\n");
down_write(&htable_rw_lock); down_write(&htable_rw_lock);
flush_cache_ents(); flush_cache_ents();
...@@ -234,8 +234,8 @@ static inline void dump_tgts(const struct cache_entry *ce) ...@@ -234,8 +234,8 @@ static inline void dump_tgts(const struct cache_entry *ce)
static inline void dump_ce(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," cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,interlink=%s,path_consumed=%d,expired=%s\n",
"interlink=%s,path_consumed=%d,expired=%s\n", ce->path, ce->path,
ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,
ce->etime.tv_nsec, ce->etime.tv_nsec,
IS_INTERLINK_SET(ce->flags) ? "yes" : "no", IS_INTERLINK_SET(ce->flags) ? "yes" : "no",
...@@ -453,11 +453,11 @@ static void remove_oldest_entry(void) ...@@ -453,11 +453,11 @@ static void remove_oldest_entry(void)
} }
if (!to_del) { if (!to_del) {
cifs_dbg(FYI, "%s: no entry to remove", __func__); cifs_dbg(FYI, "%s: no entry to remove\n", __func__);
return; return;
} }
cifs_dbg(FYI, "%s: removing entry", __func__); cifs_dbg(FYI, "%s: removing entry\n", __func__);
dump_ce(to_del); dump_ce(to_del);
flush_cache_ent(to_del); flush_cache_ent(to_del);
} }
...@@ -696,8 +696,8 @@ static int __dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, ...@@ -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) { if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) {
cifs_dbg(FYI, "%s: reached max cache size (%d)", __func__, cifs_dbg(FYI, "%s: reached max cache size (%d)\n",
CACHE_MAX_ENTRIES); __func__, CACHE_MAX_ENTRIES);
down_write(&htable_rw_lock); down_write(&htable_rw_lock);
remove_oldest_entry(); remove_oldest_entry();
up_write(&htable_rw_lock); up_write(&htable_rw_lock);
......
...@@ -857,7 +857,7 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) ...@@ -857,7 +857,7 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
tcon->need_reopen_files = false; tcon->need_reopen_files = false;
cifs_dbg(FYI, "Reopen persistent handles"); cifs_dbg(FYI, "Reopen persistent handles\n");
INIT_LIST_HEAD(&tmp_list); INIT_LIST_HEAD(&tmp_list);
/* list all files open on tree connection, reopen resilient handles */ /* 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, ...@@ -1853,7 +1853,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
unsigned int xid; unsigned int xid;
struct dentry *dentry = open_file->dentry; struct dentry *dentry = open_file->dentry;
struct cifsInodeInfo *cifsi = CIFS_I(d_inode(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", cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n",
write_size, *offset, dentry); write_size, *offset, dentry);
...@@ -2056,7 +2056,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) ...@@ -2056,7 +2056,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)
rc = cifs_get_writable_file(cifs_inode, flags, &cfile); rc = cifs_get_writable_file(cifs_inode, flags, &cfile);
if (rc) 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; return cfile;
} }
...@@ -2292,8 +2292,6 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, ...@@ -2292,8 +2292,6 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages,
struct address_space *mapping, struct writeback_control *wbc) struct address_space *mapping, struct writeback_control *wbc)
{ {
int rc; int rc;
struct TCP_Server_Info *server =
tlink_tcon(wdata->cfile->tlink)->ses->server;
wdata->sync_mode = wbc->sync_mode; wdata->sync_mode = wbc->sync_mode;
wdata->nr_pages = nr_pages; wdata->nr_pages = nr_pages;
...@@ -2305,14 +2303,15 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int 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->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz;
wdata->pid = wdata->cfile->pid; wdata->pid = wdata->cfile->pid;
rc = adjust_credits(server, &wdata->credits, wdata->bytes); rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes);
if (rc) if (rc)
return rc; return rc;
if (wdata->cfile->invalidHandle) if (wdata->cfile->invalidHandle)
rc = -EAGAIN; rc = -EAGAIN;
else else
rc = server->ops->async_writev(wdata, cifs_writedata_release); rc = wdata->server->ops->async_writev(wdata,
cifs_writedata_release);
return rc; return rc;
} }
...@@ -2349,7 +2348,8 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -2349,7 +2348,8 @@ static int cifs_writepages(struct address_space *mapping,
range_whole = true; range_whole = true;
scanned = true; scanned = true;
} }
server = cifs_sb_master_tcon(cifs_sb)->ses->server; server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses);
retry: retry:
while (!done && index <= end) { while (!done && index <= end) {
unsigned int i, nr_pages, found_pages, wsize; unsigned int i, nr_pages, found_pages, wsize;
...@@ -2403,6 +2403,7 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -2403,6 +2403,7 @@ static int cifs_writepages(struct address_space *mapping,
wdata->credits = credits_on_stack; wdata->credits = credits_on_stack;
wdata->cfile = cfile; wdata->cfile = cfile;
wdata->server = server;
cfile = NULL; cfile = NULL;
if (!wdata->cfile) { if (!wdata->cfile) {
...@@ -2806,8 +2807,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, ...@@ -2806,8 +2807,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
unsigned int wsize; unsigned int wsize;
struct cifs_credits credits; struct cifs_credits credits;
int rc; int rc;
struct TCP_Server_Info *server = struct TCP_Server_Info *server = wdata->server;
tlink_tcon(wdata->cfile->tlink)->ses->server;
do { do {
if (wdata->cfile->invalidHandle) { if (wdata->cfile->invalidHandle) {
...@@ -2893,7 +2893,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2893,7 +2893,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
else else
pid = current->tgid; pid = current->tgid;
server = tlink_tcon(open_file->tlink)->ses->server; server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
xid = get_xid(); xid = get_xid();
do { do {
...@@ -2923,11 +2923,9 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2923,11 +2923,9 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
from, &pagevec, cur_len, &start); from, &pagevec, cur_len, &start);
if (result < 0) { if (result < 0) {
cifs_dbg(VFS, cifs_dbg(VFS,
"direct_writev couldn't get user pages " "direct_writev couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
"(rc=%zd) iter type %d iov_offset %zd " result, iov_iter_type(from),
"count %zd\n", from->iov_offset, from->count);
result, iov_iter_type(from),
from->iov_offset, from->count);
dump_stack(); dump_stack();
rc = result; rc = result;
...@@ -2999,6 +2997,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2999,6 +2997,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
wdata->nr_pages = nr_pages; wdata->nr_pages = nr_pages;
wdata->offset = (__u64)offset; wdata->offset = (__u64)offset;
wdata->cfile = cifsFileInfo_get(open_file); wdata->cfile = cifsFileInfo_get(open_file);
wdata->server = server;
wdata->pid = pid; wdata->pid = pid;
wdata->bytes = cur_len; wdata->bytes = cur_len;
wdata->pagesz = PAGE_SIZE; wdata->pagesz = PAGE_SIZE;
...@@ -3540,8 +3539,10 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, ...@@ -3540,8 +3539,10 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
unsigned int rsize; unsigned int rsize;
struct cifs_credits credits; struct cifs_credits credits;
int rc; int rc;
struct TCP_Server_Info *server = struct TCP_Server_Info *server;
tlink_tcon(rdata->cfile->tlink)->ses->server;
/* XXX: should we pick a new channel here? */
server = rdata->server;
do { do {
if (rdata->cfile->invalidHandle) { if (rdata->cfile->invalidHandle) {
...@@ -3620,7 +3621,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3620,7 +3621,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
size_t start; size_t start;
struct iov_iter direct_iov = ctx->iter; 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) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid; pid = open_file->pid;
...@@ -3654,12 +3655,10 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3654,12 +3655,10 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
cur_len, &start); cur_len, &start);
if (result < 0) { if (result < 0) {
cifs_dbg(VFS, cifs_dbg(VFS,
"couldn't get user pages (rc=%zd)" "Couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
" iter type %d" result, iov_iter_type(&direct_iov),
" iov_offset %zd count %zd\n", direct_iov.iov_offset,
result, iov_iter_type(&direct_iov), direct_iov.count);
direct_iov.iov_offset,
direct_iov.count);
dump_stack(); dump_stack();
rc = result; rc = result;
...@@ -3706,6 +3705,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3706,6 +3705,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
rdata->tailsz = PAGE_SIZE; rdata->tailsz = PAGE_SIZE;
} }
rdata->server = server;
rdata->cfile = cifsFileInfo_get(open_file); rdata->cfile = cifsFileInfo_get(open_file);
rdata->nr_pages = npages; rdata->nr_pages = npages;
rdata->offset = offset; rdata->offset = offset;
...@@ -4018,7 +4018,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) ...@@ -4018,7 +4018,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
unsigned int xid; unsigned int xid;
char *cur_offset; char *cur_offset;
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
__u32 pid; __u32 pid;
...@@ -4035,7 +4035,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) ...@@ -4035,7 +4035,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
} }
open_file = file->private_data; open_file = file->private_data;
tcon = tlink_tcon(open_file->tlink); tcon = tlink_tcon(open_file->tlink);
server = tcon->ses->server; server = cifs_pick_channel(tcon->ses);
if (!server->ops->sync_read) { if (!server->ops->sync_read) {
free_xid(xid); free_xid(xid);
...@@ -4074,6 +4074,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) ...@@ -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.tcon = tcon;
io_parms.offset = *offset; io_parms.offset = *offset;
io_parms.length = current_read_size; io_parms.length = current_read_size;
io_parms.server = server;
rc = server->ops->sync_read(xid, &open_file->fid, &io_parms, rc = server->ops->sync_read(xid, &open_file->fid, &io_parms,
&bytes_read, &cur_offset, &bytes_read, &cur_offset,
&buf_type); &buf_type);
...@@ -4376,7 +4377,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -4376,7 +4377,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
pid = current->tgid; pid = current->tgid;
rc = 0; 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", cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n",
__func__, file, mapping, num_pages); __func__, file, mapping, num_pages);
...@@ -4447,6 +4448,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -4447,6 +4448,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
} }
rdata->cfile = cifsFileInfo_get(open_file); rdata->cfile = cifsFileInfo_get(open_file);
rdata->server = server;
rdata->mapping = mapping; rdata->mapping = mapping;
rdata->offset = offset; rdata->offset = offset;
rdata->bytes = bytes; rdata->bytes = bytes;
...@@ -4828,7 +4830,7 @@ static int cifs_swap_activate(struct swap_info_struct *sis, ...@@ -4828,7 +4830,7 @@ static int cifs_swap_activate(struct swap_info_struct *sis,
} }
*span = sis->pages; *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 * TODO: consider adding ACL (or documenting how) to prevent other
......
...@@ -448,7 +448,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, ...@@ -448,7 +448,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
char buf[24]; char buf[24];
unsigned int bytes_read; unsigned int bytes_read;
char *pbuf; char *pbuf;
...@@ -1156,7 +1156,7 @@ struct inode *cifs_root_iget(struct super_block *sb) ...@@ -1156,7 +1156,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
/* some servers mistakenly claim POSIX support */ /* some servers mistakenly claim POSIX support */
if (rc != -EOPNOTSUPP) if (rc != -EOPNOTSUPP)
goto iget_no_retry; 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; tcon->unix_ext = false;
} }
...@@ -1419,6 +1419,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1419,6 +1419,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
xid = get_xid(); xid = get_xid();
if (tcon->nodelete) {
rc = -EACCES;
goto unlink_out;
}
/* Unlink can be called from rename so we can not take the /* Unlink can be called from rename so we can not take the
* sb->s_vfs_rename_mutex here */ * sb->s_vfs_rename_mutex here */
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry);
...@@ -1747,6 +1752,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1747,6 +1752,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
goto rmdir_exit; 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); rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
...@@ -2000,7 +2011,7 @@ cifs_invalidate_mapping(struct inode *inode) ...@@ -2000,7 +2011,7 @@ cifs_invalidate_mapping(struct inode *inode)
if (inode->i_mapping && inode->i_mapping->nrpages != 0) { if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
rc = invalidate_inode_pages2(inode->i_mapping); rc = invalidate_inode_pages2(inode->i_mapping);
if (rc) if (rc)
cifs_dbg(VFS, "%s: could not invalidate inode %p\n", cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
__func__, inode); __func__, inode);
} }
......
...@@ -308,7 +308,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, ...@@ -308,7 +308,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int oplock = 0; int oplock = 0;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
FILE_ALL_INFO file_info; FILE_ALL_INFO file_info;
...@@ -352,7 +352,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, ...@@ -352,7 +352,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int oplock = 0; int oplock = 0;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
oparms.tcon = tcon; oparms.tcon = tcon;
oparms.cifs_sb = cifs_sb; oparms.cifs_sb = cifs_sb;
...@@ -389,7 +389,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, ...@@ -389,7 +389,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int rc; int rc;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
__le16 *utf16_path; __le16 *utf16_path;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
...@@ -450,7 +450,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, ...@@ -450,7 +450,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int rc; int rc;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms = {0};
__le16 *utf16_path; __le16 *utf16_path;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct kvec iov[2]; struct kvec iov[2];
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "smb2pdu.h" #include "smb2pdu.h"
#include "cifsfs.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_sm_req_poolp;
extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_req_poolp;
...@@ -421,7 +424,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) ...@@ -421,7 +424,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
if (data_offset > if (data_offset >
len - sizeof(struct file_notify_information)) { len - sizeof(struct file_notify_information)) {
cifs_dbg(FYI, "invalid data_offset %u\n", cifs_dbg(FYI, "Invalid data_offset %u\n",
data_offset); data_offset);
return true; return true;
} }
...@@ -449,7 +452,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) ...@@ -449,7 +452,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
large dirty files cached on the client */ large dirty files cached on the client */
if ((NT_STATUS_INVALID_HANDLE) == if ((NT_STATUS_INVALID_HANDLE) ==
le32_to_cpu(pSMB->hdr.Status.CifsError)) { 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; return true;
} else if (ERRbadfid == } else if (ERRbadfid ==
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
...@@ -530,9 +533,9 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) ...@@ -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_flags &= ~CIFS_MOUNT_SERVER_INUM;
cifs_sb->mnt_cifs_serverino_autodisabled = true; 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"); 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"); 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) ...@@ -874,7 +877,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
while (count && npages < max_pages) { while (count && npages < max_pages) {
rc = iov_iter_get_pages(iter, pages, count, max_pages, &start); rc = iov_iter_get_pages(iter, pages, count, max_pages, &start);
if (rc < 0) { 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; break;
} }
...@@ -933,7 +936,7 @@ cifs_alloc_hash(const char *name, ...@@ -933,7 +936,7 @@ cifs_alloc_hash(const char *name,
*shash = crypto_alloc_shash(name, 0, 0); *shash = crypto_alloc_shash(name, 0, 0);
if (IS_ERR(*shash)) { 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); rc = PTR_ERR(*shash);
*shash = NULL; *shash = NULL;
*sdesc = NULL; *sdesc = NULL;
...@@ -1083,6 +1086,51 @@ void cifs_put_tcp_super(struct super_block *sb) ...@@ -1083,6 +1086,51 @@ void cifs_put_tcp_super(struct super_block *sb)
} }
#ifdef CONFIG_CIFS_DFS_UPCALL #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) static void tcon_super_cb(struct super_block *sb, void *arg)
{ {
struct super_cb_data *sd = arg; struct super_cb_data *sd = arg;
......
...@@ -957,15 +957,15 @@ struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) ...@@ -957,15 +957,15 @@ struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
sec = 2 * st->TwoSeconds; sec = 2 * st->TwoSeconds;
min = st->Minutes; min = st->Minutes;
if ((sec > 59) || (min > 59)) 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 += (min * 60);
sec += 60 * 60 * st->Hours; sec += 60 * 60 * st->Hours;
if (st->Hours > 24) 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; day = sd->Day;
month = sd->Month; month = sd->Month;
if (day < 1 || day > 31 || month < 1 || month > 12) { 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); day = clamp(day, 1, 31);
month = clamp(month, 1, 12); month = clamp(month, 1, 12);
} }
......
...@@ -53,7 +53,7 @@ static void dump_cifs_file_struct(struct file *file, char *label) ...@@ -53,7 +53,7 @@ static void dump_cifs_file_struct(struct file *file, char *label)
return; return;
} }
if (cf->invalidHandle) if (cf->invalidHandle)
cifs_dbg(FYI, "invalid handle\n"); cifs_dbg(FYI, "Invalid handle\n");
if (cf->srch_inf.endOfSearch) if (cf->srch_inf.endOfSearch)
cifs_dbg(FYI, "end of search\n"); cifs_dbg(FYI, "end of search\n");
if (cf->srch_inf.emptyDir) if (cf->srch_inf.emptyDir)
...@@ -246,7 +246,7 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info, ...@@ -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; 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->DeviceId),
le32_to_cpu(info->ReparseTag), le32_to_cpu(info->ReparseTag),
le32_to_cpu(info->Mode)); le32_to_cpu(info->Mode));
...@@ -478,7 +478,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) ...@@ -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); u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
if (old_entry + next_offset < old_entry) { 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; return NULL;
} }
new_entry = old_entry + next_offset; new_entry = old_entry + next_offset;
...@@ -515,7 +515,7 @@ static void cifs_fill_dirent_posix(struct cifs_dirent *de, ...@@ -515,7 +515,7 @@ static void cifs_fill_dirent_posix(struct cifs_dirent *de,
/* payload should have already been checked at this point */ /* payload should have already been checked at this point */
if (posix_info_parse(info, NULL, &parsed) < 0) { if (posix_info_parse(info, NULL, &parsed) < 0) {
cifs_dbg(VFS, "invalid POSIX info payload"); cifs_dbg(VFS, "Invalid POSIX info payload\n");
return; return;
} }
...@@ -968,7 +968,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -968,7 +968,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
} else if (current_entry != NULL) { } else if (current_entry != NULL) {
cifs_dbg(FYI, "entry %lld found\n", ctx->pos); cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
} else { } else {
cifs_dbg(FYI, "could not find entry\n"); cifs_dbg(FYI, "Could not find entry\n");
goto rddir2_exit; goto rddir2_exit;
} }
cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
......
...@@ -122,7 +122,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses) ...@@ -122,7 +122,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
tries++; tries++;
if (tries > 3*ses->chan_max) { 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); left);
break; break;
} }
...@@ -150,6 +150,22 @@ int cifs_try_adding_channels(struct cifs_ses *ses) ...@@ -150,6 +150,22 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
return ses->chan_count - old_chan_count; 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 int
cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) 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) ...@@ -162,12 +178,14 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
int rc; int rc;
unsigned int xid = get_xid(); 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) 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 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 * 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) ...@@ -198,7 +216,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
vol.UNC = unc; vol.UNC = unc;
vol.prepath = ""; vol.prepath = "";
/* Re-use same version as master connection */ /* Reuse same version as master connection */
vol.vals = ses->server->vals; vol.vals = ses->server->vals;
vol.ops = ses->server->ops; vol.ops = ses->server->ops;
...@@ -229,7 +247,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) ...@@ -229,7 +247,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
mutex_lock(&ses->session_mutex); 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); chan->server = cifs_get_tcp_session(&vol);
if (IS_ERR(chan->server)) { if (IS_ERR(chan->server)) {
rc = PTR_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) ...@@ -261,7 +279,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
goto out; goto out;
/* success, put it on the list /* 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 * way "internal" linked lists works in linux makes element
* only able to belong to one list * only able to belong to one list
* *
...@@ -274,6 +292,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface) ...@@ -274,6 +292,7 @@ cifs_ses_add_channel(struct cifs_ses *ses, struct cifs_server_iface *iface)
atomic_set(&ses->chan_seq, 0); atomic_set(&ses->chan_seq, 0);
out: out:
ses->binding = false; ses->binding = false;
ses->binding_chan = NULL;
mutex_unlock(&ses->session_mutex); mutex_unlock(&ses->session_mutex);
if (rc && chan->server) if (rc && chan->server)
...@@ -569,15 +588,15 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, ...@@ -569,15 +588,15 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
tilen = le16_to_cpu(pblob->TargetInfoArray.Length); tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
if (tioffset > blob_len || tioffset + tilen > blob_len) { if (tioffset > blob_len || tioffset + tilen > blob_len) {
cifs_dbg(VFS, "tioffset + tilen too high %u + %u", cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n",
tioffset, tilen); tioffset, tilen);
return -EINVAL; return -EINVAL;
} }
if (tilen) { if (tilen) {
ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen, ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
GFP_KERNEL); GFP_KERNEL);
if (!ses->auth_key.response) { if (!ses->auth_key.response) {
cifs_dbg(VFS, "Challenge target info alloc failure"); cifs_dbg(VFS, "Challenge target info alloc failure\n");
return -ENOMEM; return -ENOMEM;
} }
ses->auth_key.len = tilen; ses->auth_key.len = tilen;
...@@ -970,7 +989,7 @@ sess_auth_lanman(struct sess_data *sess_data) ...@@ -970,7 +989,7 @@ sess_auth_lanman(struct sess_data *sess_data)
/* Calculate hash with password and copy into bcc_ptr. /* Calculate hash with password and copy into bcc_ptr.
* Encryption Key (stored as in cryptkey) gets used if the * 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). * to use challenge/response method (i.e. Password bit is 1).
*/ */
rc = calc_lanman_hash(ses->password, ses->server->cryptkey, rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
...@@ -1303,9 +1322,8 @@ sess_auth_kerberos(struct sess_data *sess_data) ...@@ -1303,9 +1322,8 @@ sess_auth_kerberos(struct sess_data *sess_data)
* sending us a response in an expected form * sending us a response in an expected form
*/ */
if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
cifs_dbg(VFS, cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
"incorrect version of cifs.upcall (expected %d but got %d)", CIFS_SPNEGO_UPCALL_VERSION, msg->version);
CIFS_SPNEGO_UPCALL_VERSION, msg->version);
rc = -EKEYREJECTED; rc = -EKEYREJECTED;
goto out_put_spnego_key; goto out_put_spnego_key;
} }
...@@ -1313,8 +1331,8 @@ sess_auth_kerberos(struct sess_data *sess_data) ...@@ -1313,8 +1331,8 @@ sess_auth_kerberos(struct sess_data *sess_data)
ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
GFP_KERNEL); GFP_KERNEL);
if (!ses->auth_key.response) { 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); msg->sesskey_len);
rc = -ENOMEM; rc = -ENOMEM;
goto out_put_spnego_key; goto out_put_spnego_key;
} }
...@@ -1657,8 +1675,7 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data) ...@@ -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); type = cifs_select_sectype(ses->server, ses->sectype);
cifs_dbg(FYI, "sess setup type %d\n", type); cifs_dbg(FYI, "sess setup type %d\n", type);
if (type == Unspecified) { if (type == Unspecified) {
cifs_dbg(VFS, cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
"Unable to select appropriate authentication method!");
return -EINVAL; return -EINVAL;
} }
......
...@@ -247,7 +247,7 @@ check2ndT2(char *buf) ...@@ -247,7 +247,7 @@ check2ndT2(char *buf)
/* check for plausible wct, bcc and t2 data and parm sizes */ /* check for plausible wct, bcc and t2 data and parm sizes */
/* check for parm and data offset going beyond end of smb */ /* check for parm and data offset going beyond end of smb */
if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ 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; return -EINVAL;
} }
......
This diff is collapsed.
...@@ -110,14 +110,14 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, ...@@ -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 */ /* Make sure that negotiate contexts start after gss security blob */
nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
if (nc_offset < non_ctxlen) { if (nc_offset < non_ctxlen) {
printk_once(KERN_WARNING "invalid negotiate context offset\n"); pr_warn_once("Invalid negotiate context offset\n");
return 0; return 0;
} }
size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
/* Verify that at least minimal negotiate contexts fit within frame */ /* Verify that at least minimal negotiate contexts fit within frame */
if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { 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; return 0;
} }
...@@ -190,14 +190,14 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) ...@@ -190,14 +190,14 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
return 1; return 1;
if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { 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)); le16_to_cpu(shdr->StructureSize));
return 1; return 1;
} }
command = le16_to_cpu(shdr->Command); command = le16_to_cpu(shdr->Command);
if (command >= NUMBER_OF_SMB2_COMMANDS) { 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; return 1;
} }
...@@ -205,7 +205,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) ...@@ -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 || if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
/* error packets have 9 byte structure size */ /* 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); le16_to_cpu(pdu->StructureSize2), command);
return 1; return 1;
} else if (command == SMB2_OPLOCK_BREAK_HE } else if (command == SMB2_OPLOCK_BREAK_HE
...@@ -213,7 +213,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) ...@@ -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) != 44)
&& (le16_to_cpu(pdu->StructureSize2) != 36)) { && (le16_to_cpu(pdu->StructureSize2) != 36)) {
/* special case for SMB2.1 lease break message */ /* 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)); le16_to_cpu(pdu->StructureSize2));
return 1; return 1;
} }
...@@ -864,14 +864,14 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec) ...@@ -864,14 +864,14 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
d = server->secmech.sdescsha512; d = server->secmech.sdescsha512;
rc = crypto_shash_init(&d->shash); rc = crypto_shash_init(&d->shash);
if (rc) { 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; return rc;
} }
rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash, rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash,
SMB2_PREAUTH_HASH_SIZE); SMB2_PREAUTH_HASH_SIZE);
if (rc) { 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; return rc;
} }
...@@ -879,7 +879,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec) ...@@ -879,7 +879,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
rc = crypto_shash_update(&d->shash, rc = crypto_shash_update(&d->shash,
iov[i].iov_base, iov[i].iov_len); iov[i].iov_base, iov[i].iov_len);
if (rc) { if (rc) {
cifs_dbg(VFS, "%s: could not update sha512 shash\n", cifs_dbg(VFS, "%s: Could not update sha512 shash\n",
__func__); __func__);
return rc; return rc;
} }
...@@ -887,7 +887,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec) ...@@ -887,7 +887,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash); rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash);
if (rc) { if (rc) {
cifs_dbg(VFS, "%s: could not finalize sha512 shash\n", cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n",
__func__); __func__);
return rc; return rc;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -143,8 +143,17 @@ struct smb2_transform_hdr { ...@@ -143,8 +143,17 @@ struct smb2_transform_hdr {
__u64 SessionId; __u64 SessionId;
} __packed; } __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 */ /* See MS-SMB2 2.2.42.1 */
struct compression_playload_header { struct compression_payload_header {
__le16 AlgorithmId; __le16 AlgorithmId;
__le16 Reserved; __le16 Reserved;
__le32 Length; __le32 Length;
...@@ -333,7 +342,7 @@ struct smb2_encryption_neg_context { ...@@ -333,7 +342,7 @@ struct smb2_encryption_neg_context {
#define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002) #define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002)
#define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003) #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
/* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */ /* 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 */ /* Compression Flags */
#define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000) #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000)
......
...@@ -143,7 +143,9 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, ...@@ -143,7 +143,9 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
struct smb2_file_all_info *buf, struct smb2_file_all_info *buf,
struct create_posix_rsp *posix, struct create_posix_rsp *posix,
struct kvec *err_iov, int *resp_buftype); 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, __u8 *oplock, struct cifs_open_parms *oparms,
__le16 *path); __le16 *path);
extern void SMB2_open_free(struct smb_rqst *rqst); 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, ...@@ -151,7 +153,9 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 opcode, u64 persistent_fid, u64 volatile_fid, u32 opcode,
bool is_fsctl, char *in_data, u32 indatalen, u32 maxoutlen, bool is_fsctl, char *in_data, u32 indatalen, u32 maxoutlen,
char **out_data, u32 *plen /* returned data len */); 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, u64 persistent_fid, u64 volatile_fid, u32 opcode,
bool is_fsctl, char *in_data, u32 indatalen, bool is_fsctl, char *in_data, u32 indatalen,
__u32 max_response_size); __u32 max_response_size);
...@@ -165,19 +169,25 @@ extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -165,19 +169,25 @@ extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
struct smb2_file_network_open_info *pbuf); struct smb2_file_network_open_info *pbuf);
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id); u64 persistent_file_id, u64 volatile_file_id);
extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, extern int SMB2_close_init(struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, bool query_attrs); 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 void SMB2_close_free(struct smb_rqst *rqst);
extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id); u64 persistent_file_id, u64 volatile_file_id);
extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
struct cifs_tcon *tcon, struct cifs_tcon *tcon,
struct TCP_Server_Info *server,
u64 persistent_file_id, u64 volatile_file_id); u64 persistent_file_id, u64 volatile_file_id);
extern void SMB2_flush_free(struct smb_rqst *rqst); extern void SMB2_flush_free(struct smb_rqst *rqst);
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id, u64 persistent_file_id, u64 volatile_file_id,
struct smb2_file_all_info *data); 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, u64 persistent_fid, u64 volatile_fid,
u8 info_class, u8 info_type, u8 info_class, u8 info_type,
u32 additional_info, size_t output_len, u32 additional_info, size_t output_len,
...@@ -201,6 +211,7 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -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, u64 persistent_fid, u64 volatile_fid, int index,
struct cifs_search_info *srch_inf); struct cifs_search_info *srch_inf);
extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon,
struct TCP_Server_Info *server,
struct smb_rqst *rqst, struct smb_rqst *rqst,
u64 persistent_fid, u64 volatile_fid, u64 persistent_fid, u64 volatile_fid,
int index, int info_level); int index, int info_level);
...@@ -208,7 +219,9 @@ extern void SMB2_query_directory_free(struct smb_rqst *rqst); ...@@ -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, extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 pid, u64 persistent_fid, u64 volatile_fid, u32 pid,
__le64 *eof); __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, u64 persistent_fid, u64 volatile_fid, u32 pid,
u8 info_class, u8 info_type, u32 additional_info, u8 info_class, u8 info_type, u32 additional_info,
void **data, unsigned int *size); void **data, unsigned int *size);
......
This diff is collapsed.
...@@ -112,7 +112,7 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) ...@@ -112,7 +112,7 @@ static void _cifs_mid_q_entry_release(struct kref *refcount)
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
now = jiffies; now = jiffies;
if (now < midEntry->when_alloc) 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; roundtrip_time = now - midEntry->when_alloc;
if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) {
...@@ -151,12 +151,12 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) ...@@ -151,12 +151,12 @@ static void _cifs_mid_q_entry_release(struct kref *refcount)
trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid, trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid,
midEntry->when_sent, midEntry->when_received); midEntry->when_sent, midEntry->when_received);
if (cifsFYI & CIFS_TIMER) { if (cifsFYI & CIFS_TIMER) {
pr_debug(" CIFS slow rsp: cmd %d mid %llu", pr_debug("slow rsp: cmd %d mid %llu",
midEntry->command, midEntry->mid); midEntry->command, midEntry->mid);
cifs_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n", cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n",
now - midEntry->when_alloc, now - midEntry->when_alloc,
now - midEntry->when_sent, now - midEntry->when_sent,
now - midEntry->when_received); now - midEntry->when_received);
} }
} }
#endif #endif
...@@ -473,8 +473,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, ...@@ -473,8 +473,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
return -ENOMEM; return -ENOMEM;
if (!server->ops->init_transform_rq) { if (!server->ops->init_transform_rq) {
cifs_server_dbg(VFS, "Encryption requested but transform " cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n");
"callback is missing\n");
return -EIO; return -EIO;
} }
...@@ -989,8 +988,35 @@ cifs_cancelled_callback(struct mid_q_entry *mid) ...@@ -989,8 +988,35 @@ cifs_cancelled_callback(struct mid_q_entry *mid)
DeleteMidQEntry(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 int
compound_send_recv(const unsigned int xid, struct cifs_ses *ses, 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, const int flags, const int num_rqst, struct smb_rqst *rqst,
int *resp_buf_type, struct kvec *resp_iov) int *resp_buf_type, struct kvec *resp_iov)
{ {
...@@ -1002,30 +1028,17 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -1002,30 +1028,17 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
}; };
unsigned int instance; unsigned int instance;
char *buf; char *buf;
struct TCP_Server_Info *server;
optype = flags & CIFS_OP_MASK; optype = flags & CIFS_OP_MASK;
for (i = 0; i < num_rqst; i++) for (i = 0; i < num_rqst; i++)
resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */ 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"); cifs_dbg(VFS, "Null session\n");
return -EIO; 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) if (server->tcpStatus == CifsExiting)
return -ENOENT; return -ENOENT;
...@@ -1220,11 +1233,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -1220,11 +1233,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
int int
cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, 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 smb_rqst *rqst, int *resp_buf_type, const int flags,
struct kvec *resp_iov) struct kvec *resp_iov)
{ {
return compound_send_recv(xid, ses, flags, 1, rqst, resp_buf_type, return compound_send_recv(xid, ses, server, flags, 1,
resp_iov); rqst, resp_buf_type, resp_iov);
} }
int int
...@@ -1259,7 +1273,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, ...@@ -1259,7 +1273,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rqst.rq_iov = new_iov; rqst.rq_iov = new_iov;
rqst.rq_nvec = n_vec + 1; 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) if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
kfree(new_iov); kfree(new_iov);
return rc; return rc;
...@@ -1296,8 +1311,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, ...@@ -1296,8 +1311,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
use ses->maxReq */ use ses->maxReq */
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
len); len);
return -EIO; return -EIO;
} }
...@@ -1437,8 +1452,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1437,8 +1452,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
use ses->maxReq */ use ses->maxReq */
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
cifs_tcon_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
len); len);
return -EIO; return -EIO;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment