提交 32552014 编写于 作者: L Linus Torvalds

Merge tag '4.18-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:

 - smb3 fixes for stable

 - addition of ftrace hooks for cifs.ko

 - improvements in compounding and smbdirect (rdma)

* tag '4.18-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (38 commits)
  CIFS: Add support for direct pages in wdata
  CIFS: Use offset when reading pages
  CIFS: Add support for direct pages in rdata
  cifs: update multiplex loop to handle compounded responses
  cifs: remove header_preamble_size where it is always 0
  cifs: remove struct smb2_hdr
  CIFS: 511c54a2 adds a check for session expiry, status STATUS_NETWORK_SESSION_EXPIRED, however the server can also respond with STATUS_USER_SESSION_DELETED in cases where the session has been idle for some time and the server reaps the session to recover resources.
  cifs: change smb2_get_data_area_len to take a smb2_sync_hdr as argument
  cifs: update smb2_calc_size to use smb2_sync_hdr instead of smb2_hdr
  cifs: remove struct smb2_oplock_break_rsp
  cifs: remove rfc1002 header from all SMB2 response structures
  smb3: on reconnect set PreviousSessionId field
  smb3: Add posix create context for smb3.11 posix mounts
  smb3: add tracepoints for smb2/smb3 open
  cifs: add debug output to show nocase mount option
  smb3: add define for id for posix create context and corresponding struct
  cifs: update smb2_check_message to handle PDUs without a 4 byte length header
  smb3: allow "posix" mount option to enable new SMB311 protocol extensions
  smb3: add support for posix negotiate context
  cifs: allow disabling less secure legacy dialects
  ...
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# #
# Makefile for Linux CIFS VFS client # Makefile for Linux CIFS/SMB2/SMB3 VFS client
# #
ccflags-y += -I$(src) # needed for trace events
obj-$(CONFIG_CIFS) += cifs.o obj-$(CONFIG_CIFS) += cifs.o
cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ cifs-y := trace.o cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o \
link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ inode.o link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \
cifs_unicode.o nterr.o cifsencrypt.o \ cifs_unicode.o nterr.o cifsencrypt.o \
readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o \ readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o \
smb2ops.o smb2maperror.o smb2transport.o \ smb2ops.o smb2maperror.o smb2transport.o \
......
...@@ -42,7 +42,7 @@ cifs_dump_mem(char *label, void *data, int length) ...@@ -42,7 +42,7 @@ cifs_dump_mem(char *label, void *data, int length)
data, length, true); data, length, true);
} }
void cifs_dump_detail(void *buf) void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
{ {
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
struct smb_hdr *smb = (struct smb_hdr *)buf; struct smb_hdr *smb = (struct smb_hdr *)buf;
...@@ -50,7 +50,8 @@ void cifs_dump_detail(void *buf) ...@@ -50,7 +50,8 @@ void cifs_dump_detail(void *buf)
cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n", cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
smb->Command, smb->Status.CifsError, smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid); smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
cifs_dbg(VFS, "smb buf %p len %u\n", smb, smbCalcSize(smb)); cifs_dbg(VFS, "smb buf %p len %u\n", smb,
server->ops->calc_smb_size(smb, server));
#endif /* CONFIG_CIFS_DEBUG2 */ #endif /* CONFIG_CIFS_DEBUG2 */
} }
...@@ -83,7 +84,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server) ...@@ -83,7 +84,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n", cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
mid_entry->multiRsp, mid_entry->multiEnd); mid_entry->multiRsp, mid_entry->multiEnd);
if (mid_entry->resp_buf) { if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf); cifs_dump_detail(mid_entry->resp_buf, server);
cifs_dump_mem("existing buf: ", cifs_dump_mem("existing buf: ",
mid_entry->resp_buf, 62); mid_entry->resp_buf, 62);
} }
...@@ -113,6 +114,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) ...@@ -113,6 +114,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
seq_printf(m, " type: %d ", dev_type); seq_printf(m, " type: %d ", dev_type);
if (tcon->seal) if (tcon->seal)
seq_printf(m, " Encrypted"); seq_printf(m, " Encrypted");
if (tcon->nocase)
seq_printf(m, " nocase");
if (tcon->unix_ext) if (tcon->unix_ext)
seq_printf(m, " POSIX Extensions"); seq_printf(m, " POSIX Extensions");
if (tcon->ses->server->ops->dump_share_caps) if (tcon->ses->server->ops->dump_share_caps)
...@@ -237,6 +240,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -237,6 +240,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
server->credits, server->dialect); server->credits, server->dialect);
if (server->sign) if (server->sign)
seq_printf(m, " signed"); seq_printf(m, " signed");
#ifdef CONFIG_CIFS_SMB311
if (server->posix_ext_supported)
seq_printf(m, " posix");
#endif /* 3.1.1 */
i++; i++;
list_for_each(tmp2, &server->smb_ses_list) { list_for_each(tmp2, &server->smb_ses_list) {
ses = list_entry(tmp2, struct cifs_ses, ses = list_entry(tmp2, struct cifs_ses,
...@@ -489,32 +496,32 @@ cifs_proc_init(void) ...@@ -489,32 +496,32 @@ cifs_proc_init(void)
cifs_debug_data_proc_show); cifs_debug_data_proc_show);
#ifdef CONFIG_CIFS_STATS #ifdef CONFIG_CIFS_STATS
proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops); proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops);
#endif /* STATS */ #endif /* STATS */
proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops);
proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops);
proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
&cifs_linux_ext_proc_fops); &cifs_linux_ext_proc_fops);
proc_create("SecurityFlags", 0, proc_fs_cifs, proc_create("SecurityFlags", 0644, proc_fs_cifs,
&cifs_security_flags_proc_fops); &cifs_security_flags_proc_fops);
proc_create("LookupCacheEnabled", 0, proc_fs_cifs, proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
&cifs_lookup_cache_proc_fops); &cifs_lookup_cache_proc_fops);
#ifdef CONFIG_CIFS_SMB_DIRECT #ifdef CONFIG_CIFS_SMB_DIRECT
proc_create("rdma_readwrite_threshold", 0, proc_fs_cifs, proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
&cifs_rdma_readwrite_threshold_proc_fops); &cifs_rdma_readwrite_threshold_proc_fops);
proc_create("smbd_max_frmr_depth", 0, proc_fs_cifs, proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs,
&cifs_smbd_max_frmr_depth_proc_fops); &cifs_smbd_max_frmr_depth_proc_fops);
proc_create("smbd_keep_alive_interval", 0, proc_fs_cifs, proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs,
&cifs_smbd_keep_alive_interval_proc_fops); &cifs_smbd_keep_alive_interval_proc_fops);
proc_create("smbd_max_receive_size", 0, proc_fs_cifs, proc_create("smbd_max_receive_size", 0644, proc_fs_cifs,
&cifs_smbd_max_receive_size_proc_fops); &cifs_smbd_max_receive_size_proc_fops);
proc_create("smbd_max_fragmented_recv_size", 0, proc_fs_cifs, proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs,
&cifs_smbd_max_fragmented_recv_size_proc_fops); &cifs_smbd_max_fragmented_recv_size_proc_fops);
proc_create("smbd_max_send_size", 0, proc_fs_cifs, proc_create("smbd_max_send_size", 0644, proc_fs_cifs,
&cifs_smbd_max_send_size_proc_fops); &cifs_smbd_max_send_size_proc_fops);
proc_create("smbd_send_credit_target", 0, proc_fs_cifs, proc_create("smbd_send_credit_target", 0644, proc_fs_cifs,
&cifs_smbd_send_credit_target_proc_fops); &cifs_smbd_send_credit_target_proc_fops);
proc_create("smbd_receive_credit_max", 0, proc_fs_cifs, proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs,
&cifs_smbd_receive_credit_max_proc_fops); &cifs_smbd_receive_credit_max_proc_fops);
#endif #endif
} }
...@@ -572,6 +579,8 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer, ...@@ -572,6 +579,8 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
cifsFYI = bv; cifsFYI = bv;
else if ((c[0] > '1') && (c[0] <= '9')) else if ((c[0] > '1') && (c[0] <= '9'))
cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */ cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
else
return -EINVAL;
return count; return count;
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#define _H_CIFS_DEBUG #define _H_CIFS_DEBUG
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 *); 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 *);
extern bool traceSMB; /* flag which enables the function below */ extern bool traceSMB; /* flag which enables the function below */
void dump_smb(void *, int); void dump_smb(void *, int);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
* root mountable * root mountable
*/ */
#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */ #define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
#define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */
struct cifs_sb_info { struct cifs_sb_info {
struct rb_root tlink_tree; struct rb_root tlink_tree;
......
...@@ -58,13 +58,15 @@ bool traceSMB; ...@@ -58,13 +58,15 @@ bool traceSMB;
bool enable_oplocks = true; bool enable_oplocks = true;
bool linuxExtEnabled = true; bool linuxExtEnabled = true;
bool lookupCacheEnabled = true; bool lookupCacheEnabled = true;
bool disable_legacy_dialects; /* false by default */
unsigned int global_secflags = CIFSSEC_DEF; unsigned int global_secflags = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */ /* unsigned int ntlmv2_support = 0; */
unsigned int sign_CIFS_PDUs = 1; unsigned int sign_CIFS_PDUs = 1;
static const struct super_operations cifs_super_ops; static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, uint, 0444); module_param(CIFSMaxBufSize, uint, 0444);
MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). " MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header) "
"for CIFS requests. "
"Default: 16384 Range: 8192 to 130048"); "Default: 16384 Range: 8192 to 130048");
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
module_param(cifs_min_rcv, uint, 0444); module_param(cifs_min_rcv, uint, 0444);
...@@ -76,11 +78,21 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " ...@@ -76,11 +78,21 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
"Range: 2 to 256"); "Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ; unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, uint, 0444); module_param(cifs_max_pending, uint, 0444);
MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for "
"CIFS/SMB1 dialect (N/A for SMB3) "
"Default: 32767 Range: 2 to 32767."); "Default: 32767 Range: 2 to 32767.");
module_param(enable_oplocks, bool, 0644); module_param(enable_oplocks, bool, 0644);
MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1"); MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
module_param(disable_legacy_dialects, bool, 0644);
MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
"helpful to restrict the ability to "
"override the default dialects (SMB2.1, "
"SMB3 and SMB3.02) on mount with old "
"dialects (CIFS/SMB1 and SMB2) since "
"vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker"
" and less secure. Default: n/N/0");
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;
extern mempool_t *cifs_mid_poolp; extern mempool_t *cifs_mid_poolp;
...@@ -469,10 +481,20 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -469,10 +481,20 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",persistenthandles"); seq_puts(s, ",persistenthandles");
else if (tcon->use_resilient) else if (tcon->use_resilient)
seq_puts(s, ",resilienthandles"); seq_puts(s, ",resilienthandles");
#ifdef CONFIG_CIFS_SMB311
if (tcon->posix_extensions)
seq_puts(s, ",posix");
else if (tcon->unix_ext)
seq_puts(s, ",unix");
else
seq_puts(s, ",nounix");
#else
if (tcon->unix_ext) if (tcon->unix_ext)
seq_puts(s, ",unix"); seq_puts(s, ",unix");
else else
seq_puts(s, ",nounix"); seq_puts(s, ",nounix");
#endif /* SMB311 */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_puts(s, ",posixpaths"); seq_puts(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
...@@ -495,6 +517,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -495,6 +517,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",sfu"); seq_puts(s, ",sfu");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
seq_puts(s, ",nobrl"); seq_puts(s, ",nobrl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
seq_puts(s, ",nohandlecache");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
seq_puts(s, ",cifsacl"); seq_puts(s, ",cifsacl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
...@@ -897,6 +921,17 @@ struct file_system_type cifs_fs_type = { ...@@ -897,6 +921,17 @@ struct file_system_type cifs_fs_type = {
/* .fs_flags */ /* .fs_flags */
}; };
MODULE_ALIAS_FS("cifs"); MODULE_ALIAS_FS("cifs");
static struct file_system_type smb3_fs_type = {
.owner = THIS_MODULE,
.name = "smb3",
.mount = cifs_do_mount,
.kill_sb = cifs_kill_sb,
/* .fs_flags */
};
MODULE_ALIAS_FS("smb3");
MODULE_ALIAS("smb3");
const struct inode_operations cifs_dir_inode_ops = { const struct inode_operations cifs_dir_inode_ops = {
.create = cifs_create, .create = cifs_create,
.atomic_open = cifs_atomic_open, .atomic_open = cifs_atomic_open,
...@@ -1435,6 +1470,12 @@ init_cifs(void) ...@@ -1435,6 +1470,12 @@ init_cifs(void)
if (rc) if (rc)
goto out_init_cifs_idmap; goto out_init_cifs_idmap;
rc = register_filesystem(&smb3_fs_type);
if (rc) {
unregister_filesystem(&cifs_fs_type);
goto out_init_cifs_idmap;
}
return 0; return 0;
out_init_cifs_idmap: out_init_cifs_idmap:
...@@ -1465,8 +1506,9 @@ init_cifs(void) ...@@ -1465,8 +1506,9 @@ init_cifs(void)
static void __exit static void __exit
exit_cifs(void) exit_cifs(void)
{ {
cifs_dbg(NOISY, "exit_cifs\n"); cifs_dbg(NOISY, "exit_smb3\n");
unregister_filesystem(&cifs_fs_type); unregister_filesystem(&cifs_fs_type);
unregister_filesystem(&smb3_fs_type);
cifs_dfs_release_automount_timer(); cifs_dfs_release_automount_timer();
#ifdef CONFIG_CIFS_ACL #ifdef CONFIG_CIFS_ACL
exit_cifs_idmap(); exit_cifs_idmap();
......
...@@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
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.11" #define CIFS_VERSION "2.12"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -176,6 +176,7 @@ struct smb_rqst { ...@@ -176,6 +176,7 @@ struct smb_rqst {
struct kvec *rq_iov; /* array of kvecs */ struct kvec *rq_iov; /* array of kvecs */
unsigned int rq_nvec; /* number of kvecs in array */ unsigned int rq_nvec; /* number of kvecs in array */
struct page **rq_pages; /* pointer to array of page ptrs */ struct page **rq_pages; /* pointer to array of page ptrs */
unsigned int rq_offset; /* the offset to the 1st page */
unsigned int rq_npages; /* number pages in array */ unsigned int rq_npages; /* number pages in array */
unsigned int rq_pagesz; /* page size to use */ unsigned int rq_pagesz; /* page size to use */
unsigned int rq_tailsz; /* length of last page */ unsigned int rq_tailsz; /* length of last page */
...@@ -244,7 +245,7 @@ struct smb_version_operations { ...@@ -244,7 +245,7 @@ struct smb_version_operations {
int (*map_error)(char *, bool); int (*map_error)(char *, bool);
/* find mid corresponding to the response message */ /* find mid corresponding to the response message */
struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *); struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
void (*dump_detail)(void *); void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info);
void (*clear_stats)(struct cifs_tcon *); void (*clear_stats)(struct cifs_tcon *);
void (*print_stats)(struct seq_file *m, struct cifs_tcon *); void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
...@@ -372,7 +373,7 @@ struct smb_version_operations { ...@@ -372,7 +373,7 @@ struct smb_version_operations {
int (*close_dir)(const unsigned int, struct cifs_tcon *, int (*close_dir)(const unsigned int, struct cifs_tcon *,
struct cifs_fid *); struct cifs_fid *);
/* calculate a size of SMB message */ /* calculate a size of SMB message */
unsigned int (*calc_smb_size)(void *); unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi);
/* check for STATUS_PENDING and process it in a positive case */ /* check for STATUS_PENDING and process it in a positive case */
bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
/* check for STATUS_NETWORK_SESSION_EXPIRED */ /* check for STATUS_NETWORK_SESSION_EXPIRED */
...@@ -417,7 +418,7 @@ struct smb_version_operations { ...@@ -417,7 +418,7 @@ struct smb_version_operations {
/* create lease context buffer for CREATE request */ /* create lease context buffer for CREATE request */
char * (*create_lease_buf)(u8 *, u8); char * (*create_lease_buf)(u8 *, u8);
/* parse lease context buffer and return oplock/epoch info */ /* parse lease context buffer and return oplock/epoch info */
__u8 (*parse_lease_buf)(void *, unsigned int *); __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey);
ssize_t (*copychunk_range)(const unsigned int, ssize_t (*copychunk_range)(const unsigned int,
struct cifsFileInfo *src_file, struct cifsFileInfo *src_file,
struct cifsFileInfo *target_file, struct cifsFileInfo *target_file,
...@@ -457,7 +458,7 @@ struct smb_version_operations { ...@@ -457,7 +458,7 @@ struct smb_version_operations {
struct mid_q_entry **); struct mid_q_entry **);
enum securityEnum (*select_sectype)(struct TCP_Server_Info *, enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
enum securityEnum); enum securityEnum);
int (*next_header)(char *);
}; };
struct smb_version_values { struct smb_version_values {
...@@ -521,10 +522,12 @@ struct smb_vol { ...@@ -521,10 +522,12 @@ struct smb_vol {
bool sfu_remap:1; /* remap seven reserved chars ala SFU */ bool sfu_remap:1; /* remap seven reserved chars ala SFU */
bool posix_paths:1; /* unset to not ask for posix pathnames. */ bool posix_paths:1; /* unset to not ask for posix pathnames. */
bool no_linux_ext:1; bool no_linux_ext:1;
bool linux_ext:1;
bool sfu_emul:1; bool sfu_emul:1;
bool nullauth:1; /* attempt to authenticate with null user */ bool nullauth:1; /* attempt to authenticate with null user */
bool nocase:1; /* request case insensitive filenames */ bool nocase:1; /* request case insensitive filenames */
bool nobrl:1; /* disable sending byte range locks to srv */ bool nobrl:1; /* disable sending byte range locks to srv */
bool nohandlecache:1; /* disable caching dir handles if srvr probs */
bool mand_lock:1; /* send mandatory not posix byte range lock reqs */ bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
bool seal:1; /* request transport encryption on share */ bool seal:1; /* request transport encryption on share */
bool nodfs:1; /* Do not request DFS, even if available */ bool nodfs:1; /* Do not request DFS, even if available */
...@@ -630,7 +633,7 @@ struct TCP_Server_Info { ...@@ -630,7 +633,7 @@ struct TCP_Server_Info {
bool oplocks:1; /* enable oplocks */ bool oplocks:1; /* enable oplocks */
unsigned int maxReq; /* Clients should submit no more */ unsigned int maxReq; /* Clients should submit no more */
/* than maxReq distinct unanswered SMBs to the server when using */ /* than maxReq distinct unanswered SMBs to the server when using */
/* multiplexed reads or writes */ /* multiplexed reads or writes (for SMB1/CIFS only, not SMB2/SMB3) */
unsigned int maxBuf; /* maxBuf specifies the maximum */ unsigned int maxBuf; /* maxBuf specifies the maximum */
/* message size the server can send or receive for non-raw SMBs */ /* message size the server can send or receive for non-raw SMBs */
/* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */
...@@ -681,6 +684,7 @@ struct TCP_Server_Info { ...@@ -681,6 +684,7 @@ struct TCP_Server_Info {
__le16 cipher_type; __le16 cipher_type;
/* save initital negprot hash */ /* save initital negprot hash */
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
bool posix_ext_supported;
#endif /* 3.1.1 */ #endif /* 3.1.1 */
struct delayed_work reconnect; /* reconnect workqueue job */ struct delayed_work reconnect; /* reconnect workqueue job */
struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
...@@ -953,9 +957,13 @@ struct cifs_tcon { ...@@ -953,9 +957,13 @@ struct cifs_tcon {
bool print:1; /* set if connection to printer share */ bool print:1; /* set if connection to printer share */
bool retry:1; bool retry:1;
bool nocase:1; bool nocase:1;
bool nohandlecache:1; /* if strange server resource prob can turn off */
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 */
#ifdef CONFIG_CIFS_SMB311
bool posix_extensions; /* if true SMB3.11 posix extensions enabled */
#endif /* CIFS_311 */
bool local_lease:1; /* check leases (only) on local system not remote */ bool local_lease:1; /* check leases (only) on local system not remote */
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
bool broken_sparse_sup; /* if server or share does not support sparse */ bool broken_sparse_sup; /* if server or share does not support sparse */
...@@ -979,6 +987,9 @@ struct cifs_tcon { ...@@ -979,6 +987,9 @@ struct cifs_tcon {
struct fscache_cookie *fscache; /* cookie for share */ struct fscache_cookie *fscache; /* cookie for share */
#endif #endif
struct list_head pending_opens; /* list of incomplete opens */ struct list_head pending_opens; /* list of incomplete opens */
bool valid_root_fid:1; /* Do we have a useable root fid */
struct mutex prfid_mutex; /* prevents reopen race after dead ses*/
struct cifs_fid *prfid; /* handle to the directory at top of share */
/* BB add field for back pointer to sb struct(s)? */ /* BB add field for back pointer to sb struct(s)? */
}; };
...@@ -1071,6 +1082,7 @@ struct cifs_open_parms { ...@@ -1071,6 +1082,7 @@ struct cifs_open_parms {
int create_options; int create_options;
const char *path; const char *path;
struct cifs_fid *fid; struct cifs_fid *fid;
umode_t mode;
bool reconnect:1; bool reconnect:1;
}; };
...@@ -1169,10 +1181,11 @@ struct cifs_readdata { ...@@ -1169,10 +1181,11 @@ struct cifs_readdata {
struct smbd_mr *mr; struct smbd_mr *mr;
#endif #endif
unsigned int pagesz; unsigned int pagesz;
unsigned int page_offset;
unsigned int tailsz; unsigned int tailsz;
unsigned int credits; unsigned int credits;
unsigned int nr_pages; unsigned int nr_pages;
struct page *pages[]; struct page **pages;
}; };
struct cifs_writedata; struct cifs_writedata;
...@@ -1194,10 +1207,11 @@ struct cifs_writedata { ...@@ -1194,10 +1207,11 @@ struct cifs_writedata {
struct smbd_mr *mr; struct smbd_mr *mr;
#endif #endif
unsigned int pagesz; unsigned int pagesz;
unsigned int page_offset;
unsigned int tailsz; unsigned int tailsz;
unsigned int credits; unsigned int credits;
unsigned int nr_pages; unsigned int nr_pages;
struct page *pages[]; struct page **pages;
}; };
/* /*
...@@ -1692,16 +1706,17 @@ GLOBAL_EXTERN atomic_t smBufAllocCount; ...@@ -1692,16 +1706,17 @@ GLOBAL_EXTERN atomic_t smBufAllocCount;
GLOBAL_EXTERN atomic_t midCount; GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */ /* Misc globals */
GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */ extern bool enable_oplocks; /* enable or disable oplocks */
GLOBAL_EXTERN bool lookupCacheEnabled; extern bool lookupCacheEnabled;
GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent extern unsigned int global_secflags; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */ with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ extern unsigned int CIFSMaxBufSize; /* max size not including hdr */
GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ extern unsigned int cifs_min_small; /* min size of small buf pool */
GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
#ifdef CONFIG_CIFS_ACL #ifdef CONFIG_CIFS_ACL
GLOBAL_EXTERN struct rb_root uidtree; GLOBAL_EXTERN struct rb_root uidtree;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#ifndef _CIFSPROTO_H #ifndef _CIFSPROTO_H
#define _CIFSPROTO_H #define _CIFSPROTO_H
#include <linux/nls.h> #include <linux/nls.h>
#include "trace.h"
struct statfs; struct statfs;
struct smb_vol; struct smb_vol;
...@@ -47,6 +48,7 @@ extern void _free_xid(unsigned int); ...@@ -47,6 +48,7 @@ extern void _free_xid(unsigned int);
cifs_dbg(FYI, "CIFS VFS: in %s as Xid: %u with uid: %d\n", \ cifs_dbg(FYI, "CIFS 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__); \
__xid; \ __xid; \
}) })
...@@ -55,6 +57,10 @@ do { \ ...@@ -55,6 +57,10 @@ do { \
_free_xid(curr_xid); \ _free_xid(curr_xid); \
cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \ cifs_dbg(FYI, "CIFS VFS: leaving %s (xid = %u) rc = %d\n", \
__func__, curr_xid, (int)rc); \ __func__, curr_xid, (int)rc); \
if (rc) \
trace_smb3_exit_err(curr_xid, __func__, (int)rc); \
else \
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);
...@@ -124,7 +130,7 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, ...@@ -124,7 +130,7 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
unsigned int bytes_written); unsigned int bytes_written);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
extern unsigned int smbCalcSize(void *buf); extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
...@@ -197,7 +203,9 @@ extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); ...@@ -197,7 +203,9 @@ extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read); unsigned int to_read);
extern int cifs_read_page_from_socket(struct TCP_Server_Info *server, extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
struct page *page, unsigned int to_read); struct page *page,
unsigned int page_offset,
unsigned int to_read);
extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
struct cifs_sb_info *cifs_sb); struct cifs_sb_info *cifs_sb);
extern int cifs_match_super(struct super_block *, void *); extern int cifs_match_super(struct super_block *, void *);
...@@ -525,6 +533,8 @@ int cifs_async_writev(struct cifs_writedata *wdata, ...@@ -525,6 +533,8 @@ int cifs_async_writev(struct cifs_writedata *wdata,
void cifs_writev_complete(struct work_struct *work); void cifs_writev_complete(struct work_struct *work);
struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
work_func_t complete); work_func_t complete);
struct cifs_writedata *cifs_writedata_direct_alloc(struct page **pages,
work_func_t complete);
void cifs_writedata_release(struct kref *refcount); void cifs_writedata_release(struct kref *refcount);
int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, struct cifs_sb_info *cifs_sb,
......
...@@ -106,6 +106,12 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) ...@@ -106,6 +106,12 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
open_file->oplock_break_cancelled = true; open_file->oplock_break_cancelled = true;
} }
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
mutex_lock(&tcon->prfid_mutex);
tcon->valid_root_fid = false;
memset(tcon->prfid, 0, sizeof(struct cifs_fid));
mutex_unlock(&tcon->prfid_mutex);
/* /*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted * BB Add call to invalidate_inodes(sb) for all superblocks mounted
* to this tcon. * to this tcon.
...@@ -1946,6 +1952,7 @@ cifs_writedata_release(struct kref *refcount) ...@@ -1946,6 +1952,7 @@ cifs_writedata_release(struct kref *refcount)
if (wdata->cfile) if (wdata->cfile)
cifsFileInfo_put(wdata->cfile); cifsFileInfo_put(wdata->cfile);
kvfree(wdata->pages);
kfree(wdata); kfree(wdata);
} }
...@@ -2068,13 +2075,23 @@ cifs_writev_complete(struct work_struct *work) ...@@ -2068,13 +2075,23 @@ cifs_writev_complete(struct work_struct *work)
struct cifs_writedata * struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
if (pages)
return cifs_writedata_direct_alloc(pages, complete);
return NULL;
}
struct cifs_writedata *
cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
{ {
struct cifs_writedata *wdata; struct cifs_writedata *wdata;
/* writedata + number of page pointers */ wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
wdata = kzalloc(sizeof(*wdata) +
sizeof(struct page *) * nr_pages, GFP_NOFS);
if (wdata != NULL) { if (wdata != NULL) {
wdata->pages = pages;
kref_init(&wdata->refcount); kref_init(&wdata->refcount);
INIT_LIST_HEAD(&wdata->list); INIT_LIST_HEAD(&wdata->list);
init_completion(&wdata->done); init_completion(&wdata->done);
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#define RFC1001_PORT 139 #define RFC1001_PORT 139
extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_req_poolp;
extern bool disable_legacy_dialects;
/* FIXME: should these be tunable? */ /* FIXME: should these be tunable? */
#define TLINK_ERROR_EXPIRE (1 * HZ) #define TLINK_ERROR_EXPIRE (1 * HZ)
...@@ -76,9 +77,10 @@ enum { ...@@ -76,9 +77,10 @@ enum {
Opt_mapposix, Opt_nomapposix, Opt_mapposix, Opt_nomapposix,
Opt_mapchars, Opt_nomapchars, Opt_sfu, Opt_mapchars, Opt_nomapchars, Opt_sfu,
Opt_nosfu, Opt_nodfs, Opt_posixpaths, Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Opt_noposixpaths, Opt_nounix, Opt_noposixpaths, Opt_nounix, Opt_unix,
Opt_nocase, Opt_nocase,
Opt_brl, Opt_nobrl, Opt_brl, Opt_nobrl,
Opt_handlecache, Opt_nohandlecache,
Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids, Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Opt_nosetuids, Opt_dynperm, Opt_nodynperm, Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
Opt_nohard, Opt_nosoft, Opt_nohard, Opt_nosoft,
...@@ -144,10 +146,16 @@ static const match_table_t cifs_mount_option_tokens = { ...@@ -144,10 +146,16 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_noposixpaths, "noposixpaths" }, { Opt_noposixpaths, "noposixpaths" },
{ Opt_nounix, "nounix" }, { Opt_nounix, "nounix" },
{ Opt_nounix, "nolinux" }, { Opt_nounix, "nolinux" },
{ Opt_nounix, "noposix" },
{ Opt_unix, "unix" },
{ Opt_unix, "linux" },
{ Opt_unix, "posix" },
{ Opt_nocase, "nocase" }, { Opt_nocase, "nocase" },
{ Opt_nocase, "ignorecase" }, { Opt_nocase, "ignorecase" },
{ Opt_brl, "brl" }, { Opt_brl, "brl" },
{ Opt_nobrl, "nobrl" }, { Opt_nobrl, "nobrl" },
{ Opt_handlecache, "handlecache" },
{ Opt_nohandlecache, "nohandlecache" },
{ Opt_nobrl, "nolock" }, { Opt_nobrl, "nolock" },
{ Opt_forcemandatorylock, "forcemandatorylock" }, { Opt_forcemandatorylock, "forcemandatorylock" },
{ Opt_forcemandatorylock, "forcemand" }, { Opt_forcemandatorylock, "forcemand" },
...@@ -591,10 +599,11 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, ...@@ -591,10 +599,11 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
int int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
unsigned int to_read) unsigned int page_offset, unsigned int to_read)
{ {
struct msghdr smb_msg; struct msghdr smb_msg;
struct bio_vec bv = {.bv_page = page, .bv_len = to_read}; struct bio_vec bv = {
.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
return cifs_readv_from_socket(server, &smb_msg); return cifs_readv_from_socket(server, &smb_msg);
} }
...@@ -848,6 +857,7 @@ cifs_demultiplex_thread(void *p) ...@@ -848,6 +857,7 @@ cifs_demultiplex_thread(void *p)
int length; int length;
struct TCP_Server_Info *server = p; struct TCP_Server_Info *server = p;
unsigned int pdu_length; unsigned int pdu_length;
unsigned int next_offset;
char *buf = NULL; char *buf = NULL;
struct task_struct *task_to_wake = NULL; struct task_struct *task_to_wake = NULL;
struct mid_q_entry *mid_entry; struct mid_q_entry *mid_entry;
...@@ -874,6 +884,10 @@ cifs_demultiplex_thread(void *p) ...@@ -874,6 +884,10 @@ cifs_demultiplex_thread(void *p)
length = cifs_read_from_socket(server, buf, pdu_length); length = cifs_read_from_socket(server, buf, pdu_length);
if (length < 0) if (length < 0)
continue; continue;
if (server->vals->header_preamble_size == 0)
server->total_read = 0;
else
server->total_read = length; server->total_read = length;
/* /*
...@@ -881,17 +895,18 @@ cifs_demultiplex_thread(void *p) ...@@ -881,17 +895,18 @@ cifs_demultiplex_thread(void *p)
* so we can now interpret the length field. * so we can now interpret the length field.
*/ */
pdu_length = get_rfc1002_length(buf); pdu_length = get_rfc1002_length(buf);
server->pdu_size = pdu_length;
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
if (!is_smb_response(server, buf[0])) if (!is_smb_response(server, buf[0]))
continue; continue;
next_pdu:
server->pdu_size = pdu_length;
/* make sure we have enough to get to the MID */ /* make sure we have enough to get to the MID */
if (pdu_length < HEADER_SIZE(server) - 1 - if (server->pdu_size < HEADER_SIZE(server) - 1 -
server->vals->header_preamble_size) { server->vals->header_preamble_size) {
cifs_dbg(VFS, "SMB response too short (%u bytes)\n", cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
pdu_length); server->pdu_size);
cifs_reconnect(server); cifs_reconnect(server);
wake_up(&server->response_q); wake_up(&server->response_q);
continue; continue;
...@@ -906,6 +921,12 @@ cifs_demultiplex_thread(void *p) ...@@ -906,6 +921,12 @@ cifs_demultiplex_thread(void *p)
continue; continue;
server->total_read += length; server->total_read += length;
if (server->ops->next_header) {
next_offset = server->ops->next_header(buf);
if (next_offset)
server->pdu_size = next_offset;
}
if (server->ops->is_transform_hdr && if (server->ops->is_transform_hdr &&
server->ops->receive_transform && server->ops->receive_transform &&
server->ops->is_transform_hdr(buf)) { server->ops->is_transform_hdr(buf)) {
...@@ -948,10 +969,18 @@ cifs_demultiplex_thread(void *p) ...@@ -948,10 +969,18 @@ cifs_demultiplex_thread(void *p)
HEADER_SIZE(server)); HEADER_SIZE(server));
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
if (server->ops->dump_detail) if (server->ops->dump_detail)
server->ops->dump_detail(buf); server->ops->dump_detail(buf, server);
cifs_dump_mids(server); cifs_dump_mids(server);
#endif /* CIFS_DEBUG2 */ #endif /* CIFS_DEBUG2 */
}
if (pdu_length > server->pdu_size) {
if (!allocate_buffers(server))
continue;
pdu_length -= server->pdu_size;
server->total_read = 0;
server->large_buf = false;
buf = server->smallbuf;
goto next_pdu;
} }
} /* end while !EXITING */ } /* end while !EXITING */
...@@ -1143,10 +1172,18 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) ...@@ -1143,10 +1172,18 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
switch (match_token(value, cifs_smb_version_tokens, args)) { switch (match_token(value, cifs_smb_version_tokens, args)) {
case Smb_1: case Smb_1:
if (disable_legacy_dialects) {
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
return 1;
}
vol->ops = &smb1_operations; vol->ops = &smb1_operations;
vol->vals = &smb1_values; vol->vals = &smb1_values;
break; break;
case Smb_20: case Smb_20:
if (disable_legacy_dialects) {
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
return 1;
}
vol->ops = &smb20_operations; vol->ops = &smb20_operations;
vol->vals = &smb20_values; vol->vals = &smb20_values;
break; break;
...@@ -1426,8 +1463,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1426,8 +1463,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->posix_paths = 0; vol->posix_paths = 0;
break; break;
case Opt_nounix: case Opt_nounix:
if (vol->linux_ext)
cifs_dbg(VFS,
"conflicting unix mount options\n");
vol->no_linux_ext = 1; vol->no_linux_ext = 1;
break; break;
case Opt_unix:
if (vol->no_linux_ext)
cifs_dbg(VFS,
"conflicting unix mount options\n");
vol->linux_ext = 1;
break;
case Opt_nocase: case Opt_nocase:
vol->nocase = 1; vol->nocase = 1;
break; break;
...@@ -1445,6 +1491,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1445,6 +1491,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
(S_IALLUGO & ~(S_ISUID | S_IXGRP))) (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
vol->file_mode = S_IALLUGO; vol->file_mode = S_IALLUGO;
break; break;
case Opt_nohandlecache:
vol->nohandlecache = 1;
break;
case Opt_handlecache:
vol->nohandlecache = 0;
break;
case Opt_forcemandatorylock: case Opt_forcemandatorylock:
vol->mand_lock = 1; vol->mand_lock = 1;
break; break;
...@@ -2967,6 +3019,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) ...@@ -2967,6 +3019,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
} }
} }
#ifdef CONFIG_CIFS_SMB311
if ((volume_info->linux_ext) && (ses->server->posix_ext_supported)) {
if (ses->server->vals->protocol_id == SMB311_PROT_ID)
tcon->posix_extensions = true;
}
#endif /* 311 */
/* /*
* BB Do we need to wrap session_mutex around this TCon call and Unix * BB Do we need to wrap session_mutex around this TCon call and Unix
* SetFS as we do on SessSetup and reconnect? * SetFS as we do on SessSetup and reconnect?
...@@ -3022,6 +3081,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) ...@@ -3022,6 +3081,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
*/ */
tcon->retry = volume_info->retry; tcon->retry = volume_info->retry;
tcon->nocase = volume_info->nocase; tcon->nocase = volume_info->nocase;
tcon->nohandlecache = volume_info->nohandlecache;
tcon->local_lease = volume_info->local_lease; tcon->local_lease = volume_info->local_lease;
INIT_LIST_HEAD(&tcon->pending_opens); INIT_LIST_HEAD(&tcon->pending_opens);
...@@ -3580,6 +3640,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -3580,6 +3640,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
if (pvolume_info->nobrl) if (pvolume_info->nobrl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
if (pvolume_info->nohandlecache)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
if (pvolume_info->nostrictsync) if (pvolume_info->nostrictsync)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
if (pvolume_info->mand_lock) if (pvolume_info->mand_lock)
...@@ -3922,6 +3984,12 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) ...@@ -3922,6 +3984,12 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
goto remote_path_check; goto remote_path_check;
} }
#ifdef CONFIG_CIFS_SMB311
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
if (tcon->posix_extensions)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
#endif /* SMB3.11 */
/* tell server which Unix caps we support */ /* tell server which Unix caps we support */
if (cap_unix(tcon->ses)) { if (cap_unix(tcon->ses)) {
/* reset of caps checks mount to see if unix extensions /* reset of caps checks mount to see if unix extensions
...@@ -4353,6 +4421,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) ...@@ -4353,6 +4421,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
vol_info->UNC = master_tcon->treeName; vol_info->UNC = master_tcon->treeName;
vol_info->retry = master_tcon->retry; vol_info->retry = master_tcon->retry;
vol_info->nocase = master_tcon->nocase; vol_info->nocase = master_tcon->nocase;
vol_info->nohandlecache = master_tcon->nohandlecache;
vol_info->local_lease = master_tcon->local_lease; vol_info->local_lease = master_tcon->local_lease;
vol_info->no_linux_ext = !master_tcon->unix_ext; vol_info->no_linux_ext = !master_tcon->unix_ext;
vol_info->sectype = master_tcon->ses->sectype; vol_info->sectype = master_tcon->ses->sectype;
...@@ -4382,8 +4451,14 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) ...@@ -4382,8 +4451,14 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
goto out; goto out;
} }
#ifdef CONFIG_CIFS_SMB311
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
if (tcon->posix_extensions)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
#endif /* SMB3.11 */
if (cap_unix(ses)) if (cap_unix(ses))
reset_cifs_unix_caps(0, tcon, NULL, vol_info); reset_cifs_unix_caps(0, tcon, NULL, vol_info);
out: out:
kfree(vol_info->username); kfree(vol_info->username);
kzfree(vol_info->password); kzfree(vol_info->password);
......
...@@ -369,7 +369,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, ...@@ -369,7 +369,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
oparms.path = full_path; oparms.path = full_path;
oparms.fid = fid; oparms.fid = fid;
oparms.reconnect = false; oparms.reconnect = false;
oparms.mode = mode;
rc = server->ops->open(xid, &oparms, oplock, buf); rc = server->ops->open(xid, &oparms, oplock, buf);
if (rc) { if (rc) {
cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
......
...@@ -2880,13 +2880,13 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) ...@@ -2880,13 +2880,13 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
} }
static struct cifs_readdata * static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) cifs_readdata_direct_alloc(struct page **pages, work_func_t complete)
{ {
struct cifs_readdata *rdata; struct cifs_readdata *rdata;
rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages), rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
GFP_KERNEL);
if (rdata != NULL) { if (rdata != NULL) {
rdata->pages = pages;
kref_init(&rdata->refcount); kref_init(&rdata->refcount);
INIT_LIST_HEAD(&rdata->list); INIT_LIST_HEAD(&rdata->list);
init_completion(&rdata->done); init_completion(&rdata->done);
...@@ -2896,6 +2896,22 @@ cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) ...@@ -2896,6 +2896,22 @@ cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
return rdata; return rdata;
} }
static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
kzalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL);
struct cifs_readdata *ret = NULL;
if (pages) {
ret = cifs_readdata_direct_alloc(pages, complete);
if (!ret)
kfree(pages);
}
return ret;
}
void void
cifs_readdata_release(struct kref *refcount) cifs_readdata_release(struct kref *refcount)
{ {
...@@ -2910,6 +2926,7 @@ cifs_readdata_release(struct kref *refcount) ...@@ -2910,6 +2926,7 @@ cifs_readdata_release(struct kref *refcount)
if (rdata->cfile) if (rdata->cfile)
cifsFileInfo_put(rdata->cfile); cifsFileInfo_put(rdata->cfile);
kvfree(rdata->pages);
kfree(rdata); kfree(rdata);
} }
...@@ -3009,12 +3026,20 @@ uncached_fill_pages(struct TCP_Server_Info *server, ...@@ -3009,12 +3026,20 @@ uncached_fill_pages(struct TCP_Server_Info *server,
int result = 0; int result = 0;
unsigned int i; unsigned int i;
unsigned int nr_pages = rdata->nr_pages; unsigned int nr_pages = rdata->nr_pages;
unsigned int page_offset = rdata->page_offset;
rdata->got_bytes = 0; rdata->got_bytes = 0;
rdata->tailsz = PAGE_SIZE; rdata->tailsz = PAGE_SIZE;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
struct page *page = rdata->pages[i]; struct page *page = rdata->pages[i];
size_t n; size_t n;
unsigned int segment_size = rdata->pagesz;
if (i == 0)
segment_size -= page_offset;
else
page_offset = 0;
if (len <= 0) { if (len <= 0) {
/* no need to hold page hostage */ /* no need to hold page hostage */
...@@ -3023,24 +3048,25 @@ uncached_fill_pages(struct TCP_Server_Info *server, ...@@ -3023,24 +3048,25 @@ uncached_fill_pages(struct TCP_Server_Info *server,
put_page(page); put_page(page);
continue; continue;
} }
n = len; n = len;
if (len >= PAGE_SIZE) { if (len >= segment_size)
/* enough data to fill the page */ /* enough data to fill the page */
n = PAGE_SIZE; n = segment_size;
len -= n; else
} else {
zero_user(page, len, PAGE_SIZE - len);
rdata->tailsz = len; rdata->tailsz = len;
len = 0; len -= n;
}
if (iter) if (iter)
result = copy_page_from_iter(page, 0, n, iter); result = copy_page_from_iter(
page, page_offset, n, iter);
#ifdef CONFIG_CIFS_SMB_DIRECT #ifdef CONFIG_CIFS_SMB_DIRECT
else if (rdata->mr) else if (rdata->mr)
result = n; result = n;
#endif #endif
else else
result = cifs_read_page_from_socket(server, page, n); result = cifs_read_page_from_socket(
server, page, page_offset, n);
if (result < 0) if (result < 0)
break; break;
...@@ -3113,6 +3139,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3113,6 +3139,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
rdata->bytes = cur_len; rdata->bytes = cur_len;
rdata->pid = pid; rdata->pid = pid;
rdata->pagesz = PAGE_SIZE; rdata->pagesz = PAGE_SIZE;
rdata->tailsz = PAGE_SIZE;
rdata->read_into_pages = cifs_uncached_read_into_pages; rdata->read_into_pages = cifs_uncached_read_into_pages;
rdata->copy_into_pages = cifs_uncached_copy_into_pages; rdata->copy_into_pages = cifs_uncached_copy_into_pages;
rdata->credits = credits; rdata->credits = credits;
...@@ -3557,6 +3584,7 @@ readpages_fill_pages(struct TCP_Server_Info *server, ...@@ -3557,6 +3584,7 @@ readpages_fill_pages(struct TCP_Server_Info *server,
u64 eof; u64 eof;
pgoff_t eof_index; pgoff_t eof_index;
unsigned int nr_pages = rdata->nr_pages; unsigned int nr_pages = rdata->nr_pages;
unsigned int page_offset = rdata->page_offset;
/* determine the eof that the server (probably) has */ /* determine the eof that the server (probably) has */
eof = CIFS_I(rdata->mapping->host)->server_eof; eof = CIFS_I(rdata->mapping->host)->server_eof;
...@@ -3567,13 +3595,21 @@ readpages_fill_pages(struct TCP_Server_Info *server, ...@@ -3567,13 +3595,21 @@ readpages_fill_pages(struct TCP_Server_Info *server,
rdata->tailsz = PAGE_SIZE; rdata->tailsz = PAGE_SIZE;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
struct page *page = rdata->pages[i]; struct page *page = rdata->pages[i];
size_t n = PAGE_SIZE; unsigned int to_read = rdata->pagesz;
size_t n;
if (i == 0)
to_read -= page_offset;
else
page_offset = 0;
n = to_read;
if (len >= PAGE_SIZE) { if (len >= to_read) {
len -= PAGE_SIZE; len -= to_read;
} else if (len > 0) { } else if (len > 0) {
/* enough for partial page, fill and zero the rest */ /* enough for partial page, fill and zero the rest */
zero_user(page, len, PAGE_SIZE - len); zero_user(page, len + page_offset, to_read - len);
n = rdata->tailsz = len; n = rdata->tailsz = len;
len = 0; len = 0;
} else if (page->index > eof_index) { } else if (page->index > eof_index) {
...@@ -3605,13 +3641,15 @@ readpages_fill_pages(struct TCP_Server_Info *server, ...@@ -3605,13 +3641,15 @@ readpages_fill_pages(struct TCP_Server_Info *server,
} }
if (iter) if (iter)
result = copy_page_from_iter(page, 0, n, iter); result = copy_page_from_iter(
page, page_offset, n, iter);
#ifdef CONFIG_CIFS_SMB_DIRECT #ifdef CONFIG_CIFS_SMB_DIRECT
else if (rdata->mr) else if (rdata->mr)
result = n; result = n;
#endif #endif
else else
result = cifs_read_page_from_socket(server, page, n); result = cifs_read_page_from_socket(
server, page, page_offset, n);
if (result < 0) if (result < 0)
break; break;
...@@ -3790,6 +3828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -3790,6 +3828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
rdata->bytes = bytes; rdata->bytes = bytes;
rdata->pid = pid; rdata->pid = pid;
rdata->pagesz = PAGE_SIZE; rdata->pagesz = PAGE_SIZE;
rdata->tailsz = PAGE_SIZE;
rdata->read_into_pages = cifs_readpages_read_into_pages; rdata->read_into_pages = cifs_readpages_read_into_pages;
rdata->copy_into_pages = cifs_readpages_copy_into_pages; rdata->copy_into_pages = cifs_readpages_copy_into_pages;
rdata->credits = credits; rdata->credits = credits;
......
...@@ -746,7 +746,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, ...@@ -746,7 +746,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
cifs_dbg(FYI, "Getting info on %s\n", full_path); cifs_dbg(FYI, "Getting info on %s\n", full_path);
if ((data == NULL) && (*inode != NULL)) { if ((data == NULL) && (*inode != NULL)) {
if (CIFS_CACHE_READ(CIFS_I(*inode))) { if (CIFS_CACHE_READ(CIFS_I(*inode)) &&
CIFS_I(*inode)->time != 0) {
cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
goto cgii_exit; goto cgii_exit;
} }
...@@ -1857,15 +1858,15 @@ cifs_inode_needs_reval(struct inode *inode) ...@@ -1857,15 +1858,15 @@ cifs_inode_needs_reval(struct inode *inode)
struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifsInodeInfo *cifs_i = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
if (cifs_i->time == 0)
return true;
if (CIFS_CACHE_READ(cifs_i)) if (CIFS_CACHE_READ(cifs_i))
return false; return false;
if (!lookupCacheEnabled) if (!lookupCacheEnabled)
return true; return true;
if (cifs_i->time == 0)
return true;
if (!cifs_sb->actimeo) if (!cifs_sb->actimeo)
return true; return true;
...@@ -2104,10 +2105,14 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) ...@@ -2104,10 +2105,14 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
static void cifs_setsize(struct inode *inode, loff_t offset) static void cifs_setsize(struct inode *inode, loff_t offset)
{ {
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
i_size_write(inode, offset); i_size_write(inode, offset);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
/* Cached inode must be refreshed on truncate */
cifs_i->time = 0;
truncate_pagecache(inode, offset); truncate_pagecache(inode, offset);
} }
......
...@@ -117,6 +117,8 @@ tconInfoAlloc(void) ...@@ -117,6 +117,8 @@ tconInfoAlloc(void)
INIT_LIST_HEAD(&ret_buf->openFileList); INIT_LIST_HEAD(&ret_buf->openFileList);
INIT_LIST_HEAD(&ret_buf->tcon_list); INIT_LIST_HEAD(&ret_buf->tcon_list);
spin_lock_init(&ret_buf->open_file_lock); spin_lock_init(&ret_buf->open_file_lock);
mutex_init(&ret_buf->prfid_mutex);
ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL);
#ifdef CONFIG_CIFS_STATS #ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock); spin_lock_init(&ret_buf->stat_lock);
#endif #endif
...@@ -134,6 +136,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) ...@@ -134,6 +136,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free)
atomic_dec(&tconInfoAllocCount); atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem); kfree(buf_to_free->nativeFileSystem);
kzfree(buf_to_free->password); kzfree(buf_to_free->password);
kfree(buf_to_free->prfid);
kfree(buf_to_free); kfree(buf_to_free);
} }
...@@ -145,7 +148,7 @@ cifs_buf_get(void) ...@@ -145,7 +148,7 @@ cifs_buf_get(void)
* SMB2 header is bigger than CIFS one - no problems to clean some * SMB2 header is bigger than CIFS one - no problems to clean some
* more bytes for CIFS. * more bytes for CIFS.
*/ */
size_t buf_size = sizeof(struct smb2_hdr); size_t buf_size = sizeof(struct smb2_sync_hdr);
/* /*
* We could use negotiated size instead of max_msgsize - * We could use negotiated size instead of max_msgsize -
...@@ -339,7 +342,7 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) ...@@ -339,7 +342,7 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
/* otherwise, there is enough to get to the BCC */ /* otherwise, there is enough to get to the BCC */
if (check_smb_hdr(smb)) if (check_smb_hdr(smb))
return -EIO; return -EIO;
clc_len = smbCalcSize(smb); clc_len = smbCalcSize(smb, server);
if (4 + rfclen != total_read) { if (4 + rfclen != total_read) {
cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n", cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
......
...@@ -903,7 +903,7 @@ map_smb_to_linux_error(char *buf, bool logErr) ...@@ -903,7 +903,7 @@ map_smb_to_linux_error(char *buf, bool logErr)
* portion, the number of word parameters and the data portion of the message * portion, the number of word parameters and the data portion of the message
*/ */
unsigned int unsigned int
smbCalcSize(void *buf) smbCalcSize(void *buf, struct TCP_Server_Info *server)
{ {
struct smb_hdr *ptr = (struct smb_hdr *)buf; struct smb_hdr *ptr = (struct smb_hdr *)buf;
return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
......
...@@ -650,7 +650,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, ...@@ -650,7 +650,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
char *cur_ent; char *cur_ent;
char *end_of_smb = cfile->srch_inf.ntwrk_buf_start + char *end_of_smb = cfile->srch_inf.ntwrk_buf_start +
server->ops->calc_smb_size( server->ops->calc_smb_size(
cfile->srch_inf.ntwrk_buf_start); cfile->srch_inf.ntwrk_buf_start,
server);
cur_ent = cfile->srch_inf.srch_entries_start; cur_ent = cfile->srch_inf.srch_entries_start;
first_entry_in_buffer = cfile->srch_inf.index_of_last_entry first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
...@@ -831,7 +832,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -831,7 +832,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
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",
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
max_len = tcon->ses->server->ops->calc_smb_size( max_len = tcon->ses->server->ops->calc_smb_size(
cifsFile->srch_inf.ntwrk_buf_start); cifsFile->srch_inf.ntwrk_buf_start,
tcon->ses->server);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
......
...@@ -61,9 +61,4 @@ ...@@ -61,9 +61,4 @@
/* Maximum buffer size value we can send with 1 credit */ /* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536 #define SMB2_MAX_BUFFER_SIZE 65536
static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
{
return &(((struct smb2_hdr *)buf)->sync_hdr);
}
#endif /* _SMB2_GLOB_H */ #endif /* _SMB2_GLOB_H */
...@@ -44,11 +44,22 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -44,11 +44,22 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
__u32 create_options, void *data, int command) __u32 create_options, void *data, int command)
{ {
int rc, tmprc = 0; int rc, tmprc = 0;
__le16 *utf16_path; __le16 *utf16_path = NULL;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_fid fid; struct cifs_fid fid;
bool use_cached_root_handle = false;
if ((strcmp(full_path, "") == 0) && (create_options == 0) &&
(desired_access == FILE_READ_ATTRIBUTES) &&
(create_disposition == FILE_OPEN) &&
(tcon->nohandlecache == false)) {
rc = open_shroot(xid, tcon, &fid);
if (rc == 0)
use_cached_root_handle = true;
}
if (use_cached_root_handle == false) {
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
if (!utf16_path) if (!utf16_path)
return -ENOMEM; return -ENOMEM;
...@@ -65,6 +76,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -65,6 +76,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
kfree(utf16_path); kfree(utf16_path);
return rc; return rc;
} }
}
switch (command) { switch (command) {
case SMB2_OP_DELETE: case SMB2_OP_DELETE:
...@@ -107,6 +119,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -107,6 +119,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
break; break;
} }
if (use_cached_root_handle == false)
rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
if (tmprc) if (tmprc)
rc = tmprc; rc = tmprc;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "smb2proto.h" #include "smb2proto.h"
#include "smb2status.h" #include "smb2status.h"
#include "smb2glob.h" #include "smb2glob.h"
#include "trace.h"
struct status_to_posix_error { struct status_to_posix_error {
__le32 smb2_status; __le32 smb2_status;
...@@ -2450,13 +2451,16 @@ smb2_print_status(__le32 status) ...@@ -2450,13 +2451,16 @@ smb2_print_status(__le32 status)
int int
map_smb2_to_linux_error(char *buf, bool log_err) map_smb2_to_linux_error(char *buf, bool log_err)
{ {
struct smb2_sync_hdr *shdr = get_sync_hdr(buf); struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
unsigned int i; unsigned int i;
int rc = -EIO; int rc = -EIO;
__le32 smb2err = shdr->Status; __le32 smb2err = shdr->Status;
if (smb2err == 0) if (smb2err == 0) {
trace_smb3_cmd_done(shdr->TreeId, shdr->SessionId,
le16_to_cpu(shdr->Command), le64_to_cpu(shdr->MessageId));
return 0; return 0;
}
/* mask facility */ /* mask facility */
if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) && if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) &&
...@@ -2478,5 +2482,8 @@ map_smb2_to_linux_error(char *buf, bool log_err) ...@@ -2478,5 +2482,8 @@ map_smb2_to_linux_error(char *buf, bool log_err)
cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n", cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n",
__le32_to_cpu(smb2err), rc); __le32_to_cpu(smb2err), rc);
trace_smb3_cmd_err(shdr->TreeId, shdr->SessionId,
le16_to_cpu(shdr->Command),
le64_to_cpu(shdr->MessageId), le32_to_cpu(smb2err), rc);
return rc; return rc;
} }
...@@ -94,8 +94,8 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { ...@@ -94,8 +94,8 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
}; };
#ifdef CONFIG_CIFS_SMB311 #ifdef CONFIG_CIFS_SMB311
static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
size_t hdr_preamble_size) __u32 non_ctxlen)
{ {
__u16 neg_count; __u16 neg_count;
__u32 nc_offset, size_of_pad_before_neg_ctxts; __u32 nc_offset, size_of_pad_before_neg_ctxts;
...@@ -109,12 +109,11 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, ...@@ -109,12 +109,11 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
/* 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 - hdr_preamble_size /* RFC1001 len */) { if (nc_offset < non_ctxlen) {
printk_once(KERN_WARNING "invalid negotiate context offset\n"); printk_once(KERN_WARNING "invalid negotiate context offset\n");
return 0; return 0;
} }
size_of_pad_before_neg_ctxts = nc_offset - size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
(non_ctxlen - hdr_preamble_size);
/* 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))) {
...@@ -131,25 +130,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, ...@@ -131,25 +130,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
#endif /* CIFS_SMB311 */ #endif /* CIFS_SMB311 */
int int
smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
{ {
struct smb2_pdu *pdu = (struct smb2_pdu *)buf; struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
struct smb2_hdr *hdr = &pdu->hdr; struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
__u64 mid; __u64 mid;
__u32 len = get_rfc1002_length(buf);
__u32 clc_len; /* calculated length */ __u32 clc_len; /* calculated length */
int command; int command;
int pdu_size = sizeof(struct smb2_sync_pdu);
/* BB disable following printk later */ int hdr_size = sizeof(struct smb2_sync_hdr);
cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
__func__, length, len);
/* /*
* Add function to do table lookup of StructureSize by command * Add function to do table lookup of StructureSize by command
* ie Validate the wct via smb2_struct_sizes table above * ie Validate the wct via smb2_struct_sizes table above
*/ */
if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
struct smb2_transform_hdr *thdr = struct smb2_transform_hdr *thdr =
(struct smb2_transform_hdr *)buf; (struct smb2_transform_hdr *)buf;
...@@ -173,8 +167,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -173,8 +167,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
mid = le64_to_cpu(shdr->MessageId); mid = le64_to_cpu(shdr->MessageId);
if (length < sizeof(struct smb2_pdu)) { if (len < pdu_size) {
if ((length >= sizeof(struct smb2_hdr)) if ((len >= hdr_size)
&& (shdr->Status != 0)) { && (shdr->Status != 0)) {
pdu->StructureSize2 = 0; pdu->StructureSize2 = 0;
/* /*
...@@ -187,8 +181,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -187,8 +181,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
return 1; return 1;
} }
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
srvr->vals->header_preamble_size) {
cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n", cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
mid); mid);
return 1; return 1;
...@@ -227,44 +220,38 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -227,44 +220,38 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
} }
if (srvr->vals->header_preamble_size + len != length) { clc_len = smb2_calc_size(buf, srvr);
cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n",
length, srvr->vals->header_preamble_size + len, mid);
return 1;
}
clc_len = smb2_calc_size(hdr);
#ifdef CONFIG_CIFS_SMB311 #ifdef CONFIG_CIFS_SMB311
if (shdr->Command == SMB2_NEGOTIATE) if (shdr->Command == SMB2_NEGOTIATE)
clc_len += get_neg_ctxt_len(hdr, len, clc_len, clc_len += get_neg_ctxt_len(shdr, len, clc_len);
srvr->vals->header_preamble_size);
#endif /* SMB311 */ #endif /* SMB311 */
if (srvr->vals->header_preamble_size + len != clc_len) { if (len != clc_len) {
cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n", cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
clc_len, srvr->vals->header_preamble_size + len, mid); clc_len, len, mid);
/* create failed on symlink */ /* create failed on symlink */
if (command == SMB2_CREATE_HE && if (command == SMB2_CREATE_HE &&
shdr->Status == STATUS_STOPPED_ON_SYMLINK) shdr->Status == STATUS_STOPPED_ON_SYMLINK)
return 0; return 0;
/* Windows 7 server returns 24 bytes more */ /* Windows 7 server returns 24 bytes more */
if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE) if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
return 0; return 0;
/* server can return one byte more due to implied bcc[0] */ /* server can return one byte more due to implied bcc[0] */
if (clc_len == srvr->vals->header_preamble_size + len + 1) if (clc_len == len + 1)
return 0; return 0;
/* /*
* MacOS server pads after SMB2.1 write response with 3 bytes * MacOS server pads after SMB2.1 write response with 3 bytes
* of junk. Other servers match RFC1001 len to actual * of junk. Other servers match RFC1001 len to actual
* SMB2/SMB3 frame length (header + smb2 response specific data) * SMB2/SMB3 frame length (header + smb2 response specific data)
* Some windows servers do too when compounding is used.
* Log the server error (once), but allow it and continue * Log the server error (once), but allow it and continue
* since the frame is parseable. * since the frame is parseable.
*/ */
if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) { if (clc_len < len) {
printk_once(KERN_WARNING printk_once(KERN_WARNING
"SMB2 server sent bad RFC1001 len %d not %zu\n", "SMB2 server sent bad RFC1001 len %d not %d\n",
len, clc_len - srvr->vals->header_preamble_size); len, clc_len);
return 0; return 0;
} }
...@@ -305,15 +292,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { ...@@ -305,15 +292,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
* area and the offset to it (from the beginning of the smb are also returned. * area and the offset to it (from the beginning of the smb are also returned.
*/ */
char * char *
smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
{ {
struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
*off = 0; *off = 0;
*len = 0; *len = 0;
/* error responses do not have data area */ /* error responses do not have data area */
if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
(((struct smb2_err_rsp *)hdr)->StructureSize) == (((struct smb2_err_rsp *)shdr)->StructureSize) ==
SMB2_ERROR_STRUCTURE_SIZE2) SMB2_ERROR_STRUCTURE_SIZE2)
return NULL; return NULL;
...@@ -325,42 +311,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) ...@@ -325,42 +311,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
switch (shdr->Command) { switch (shdr->Command) {
case SMB2_NEGOTIATE: case SMB2_NEGOTIATE:
*off = le16_to_cpu( *off = le16_to_cpu(
((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset);
*len = le16_to_cpu( *len = le16_to_cpu(
((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength); ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength);
break; break;
case SMB2_SESSION_SETUP: case SMB2_SESSION_SETUP:
*off = le16_to_cpu( *off = le16_to_cpu(
((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset); ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
*len = le16_to_cpu( *len = le16_to_cpu(
((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength); ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
break; break;
case SMB2_CREATE: case SMB2_CREATE:
*off = le32_to_cpu( *off = le32_to_cpu(
((struct smb2_create_rsp *)hdr)->CreateContextsOffset); ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
*len = le32_to_cpu( *len = le32_to_cpu(
((struct smb2_create_rsp *)hdr)->CreateContextsLength); ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
break; break;
case SMB2_QUERY_INFO: case SMB2_QUERY_INFO:
*off = le16_to_cpu( *off = le16_to_cpu(
((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset); ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
*len = le32_to_cpu( *len = le32_to_cpu(
((struct smb2_query_info_rsp *)hdr)->OutputBufferLength); ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
break; break;
case SMB2_READ: case SMB2_READ:
*off = ((struct smb2_read_rsp *)hdr)->DataOffset; /* TODO: is this a bug ? */
*len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength); *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
*len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
break; break;
case SMB2_QUERY_DIRECTORY: case SMB2_QUERY_DIRECTORY:
*off = le16_to_cpu( *off = le16_to_cpu(
((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset); ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
*len = le32_to_cpu( *len = le32_to_cpu(
((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength); ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
break; break;
case SMB2_IOCTL: case SMB2_IOCTL:
*off = le32_to_cpu( *off = le32_to_cpu(
((struct smb2_ioctl_rsp *)hdr)->OutputOffset); ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
*len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount); *len = le32_to_cpu(
((struct smb2_ioctl_rsp *)shdr)->OutputCount);
break; break;
case SMB2_CHANGE_NOTIFY: case SMB2_CHANGE_NOTIFY:
default: default:
...@@ -403,15 +391,14 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) ...@@ -403,15 +391,14 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
* portion, the number of word parameters and the data portion of the message. * portion, the number of word parameters and the data portion of the message.
*/ */
unsigned int unsigned int
smb2_calc_size(void *buf) smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
{ {
struct smb2_pdu *pdu = (struct smb2_pdu *)buf; struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
struct smb2_hdr *hdr = &pdu->hdr; struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
int offset; /* the offset from the beginning of SMB to data area */ int offset; /* the offset from the beginning of SMB to data area */
int data_length; /* the length of the variable length data area */ int data_length; /* the length of the variable length data area */
/* Structure Size has already been checked to make sure it is 64 */ /* Structure Size has already been checked to make sure it is 64 */
int len = 4 + le16_to_cpu(shdr->StructureSize); int len = le16_to_cpu(shdr->StructureSize);
/* /*
* StructureSize2, ie length of fixed parameter area has already * StructureSize2, ie length of fixed parameter area has already
...@@ -422,7 +409,7 @@ smb2_calc_size(void *buf) ...@@ -422,7 +409,7 @@ smb2_calc_size(void *buf)
if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
goto calc_size_exit; goto calc_size_exit;
smb2_get_data_area_len(&offset, &data_length, hdr); smb2_get_data_area_len(&offset, &data_length, shdr);
cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset); cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
if (data_length > 0) { if (data_length > 0) {
...@@ -430,15 +417,14 @@ smb2_calc_size(void *buf) ...@@ -430,15 +417,14 @@ smb2_calc_size(void *buf)
* Check to make sure that data area begins after fixed area, * Check to make sure that data area begins after fixed area,
* Note that last byte of the fixed area is part of data area * Note that last byte of the fixed area is part of data area
* for some commands, typically those with odd StructureSize, * for some commands, typically those with odd StructureSize,
* so we must add one to the calculation (and 4 to account for * so we must add one to the calculation.
* the size of the RFC1001 hdr.
*/ */
if (offset + 4 + 1 < len) { if (offset + 1 < len) {
cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n", cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
offset + 4 + 1, len); offset + 1, len);
data_length = 0; data_length = 0;
} else { } else {
len = 4 + offset + data_length; len = offset + data_length;
} }
} }
calc_size_exit: calc_size_exit:
...@@ -465,8 +451,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) ...@@ -465,8 +451,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
/* Windows doesn't allow paths beginning with \ */ /* Windows doesn't allow paths beginning with \ */
if (from[0] == '\\') if (from[0] == '\\')
start_of_path = from + 1; start_of_path = from + 1;
#ifdef CONFIG_CIFS_SMB311
/* SMB311 POSIX extensions paths do not include leading slash */
else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)
start_of_path = from + 1;
#endif /* 311 */
else else
start_of_path = from; start_of_path = from;
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
cifs_sb->local_nls, map_type); cifs_sb->local_nls, map_type);
return to; return to;
...@@ -621,7 +613,7 @@ smb2_is_valid_lease_break(char *buffer) ...@@ -621,7 +613,7 @@ smb2_is_valid_lease_break(char *buffer)
bool bool
smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
{ {
struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer; struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
struct list_head *tmp, *tmp1, *tmp2; struct list_head *tmp, *tmp1, *tmp2;
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
...@@ -630,7 +622,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) ...@@ -630,7 +622,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "Checking for oplock break\n"); cifs_dbg(FYI, "Checking for oplock break\n");
if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK) if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
return false; return false;
if (rsp->StructureSize != if (rsp->StructureSize !=
...@@ -721,7 +713,7 @@ smb2_cancelled_close_fid(struct work_struct *work) ...@@ -721,7 +713,7 @@ smb2_cancelled_close_fid(struct work_struct *work)
int int
smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
{ {
struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer); struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct close_cancelled_open *cancelled; struct close_cancelled_open *cancelled;
......
此差异已折叠。
此差异已折叠。
...@@ -122,25 +122,10 @@ struct smb2_sync_pdu { ...@@ -122,25 +122,10 @@ struct smb2_sync_pdu {
__le16 StructureSize2; /* size of wct area (varies, request specific) */ __le16 StructureSize2; /* size of wct area (varies, request specific) */
} __packed; } __packed;
struct smb2_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/* length is only two or three bytes - with */
/* one or two byte type preceding it that MBZ */
struct smb2_sync_hdr sync_hdr;
} __packed;
struct smb2_pdu {
struct smb2_hdr hdr;
__le16 StructureSize2; /* size of wct area (varies, request specific) */
} __packed;
#define SMB3_AES128CMM_NONCE 11 #define SMB3_AES128CMM_NONCE 11
#define SMB3_AES128GCM_NONCE 12 #define SMB3_AES128GCM_NONCE 12
struct smb2_transform_hdr { struct smb2_transform_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/* length is only two or three bytes - with
one or two byte type preceding it that MBZ */
__le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */
__u8 Signature[16]; __u8 Signature[16];
__u8 Nonce[16]; __u8 Nonce[16];
...@@ -171,7 +156,7 @@ struct smb2_transform_hdr { ...@@ -171,7 +156,7 @@ struct smb2_transform_hdr {
#define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9) #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9)
struct smb2_err_rsp { struct smb2_err_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; __le16 StructureSize;
__le16 Reserved; /* MBZ */ __le16 Reserved; /* MBZ */
__le32 ByteCount; /* even if zero, at least one byte follows */ __le32 ByteCount; /* even if zero, at least one byte follows */
...@@ -300,8 +285,16 @@ struct smb2_encryption_neg_context { ...@@ -300,8 +285,16 @@ struct smb2_encryption_neg_context {
__le16 Ciphers[1]; /* Ciphers[0] since only one used now */ __le16 Ciphers[1]; /* Ciphers[0] since only one used now */
} __packed; } __packed;
#define POSIX_CTXT_DATA_LEN 8
struct smb2_posix_neg_context {
__le16 ContextType; /* 0x100 */
__le16 DataLength;
__le32 Reserved;
__le64 Reserved1; /* In case needed for future (eg version or caps) */
} __packed;
struct smb2_negotiate_rsp { struct smb2_negotiate_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 65 */ __le16 StructureSize; /* Must be 65 */
__le16 SecurityMode; __le16 SecurityMode;
__le16 DialectRevision; __le16 DialectRevision;
...@@ -341,7 +334,7 @@ struct smb2_sess_setup_req { ...@@ -341,7 +334,7 @@ struct smb2_sess_setup_req {
#define SMB2_SESSION_FLAG_IS_NULL 0x0002 #define SMB2_SESSION_FLAG_IS_NULL 0x0002
#define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004 #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
struct smb2_sess_setup_rsp { struct smb2_sess_setup_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 9 */ __le16 StructureSize; /* Must be 9 */
__le16 SessionFlags; __le16 SessionFlags;
__le16 SecurityBufferOffset; __le16 SecurityBufferOffset;
...@@ -356,7 +349,7 @@ struct smb2_logoff_req { ...@@ -356,7 +349,7 @@ struct smb2_logoff_req {
} __packed; } __packed;
struct smb2_logoff_rsp { struct smb2_logoff_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 4 */ __le16 StructureSize; /* Must be 4 */
__le16 Reserved; __le16 Reserved;
} __packed; } __packed;
...@@ -452,7 +445,7 @@ struct smb2_tree_connect_req_extension { ...@@ -452,7 +445,7 @@ struct smb2_tree_connect_req_extension {
} __packed; } __packed;
struct smb2_tree_connect_rsp { struct smb2_tree_connect_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 16 */ __le16 StructureSize; /* Must be 16 */
__u8 ShareType; /* see below */ __u8 ShareType; /* see below */
__u8 Reserved; __u8 Reserved;
...@@ -503,7 +496,7 @@ struct smb2_tree_disconnect_req { ...@@ -503,7 +496,7 @@ struct smb2_tree_disconnect_req {
} __packed; } __packed;
struct smb2_tree_disconnect_rsp { struct smb2_tree_disconnect_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 4 */ __le16 StructureSize; /* Must be 4 */
__le16 Reserved; __le16 Reserved;
} __packed; } __packed;
...@@ -615,7 +608,9 @@ struct smb2_tree_disconnect_rsp { ...@@ -615,7 +608,9 @@ struct smb2_tree_disconnect_rsp {
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q" #define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C" #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
#define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74 #define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74
#define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9 #define SVHDX_OPEN_DEVICE_CONTEX 0x9CCBCF9E04C1E643980E158DA1F6EC83
#define SMB2_CREATE_TAG_POSIX 0x93AD25509CB411E7B42383DE968BCD7C
struct smb2_create_req { struct smb2_create_req {
struct smb2_sync_hdr sync_hdr; struct smb2_sync_hdr sync_hdr;
...@@ -638,7 +633,7 @@ struct smb2_create_req { ...@@ -638,7 +633,7 @@ struct smb2_create_req {
} __packed; } __packed;
struct smb2_create_rsp { struct smb2_create_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 89 */ __le16 StructureSize; /* Must be 89 */
__u8 OplockLevel; __u8 OplockLevel;
__u8 Reserved; __u8 Reserved;
...@@ -727,6 +722,13 @@ struct create_durable { ...@@ -727,6 +722,13 @@ struct create_durable {
} Data; } Data;
} __packed; } __packed;
struct create_posix {
struct create_context ccontext;
__u8 Name[16];
__le32 Mode;
__u32 Reserved;
} __packed;
/* See MS-SMB2 2.2.13.2.11 */ /* See MS-SMB2 2.2.13.2.11 */
/* Flags */ /* Flags */
#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002 #define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
...@@ -894,7 +896,7 @@ struct smb2_ioctl_req { ...@@ -894,7 +896,7 @@ struct smb2_ioctl_req {
} __packed; } __packed;
struct smb2_ioctl_rsp { struct smb2_ioctl_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 57 */ __le16 StructureSize; /* Must be 57 */
__u16 Reserved; __u16 Reserved;
__le32 CtlCode; __le32 CtlCode;
...@@ -921,7 +923,7 @@ struct smb2_close_req { ...@@ -921,7 +923,7 @@ struct smb2_close_req {
} __packed; } __packed;
struct smb2_close_rsp { struct smb2_close_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* 60 */ __le16 StructureSize; /* 60 */
__le16 Flags; __le16 Flags;
__le32 Reserved; __le32 Reserved;
...@@ -944,7 +946,7 @@ struct smb2_flush_req { ...@@ -944,7 +946,7 @@ struct smb2_flush_req {
} __packed; } __packed;
struct smb2_flush_rsp { struct smb2_flush_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; __le16 StructureSize;
__le16 Reserved; __le16 Reserved;
} __packed; } __packed;
...@@ -976,7 +978,7 @@ struct smb2_read_plain_req { ...@@ -976,7 +978,7 @@ struct smb2_read_plain_req {
} __packed; } __packed;
struct smb2_read_rsp { struct smb2_read_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 17 */ __le16 StructureSize; /* Must be 17 */
__u8 DataOffset; __u8 DataOffset;
__u8 Reserved; __u8 Reserved;
...@@ -1007,7 +1009,7 @@ struct smb2_write_req { ...@@ -1007,7 +1009,7 @@ struct smb2_write_req {
} __packed; } __packed;
struct smb2_write_rsp { struct smb2_write_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 17 */ __le16 StructureSize; /* Must be 17 */
__u8 DataOffset; __u8 DataOffset;
__u8 Reserved; __u8 Reserved;
...@@ -1041,7 +1043,7 @@ struct smb2_lock_req { ...@@ -1041,7 +1043,7 @@ struct smb2_lock_req {
} __packed; } __packed;
struct smb2_lock_rsp { struct smb2_lock_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 4 */ __le16 StructureSize; /* Must be 4 */
__le16 Reserved; __le16 Reserved;
} __packed; } __packed;
...@@ -1053,7 +1055,7 @@ struct smb2_echo_req { ...@@ -1053,7 +1055,7 @@ struct smb2_echo_req {
} __packed; } __packed;
struct smb2_echo_rsp { struct smb2_echo_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 4 */ __le16 StructureSize; /* Must be 4 */
__u16 Reserved; __u16 Reserved;
} __packed; } __packed;
...@@ -1079,7 +1081,7 @@ struct smb2_query_directory_req { ...@@ -1079,7 +1081,7 @@ struct smb2_query_directory_req {
} __packed; } __packed;
struct smb2_query_directory_rsp { struct smb2_query_directory_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 9 */ __le16 StructureSize; /* Must be 9 */
__le16 OutputBufferOffset; __le16 OutputBufferOffset;
__le32 OutputBufferLength; __le32 OutputBufferLength;
...@@ -1128,7 +1130,7 @@ struct smb2_query_info_req { ...@@ -1128,7 +1130,7 @@ struct smb2_query_info_req {
} __packed; } __packed;
struct smb2_query_info_rsp { struct smb2_query_info_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 9 */ __le16 StructureSize; /* Must be 9 */
__le16 OutputBufferOffset; __le16 OutputBufferOffset;
__le32 OutputBufferLength; __le32 OutputBufferLength;
...@@ -1150,12 +1152,11 @@ struct smb2_set_info_req { ...@@ -1150,12 +1152,11 @@ struct smb2_set_info_req {
} __packed; } __packed;
struct smb2_set_info_rsp { struct smb2_set_info_rsp {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 2 */ __le16 StructureSize; /* Must be 2 */
} __packed; } __packed;
/* oplock break without an rfc1002 header */ struct smb2_oplock_break {
struct smb2_oplock_break_req {
struct smb2_sync_hdr sync_hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 24 */ __le16 StructureSize; /* Must be 24 */
__u8 OplockLevel; __u8 OplockLevel;
...@@ -1165,21 +1166,10 @@ struct smb2_oplock_break_req { ...@@ -1165,21 +1166,10 @@ struct smb2_oplock_break_req {
__u64 VolatileFid; __u64 VolatileFid;
} __packed; } __packed;
/* oplock break with an rfc1002 header */
struct smb2_oplock_break_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 24 */
__u8 OplockLevel;
__u8 Reserved;
__le32 Reserved2;
__u64 PersistentFid;
__u64 VolatileFid;
} __packed;
#define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01) #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
struct smb2_lease_break { struct smb2_lease_break {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 44 */ __le16 StructureSize; /* Must be 44 */
__le16 Reserved; __le16 Reserved;
__le32 Flags; __le32 Flags;
......
...@@ -36,8 +36,9 @@ struct smb_rqst; ...@@ -36,8 +36,9 @@ struct smb_rqst;
extern int map_smb2_to_linux_error(char *buf, bool log_err); extern int map_smb2_to_linux_error(char *buf, bool log_err);
extern int smb2_check_message(char *buf, unsigned int length, extern int smb2_check_message(char *buf, unsigned int length,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
extern unsigned int smb2_calc_size(void *buf); extern unsigned int smb2_calc_size(void *buf, struct TCP_Server_Info *server);
extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr); extern char *smb2_get_data_area_len(int *off, int *len,
struct smb2_sync_hdr *shdr);
extern __le16 *cifs_convert_path_to_utf16(const char *from, extern __le16 *cifs_convert_path_to_utf16(const char *from,
struct cifs_sb_info *cifs_sb); struct cifs_sb_info *cifs_sb);
...@@ -65,6 +66,8 @@ extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, ...@@ -65,6 +66,8 @@ extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
extern int smb3_handle_read_data(struct TCP_Server_Info *server, extern int smb3_handle_read_data(struct TCP_Server_Info *server,
struct mid_q_entry *mid); struct mid_q_entry *mid);
extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_fid *pfid);
extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
struct smb2_file_all_info *src); struct smb2_file_all_info *src);
extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
...@@ -129,6 +132,8 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -129,6 +132,8 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
char **out_data, u32 *plen /* returned data len */); char **out_data, u32 *plen /* returned data len */);
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_flags(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, int flags);
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_query_eas(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
......
...@@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
unsigned int rc; unsigned int rc;
char server_response_sig[16]; char server_response_sig[16];
struct smb2_sync_hdr *shdr = struct smb2_sync_hdr *shdr =
(struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base; (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
if ((shdr->Command == SMB2_NEGOTIATE) || if ((shdr->Command == SMB2_NEGOTIATE) ||
(shdr->Command == SMB2_SESSION_SETUP) || (shdr->Command == SMB2_SESSION_SETUP) ||
...@@ -605,14 +605,12 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, ...@@ -605,14 +605,12 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
bool log_error) bool log_error)
{ {
unsigned int len = mid->resp_buf_size; unsigned int len = mid->resp_buf_size;
struct kvec iov[2]; struct kvec iov[1];
struct smb_rqst rqst = { .rq_iov = iov, struct smb_rqst rqst = { .rq_iov = iov,
.rq_nvec = 2 }; .rq_nvec = 1 };
iov[0].iov_base = (char *)mid->resp_buf; iov[0].iov_base = (char *)mid->resp_buf;
iov[0].iov_len = 4; iov[0].iov_len = len;
iov[1].iov_base = (char *)mid->resp_buf + 4;
iov[1].iov_len = len;
dump_smb(mid->resp_buf, min_t(u32, 80, len)); dump_smb(mid->resp_buf, min_t(u32, 80, len));
/* convert the length into a more usable form */ /* convert the length into a more usable form */
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018, Microsoft Corporation.
*
* Author(s): Steve French <stfrench@microsoft.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*/
#define CREATE_TRACE_POINTS
#include "trace.h"
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2018, Microsoft Corporation.
*
* Author(s): Steve French <stfrench@microsoft.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM cifs
#if !defined(_CIFS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _CIFS_TRACE_H
#include <linux/tracepoint.h>
/* For logging errors in read or write */
DECLARE_EVENT_CLASS(smb3_rw_err_class,
TP_PROTO(unsigned int xid,
__u64 fid,
__u32 tid,
__u64 sesid,
__u64 offset,
__u32 len,
int rc),
TP_ARGS(xid, fid, tid, sesid, offset, len, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(__u64, offset)
__field(__u32, len)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->fid = fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->offset = offset;
__entry->len = len;
__entry->rc = rc;
),
TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d",
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
__entry->offset, __entry->len, __entry->rc)
)
#define DEFINE_SMB3_RW_ERR_EVENT(name) \
DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 fid, \
__u32 tid, \
__u64 sesid, \
__u64 offset, \
__u32 len, \
int rc), \
TP_ARGS(xid, fid, tid, sesid, offset, len, rc))
DEFINE_SMB3_RW_ERR_EVENT(write_err);
DEFINE_SMB3_RW_ERR_EVENT(read_err);
/* For logging successful read or write */
DECLARE_EVENT_CLASS(smb3_rw_done_class,
TP_PROTO(unsigned int xid,
__u64 fid,
__u32 tid,
__u64 sesid,
__u64 offset,
__u32 len),
TP_ARGS(xid, fid, tid, sesid, offset, len),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(__u64, offset)
__field(__u32, len)
),
TP_fast_assign(
__entry->xid = xid;
__entry->fid = fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->offset = offset;
__entry->len = len;
),
TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x",
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
__entry->offset, __entry->len)
)
#define DEFINE_SMB3_RW_DONE_EVENT(name) \
DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 fid, \
__u32 tid, \
__u64 sesid, \
__u64 offset, \
__u32 len), \
TP_ARGS(xid, fid, tid, sesid, offset, len))
DEFINE_SMB3_RW_DONE_EVENT(write_done);
DEFINE_SMB3_RW_DONE_EVENT(read_done);
/*
* For handle based calls other than read and write, and get/set info
*/
DECLARE_EVENT_CLASS(smb3_fd_err_class,
TP_PROTO(unsigned int xid,
__u64 fid,
__u32 tid,
__u64 sesid,
int rc),
TP_ARGS(xid, fid, tid, sesid, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->fid = fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->rc = rc;
),
TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d",
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
__entry->rc)
)
#define DEFINE_SMB3_FD_ERR_EVENT(name) \
DEFINE_EVENT(smb3_fd_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 fid, \
__u32 tid, \
__u64 sesid, \
int rc), \
TP_ARGS(xid, fid, tid, sesid, rc))
DEFINE_SMB3_FD_ERR_EVENT(flush_err);
DEFINE_SMB3_FD_ERR_EVENT(lock_err);
DEFINE_SMB3_FD_ERR_EVENT(close_err);
/*
* For handle based query/set info calls
*/
DECLARE_EVENT_CLASS(smb3_inf_err_class,
TP_PROTO(unsigned int xid,
__u64 fid,
__u32 tid,
__u64 sesid,
__u8 infclass,
__u32 type,
int rc),
TP_ARGS(xid, fid, tid, sesid, infclass, type, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(__u8, infclass)
__field(__u32, type)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->fid = fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->infclass = infclass;
__entry->type = type;
__entry->rc = rc;
),
TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x rc=%d",
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
__entry->infclass, __entry->type, __entry->rc)
)
#define DEFINE_SMB3_INF_ERR_EVENT(name) \
DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 fid, \
__u32 tid, \
__u64 sesid, \
__u8 infclass, \
__u32 type, \
int rc), \
TP_ARGS(xid, fid, tid, sesid, infclass, type, rc))
DEFINE_SMB3_INF_ERR_EVENT(query_info_err);
DEFINE_SMB3_INF_ERR_EVENT(set_info_err);
DEFINE_SMB3_INF_ERR_EVENT(fsctl_err);
/*
* For logging SMB3 Status code and Command for responses which return errors
*/
DECLARE_EVENT_CLASS(smb3_cmd_err_class,
TP_PROTO(__u32 tid,
__u64 sesid,
__u16 cmd,
__u64 mid,
__u32 status,
int rc),
TP_ARGS(tid, sesid, cmd, mid, status, rc),
TP_STRUCT__entry(
__field(__u32, tid)
__field(__u64, sesid)
__field(__u16, cmd)
__field(__u64, mid)
__field(__u32, status)
__field(int, rc)
),
TP_fast_assign(
__entry->tid = tid;
__entry->sesid = sesid;
__entry->cmd = cmd;
__entry->mid = mid;
__entry->status = status;
__entry->rc = rc;
),
TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d",
__entry->sesid, __entry->tid, __entry->cmd, __entry->mid,
__entry->status, __entry->rc)
)
#define DEFINE_SMB3_CMD_ERR_EVENT(name) \
DEFINE_EVENT(smb3_cmd_err_class, smb3_##name, \
TP_PROTO(__u32 tid, \
__u64 sesid, \
__u16 cmd, \
__u64 mid, \
__u32 status, \
int rc), \
TP_ARGS(tid, sesid, cmd, mid, status, rc))
DEFINE_SMB3_CMD_ERR_EVENT(cmd_err);
DECLARE_EVENT_CLASS(smb3_cmd_done_class,
TP_PROTO(__u32 tid,
__u64 sesid,
__u16 cmd,
__u64 mid),
TP_ARGS(tid, sesid, cmd, mid),
TP_STRUCT__entry(
__field(__u32, tid)
__field(__u64, sesid)
__field(__u16, cmd)
__field(__u64, mid)
),
TP_fast_assign(
__entry->tid = tid;
__entry->sesid = sesid;
__entry->cmd = cmd;
__entry->mid = mid;
),
TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu",
__entry->sesid, __entry->tid,
__entry->cmd, __entry->mid)
)
#define DEFINE_SMB3_CMD_DONE_EVENT(name) \
DEFINE_EVENT(smb3_cmd_done_class, smb3_##name, \
TP_PROTO(__u32 tid, \
__u64 sesid, \
__u16 cmd, \
__u64 mid), \
TP_ARGS(tid, sesid, cmd, mid))
DEFINE_SMB3_CMD_DONE_EVENT(cmd_done);
DECLARE_EVENT_CLASS(smb3_exit_err_class,
TP_PROTO(unsigned int xid,
const char *func_name,
int rc),
TP_ARGS(xid, func_name, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(const char *, func_name)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->func_name = func_name;
__entry->rc = rc;
),
TP_printk("\t%s: xid=%u rc=%d",
__entry->func_name, __entry->xid, __entry->rc)
)
#define DEFINE_SMB3_EXIT_ERR_EVENT(name) \
DEFINE_EVENT(smb3_exit_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
const char *func_name, \
int rc), \
TP_ARGS(xid, func_name, rc))
DEFINE_SMB3_EXIT_ERR_EVENT(exit_err);
DECLARE_EVENT_CLASS(smb3_enter_exit_class,
TP_PROTO(unsigned int xid,
const char *func_name),
TP_ARGS(xid, func_name),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(const char *, func_name)
),
TP_fast_assign(
__entry->xid = xid;
__entry->func_name = func_name;
),
TP_printk("\t%s: xid=%u",
__entry->func_name, __entry->xid)
)
#define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \
DEFINE_EVENT(smb3_enter_exit_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
const char *func_name), \
TP_ARGS(xid, func_name))
DEFINE_SMB3_ENTER_EXIT_EVENT(enter);
DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done);
/*
* For smb2/smb3 open call
*/
DECLARE_EVENT_CLASS(smb3_open_err_class,
TP_PROTO(unsigned int xid,
__u32 tid,
__u64 sesid,
int create_options,
int desired_access,
int rc),
TP_ARGS(xid, tid, sesid, create_options, desired_access, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u32, tid)
__field(__u64, sesid)
__field(int, create_options)
__field(int, desired_access)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->create_options = create_options;
__entry->desired_access = desired_access;
__entry->rc = rc;
),
TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x rc=%d",
__entry->xid, __entry->sesid, __entry->tid,
__entry->create_options, __entry->desired_access, __entry->rc)
)
#define DEFINE_SMB3_OPEN_ERR_EVENT(name) \
DEFINE_EVENT(smb3_open_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u32 tid, \
__u64 sesid, \
int create_options, \
int desired_access, \
int rc), \
TP_ARGS(xid, tid, sesid, create_options, desired_access, rc))
DEFINE_SMB3_OPEN_ERR_EVENT(open_err);
DECLARE_EVENT_CLASS(smb3_open_done_class,
TP_PROTO(unsigned int xid,
__u64 fid,
__u32 tid,
__u64 sesid,
int create_options,
int desired_access),
TP_ARGS(xid, fid, tid, sesid, create_options, desired_access),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(int, create_options)
__field(int, desired_access)
),
TP_fast_assign(
__entry->xid = xid;
__entry->fid = fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->create_options = create_options;
__entry->desired_access = desired_access;
),
TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx cr_opts=0x%x des_access=0x%x",
__entry->xid, __entry->sesid, __entry->tid, __entry->fid,
__entry->create_options, __entry->desired_access)
)
#define DEFINE_SMB3_OPEN_DONE_EVENT(name) \
DEFINE_EVENT(smb3_open_done_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 fid, \
__u32 tid, \
__u64 sesid, \
int create_options, \
int desired_access), \
TP_ARGS(xid, fid, tid, sesid, create_options, desired_access))
DEFINE_SMB3_OPEN_DONE_EVENT(open_done);
#endif /* _CIFS_TRACE_H */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
...@@ -800,8 +800,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -800,8 +800,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
#ifdef CONFIG_CIFS_SMB311 #ifdef CONFIG_CIFS_SMB311
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
struct kvec iov = { struct kvec iov = {
.iov_base = buf + 4, .iov_base = buf,
.iov_len = get_rfc1002_length(buf) .iov_len = midQ->resp_buf_size
}; };
smb311_update_preauth_hash(ses, &iov, 1); smb311_update_preauth_hash(ses, &iov, 1);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册