Commit 6787dc24 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '4.16-rc-SMB3' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:
 "Some fixes for stable, fixed SMB3 DFS support, SMB3 Direct (RDMA) and
  various bug fixes and cleanup"

* tag '4.16-rc-SMB3' of git://git.samba.org/sfrench/cifs-2.6: (60 commits)
  fs/cifs/cifsacl.c Fixes typo in a comment
  update internal version number for cifs.ko
  cifs: add .splice_write
  CIFS: document tcon/ses/server refcount dance
  move a few externs to smbdirect.h to eliminate warning
  CIFS: zero sensitive data when freeing
  Cleanup some minor endian issues in smb3 rdma
  CIFS: dump IPC tcon in debug proc file
  CIFS: use tcon_ipc instead of use_ipc parameter of SMB2_ioctl
  CIFS: make IPC a regular tcon
  cifs: remove redundant duplicated assignment of pointer 'node'
  CIFS: SMBD: work around gcc -Wmaybe-uninitialized warning
  cifs: Fix autonegotiate security settings mismatch
  CIFS: SMBD: _smbd_get_connection() can be static
  CIFS: SMBD: Disable signing on SMB direct transport
  CIFS: SMBD: Add SMB Direct debug counters
  CIFS: SMBD: Upper layer performs SMB read via RDMA write through memory registration
  CIFS: SMBD: Read correct returned data length for RDMA write (SMB read) I/O
  CIFS: SMBD: Upper layer performs SMB write via RDMA read through memory registration
  CIFS: SMBD: Implement RDMA memory registration
  ...
parents a4b7fd7d 36c7ce4a
...@@ -196,6 +196,14 @@ config CIFS_SMB311 ...@@ -196,6 +196,14 @@ config CIFS_SMB311
This dialect includes improved security negotiation features. This dialect includes improved security negotiation features.
If unsure, say N If unsure, say N
config CIFS_SMB_DIRECT
bool "SMB Direct support (Experimental)"
depends on CIFS=m && INFINIBAND || CIFS=y && INFINIBAND=y
help
Enables SMB Direct experimental support for SMB 3.0, 3.02 and 3.1.1.
SMB Direct allows transferring SMB packets over RDMA. If unsure,
say N.
config CIFS_FSCACHE config CIFS_FSCACHE
bool "Provide CIFS client caching support" bool "Provide CIFS client caching support"
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
......
...@@ -19,3 +19,5 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o ...@@ -19,3 +19,5 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifsfs.h" #include "cifsfs.h"
#ifdef CONFIG_CIFS_SMB_DIRECT
#include "smbdirect.h"
#endif
void void
cifs_dump_mem(char *label, void *data, int length) cifs_dump_mem(char *label, void *data, int length)
...@@ -107,6 +110,32 @@ void cifs_dump_mids(struct TCP_Server_Info *server) ...@@ -107,6 +110,32 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
{
__u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
seq_printf(m, "%s Mounts: %d ", tcon->treeName, tcon->tc_count);
if (tcon->nativeFileSystem)
seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
tcon->tidStatus);
if (dev_type == FILE_DEVICE_DISK)
seq_puts(m, " type: DISK ");
else if (dev_type == FILE_DEVICE_CD_ROM)
seq_puts(m, " type: CDROM ");
else
seq_printf(m, " type: %d ", dev_type);
if (tcon->ses->server->ops->dump_share_caps)
tcon->ses->server->ops->dump_share_caps(m, tcon);
if (tcon->need_reconnect)
seq_puts(m, "\tDISCONNECTED ");
seq_putc(m, '\n');
}
static int cifs_debug_data_proc_show(struct seq_file *m, void *v) static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{ {
struct list_head *tmp1, *tmp2, *tmp3; struct list_head *tmp1, *tmp2, *tmp3;
...@@ -115,7 +144,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -115,7 +144,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
int i, j; int i, j;
__u32 dev_type;
seq_puts(m, seq_puts(m,
"Display Internal CIFS Data Structures for Debugging\n" "Display Internal CIFS Data Structures for Debugging\n"
...@@ -152,6 +180,72 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -152,6 +180,72 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
list_for_each(tmp1, &cifs_tcp_ses_list) { list_for_each(tmp1, &cifs_tcp_ses_list) {
server = list_entry(tmp1, struct TCP_Server_Info, server = list_entry(tmp1, struct TCP_Server_Info,
tcp_ses_list); tcp_ses_list);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (!server->rdma)
goto skip_rdma;
seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
"transport status: %x",
server->smbd_conn->protocol,
server->smbd_conn->transport_status);
seq_printf(m, "\nConn receive_credit_max: %x "
"send_credit_target: %x max_send_size: %x",
server->smbd_conn->receive_credit_max,
server->smbd_conn->send_credit_target,
server->smbd_conn->max_send_size);
seq_printf(m, "\nConn max_fragmented_recv_size: %x "
"max_fragmented_send_size: %x max_receive_size:%x",
server->smbd_conn->max_fragmented_recv_size,
server->smbd_conn->max_fragmented_send_size,
server->smbd_conn->max_receive_size);
seq_printf(m, "\nConn keep_alive_interval: %x "
"max_readwrite_size: %x rdma_readwrite_threshold: %x",
server->smbd_conn->keep_alive_interval,
server->smbd_conn->max_readwrite_size,
server->smbd_conn->rdma_readwrite_threshold);
seq_printf(m, "\nDebug count_get_receive_buffer: %x "
"count_put_receive_buffer: %x count_send_empty: %x",
server->smbd_conn->count_get_receive_buffer,
server->smbd_conn->count_put_receive_buffer,
server->smbd_conn->count_send_empty);
seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
"count_enqueue_reassembly_queue: %x "
"count_dequeue_reassembly_queue: %x "
"fragment_reassembly_remaining: %x "
"reassembly_data_length: %x "
"reassembly_queue_length: %x",
server->smbd_conn->count_reassembly_queue,
server->smbd_conn->count_enqueue_reassembly_queue,
server->smbd_conn->count_dequeue_reassembly_queue,
server->smbd_conn->fragment_reassembly_remaining,
server->smbd_conn->reassembly_data_length,
server->smbd_conn->reassembly_queue_length);
seq_printf(m, "\nCurrent Credits send_credits: %x "
"receive_credits: %x receive_credit_target: %x",
atomic_read(&server->smbd_conn->send_credits),
atomic_read(&server->smbd_conn->receive_credits),
server->smbd_conn->receive_credit_target);
seq_printf(m, "\nPending send_pending: %x send_payload_pending:"
" %x smbd_send_pending: %x smbd_recv_pending: %x",
atomic_read(&server->smbd_conn->send_pending),
atomic_read(&server->smbd_conn->send_payload_pending),
server->smbd_conn->smbd_send_pending,
server->smbd_conn->smbd_recv_pending);
seq_printf(m, "\nReceive buffers count_receive_queue: %x "
"count_empty_packet_queue: %x",
server->smbd_conn->count_receive_queue,
server->smbd_conn->count_empty_packet_queue);
seq_printf(m, "\nMR responder_resources: %x "
"max_frmr_depth: %x mr_type: %x",
server->smbd_conn->responder_resources,
server->smbd_conn->max_frmr_depth,
server->smbd_conn->mr_type);
seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
atomic_read(&server->smbd_conn->mr_ready_count),
atomic_read(&server->smbd_conn->mr_used_count));
skip_rdma:
#endif
seq_printf(m, "\nNumber of credits: %d", server->credits); seq_printf(m, "\nNumber of credits: %d", server->credits);
i++; i++;
list_for_each(tmp2, &server->smb_ses_list) { list_for_each(tmp2, &server->smb_ses_list) {
...@@ -176,6 +270,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -176,6 +270,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
ses->ses_count, ses->serverOS, ses->serverNOS, ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->status); ses->capabilities, ses->status);
} }
if (server->rdma)
seq_printf(m, "RDMA\n\t");
seq_printf(m, "TCP status: %d\n\tLocal Users To " seq_printf(m, "TCP status: %d\n\tLocal Users To "
"Server: %d SecMode: 0x%x Req On Wire: %d", "Server: %d SecMode: 0x%x Req On Wire: %d",
server->tcpStatus, server->srv_count, server->tcpStatus, server->srv_count,
...@@ -189,35 +285,19 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) ...@@ -189,35 +285,19 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_puts(m, "\n\tShares:"); seq_puts(m, "\n\tShares:");
j = 0; j = 0;
seq_printf(m, "\n\t%d) IPC: ", j);
if (ses->tcon_ipc)
cifs_debug_tcon(m, ses->tcon_ipc);
else
seq_puts(m, "none\n");
list_for_each(tmp3, &ses->tcon_list) { list_for_each(tmp3, &ses->tcon_list) {
tcon = list_entry(tmp3, struct cifs_tcon, tcon = list_entry(tmp3, struct cifs_tcon,
tcon_list); tcon_list);
++j; ++j;
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); seq_printf(m, "\n\t%d) ", j);
seq_printf(m, "\n\t%d) %s Mounts: %d ", j, cifs_debug_tcon(m, tcon);
tcon->treeName, tcon->tc_count);
if (tcon->nativeFileSystem) {
seq_printf(m, "Type: %s ",
tcon->nativeFileSystem);
}
seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
"\n\tPathComponentMax: %d Status: %d",
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
tcon->tidStatus);
if (dev_type == FILE_DEVICE_DISK)
seq_puts(m, " type: DISK ");
else if (dev_type == FILE_DEVICE_CD_ROM)
seq_puts(m, " type: CDROM ");
else
seq_printf(m, " type: %d ", dev_type);
if (server->ops->dump_share_caps)
server->ops->dump_share_caps(m, tcon);
if (tcon->need_reconnect)
seq_puts(m, "\tDISCONNECTED ");
seq_putc(m, '\n');
} }
seq_puts(m, "\n\tMIDs:\n"); seq_puts(m, "\n\tMIDs:\n");
...@@ -374,6 +454,45 @@ static const struct file_operations cifs_stats_proc_fops = { ...@@ -374,6 +454,45 @@ static const struct file_operations cifs_stats_proc_fops = {
}; };
#endif /* STATS */ #endif /* STATS */
#ifdef CONFIG_CIFS_SMB_DIRECT
#define PROC_FILE_DEFINE(name) \
static ssize_t name##_write(struct file *file, const char __user *buffer, \
size_t count, loff_t *ppos) \
{ \
int rc; \
rc = kstrtoint_from_user(buffer, count, 10, & name); \
if (rc) \
return rc; \
return count; \
} \
static int name##_proc_show(struct seq_file *m, void *v) \
{ \
seq_printf(m, "%d\n", name ); \
return 0; \
} \
static int name##_open(struct inode *inode, struct file *file) \
{ \
return single_open(file, name##_proc_show, NULL); \
} \
\
static const struct file_operations cifs_##name##_proc_fops = { \
.open = name##_open, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release, \
.write = name##_write, \
}
PROC_FILE_DEFINE(rdma_readwrite_threshold);
PROC_FILE_DEFINE(smbd_max_frmr_depth);
PROC_FILE_DEFINE(smbd_keep_alive_interval);
PROC_FILE_DEFINE(smbd_max_receive_size);
PROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
PROC_FILE_DEFINE(smbd_max_send_size);
PROC_FILE_DEFINE(smbd_send_credit_target);
PROC_FILE_DEFINE(smbd_receive_credit_max);
#endif
static struct proc_dir_entry *proc_fs_cifs; static struct proc_dir_entry *proc_fs_cifs;
static const struct file_operations cifsFYI_proc_fops; static const struct file_operations cifsFYI_proc_fops;
static const struct file_operations cifs_lookup_cache_proc_fops; static const struct file_operations cifs_lookup_cache_proc_fops;
...@@ -401,6 +520,24 @@ cifs_proc_init(void) ...@@ -401,6 +520,24 @@ cifs_proc_init(void)
&cifs_security_flags_proc_fops); &cifs_security_flags_proc_fops);
proc_create("LookupCacheEnabled", 0, proc_fs_cifs, proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
&cifs_lookup_cache_proc_fops); &cifs_lookup_cache_proc_fops);
#ifdef CONFIG_CIFS_SMB_DIRECT
proc_create("rdma_readwrite_threshold", 0, proc_fs_cifs,
&cifs_rdma_readwrite_threshold_proc_fops);
proc_create("smbd_max_frmr_depth", 0, proc_fs_cifs,
&cifs_smbd_max_frmr_depth_proc_fops);
proc_create("smbd_keep_alive_interval", 0, proc_fs_cifs,
&cifs_smbd_keep_alive_interval_proc_fops);
proc_create("smbd_max_receive_size", 0, proc_fs_cifs,
&cifs_smbd_max_receive_size_proc_fops);
proc_create("smbd_max_fragmented_recv_size", 0, proc_fs_cifs,
&cifs_smbd_max_fragmented_recv_size_proc_fops);
proc_create("smbd_max_send_size", 0, proc_fs_cifs,
&cifs_smbd_max_send_size_proc_fops);
proc_create("smbd_send_credit_target", 0, proc_fs_cifs,
&cifs_smbd_send_credit_target_proc_fops);
proc_create("smbd_receive_credit_max", 0, proc_fs_cifs,
&cifs_smbd_receive_credit_max_proc_fops);
#endif
} }
void void
...@@ -418,6 +555,16 @@ cifs_proc_clean(void) ...@@ -418,6 +555,16 @@ cifs_proc_clean(void)
remove_proc_entry("SecurityFlags", proc_fs_cifs); remove_proc_entry("SecurityFlags", proc_fs_cifs);
remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
#ifdef CONFIG_CIFS_SMB_DIRECT
remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
#endif
remove_proc_entry("fs/cifs", NULL); remove_proc_entry("fs/cifs", NULL);
} }
......
...@@ -1125,7 +1125,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ...@@ -1125,7 +1125,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
return rc; return rc;
} }
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
int int
cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
struct inode *inode, const char *path, struct inode *inode, const char *path,
......
...@@ -325,9 +325,8 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, ...@@ -325,9 +325,8 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
{ {
int i; int i;
int rc; int rc;
char password_with_pad[CIFS_ENCPWD_SIZE]; char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
if (password) if (password)
strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
......
...@@ -327,6 +327,8 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) ...@@ -327,6 +327,8 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
default: default:
seq_puts(s, "(unknown)"); seq_puts(s, "(unknown)");
} }
if (server->rdma)
seq_puts(s, ",rdma");
} }
static void static void
...@@ -1068,6 +1070,7 @@ const struct file_operations cifs_file_ops = { ...@@ -1068,6 +1070,7 @@ const struct file_operations cifs_file_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap, .mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.llseek = cifs_llseek, .llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
...@@ -1086,6 +1089,7 @@ const struct file_operations cifs_file_strict_ops = { ...@@ -1086,6 +1089,7 @@ const struct file_operations cifs_file_strict_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_strict_mmap, .mmap = cifs_file_strict_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.llseek = cifs_llseek, .llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
...@@ -1105,6 +1109,7 @@ const struct file_operations cifs_file_direct_ops = { ...@@ -1105,6 +1109,7 @@ const struct file_operations cifs_file_direct_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap, .mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range, .clone_file_range = cifs_clone_file_range,
...@@ -1122,6 +1127,7 @@ const struct file_operations cifs_file_nobrl_ops = { ...@@ -1122,6 +1127,7 @@ const struct file_operations cifs_file_nobrl_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap, .mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.llseek = cifs_llseek, .llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
...@@ -1139,6 +1145,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = { ...@@ -1139,6 +1145,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_strict_mmap, .mmap = cifs_file_strict_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.llseek = cifs_llseek, .llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
...@@ -1157,6 +1164,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { ...@@ -1157,6 +1164,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap, .mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.copy_file_range = cifs_copy_file_range, .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range, .clone_file_range = cifs_clone_file_range,
......
...@@ -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.10" #define CIFS_VERSION "2.11"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
#define RFC1001_NAME_LEN 15 #define RFC1001_NAME_LEN 15
#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1) #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
/* currently length of NIP6_FMT */ /* maximum length of ip addr as a string (including ipv6 and sctp) */
#define SERVER_NAME_LENGTH 40 #define SERVER_NAME_LENGTH 80
#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
/* echo interval in seconds */ /* echo interval in seconds */
...@@ -230,8 +230,14 @@ struct smb_version_operations { ...@@ -230,8 +230,14 @@ struct smb_version_operations {
__u64 (*get_next_mid)(struct TCP_Server_Info *); __u64 (*get_next_mid)(struct TCP_Server_Info *);
/* data offset from read response message */ /* data offset from read response message */
unsigned int (*read_data_offset)(char *); unsigned int (*read_data_offset)(char *);
/* data length from read response message */ /*
unsigned int (*read_data_length)(char *); * Data length from read response message
* When in_remaining is true, the returned data length is in
* message field DataRemaining for out-of-band data read (e.g through
* Memory Registration RDMA write in SMBD).
* Otherwise, the returned data length is in message field DataLength.
*/
unsigned int (*read_data_length)(char *, bool in_remaining);
/* map smb to linux error */ /* map smb to linux error */
int (*map_error)(char *, bool); int (*map_error)(char *, bool);
/* find mid corresponding to the response message */ /* find mid corresponding to the response message */
...@@ -532,6 +538,7 @@ struct smb_vol { ...@@ -532,6 +538,7 @@ struct smb_vol {
bool nopersistent:1; bool nopersistent:1;
bool resilient:1; /* noresilient not required since not fored for CA */ bool resilient:1; /* noresilient not required since not fored for CA */
bool domainauto:1; bool domainauto:1;
bool rdma:1;
unsigned int rsize; unsigned int rsize;
unsigned int wsize; unsigned int wsize;
bool sockopt_tcp_nodelay:1; bool sockopt_tcp_nodelay:1;
...@@ -648,6 +655,10 @@ struct TCP_Server_Info { ...@@ -648,6 +655,10 @@ struct TCP_Server_Info {
bool sec_kerberos; /* supports plain Kerberos */ bool sec_kerberos; /* supports plain Kerberos */
bool sec_mskerberos; /* supports legacy MS Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */
bool large_buf; /* is current buffer large? */ bool large_buf; /* is current buffer large? */
/* use SMBD connection instead of socket */
bool rdma;
/* point to the SMBD connection if RDMA is used instead of socket */
struct smbd_connection *smbd_conn;
struct delayed_work echo; /* echo ping workqueue job */ struct delayed_work echo; /* echo ping workqueue job */
char *smallbuf; /* pointer to current "small" buffer */ char *smallbuf; /* pointer to current "small" buffer */
char *bigbuf; /* pointer to current "big" buffer */ char *bigbuf; /* pointer to current "big" buffer */
...@@ -822,12 +833,12 @@ static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net) ...@@ -822,12 +833,12 @@ static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
struct cifs_ses { struct cifs_ses {
struct list_head smb_ses_list; struct list_head smb_ses_list;
struct list_head tcon_list; struct list_head tcon_list;
struct cifs_tcon *tcon_ipc;
struct mutex session_mutex; struct mutex session_mutex;
struct TCP_Server_Info *server; /* pointer to server info */ struct TCP_Server_Info *server; /* pointer to server info */
int ses_count; /* reference counter */ int ses_count; /* reference counter */
enum statusEnum status; enum statusEnum status;
unsigned overrideSecFlg; /* if non-zero override global sec flags */ unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u32 ipc_tid; /* special tid for connection to IPC share */
char *serverOS; /* name of operating system underlying server */ char *serverOS; /* name of operating system underlying server */
char *serverNOS; /* name of network operating system of server */ char *serverNOS; /* name of network operating system of server */
char *serverDomain; /* security realm of server */ char *serverDomain; /* security realm of server */
...@@ -835,8 +846,7 @@ struct cifs_ses { ...@@ -835,8 +846,7 @@ struct cifs_ses {
kuid_t linux_uid; /* overriding owner of files on the mount */ kuid_t linux_uid; /* overriding owner of files on the mount */
kuid_t cred_uid; /* owner of credentials */ kuid_t cred_uid; /* owner of credentials */
unsigned int capabilities; unsigned int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for char serverName[SERVER_NAME_LEN_WITH_NULL];
TCP names - will ipv6 and sctp addresses fit? */
char *user_name; /* must not be null except during init of sess char *user_name; /* must not be null except during init of sess
and after mount option parsing we fill it */ and after mount option parsing we fill it */
char *domainName; char *domainName;
...@@ -931,7 +941,9 @@ struct cifs_tcon { ...@@ -931,7 +941,9 @@ struct cifs_tcon {
FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo; FILE_SYSTEM_UNIX_INFO fsUnixInfo;
bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ bool ipc:1; /* set if connection to IPC$ share (always also pipe) */
bool pipe:1; /* set if connection to pipe share */
bool print:1; /* set if connection to printer share */
bool retry:1; bool retry:1;
bool nocase:1; bool nocase:1;
bool seal:1; /* transport encryption for this mounted share */ bool seal:1; /* transport encryption for this mounted share */
...@@ -944,7 +956,6 @@ struct cifs_tcon { ...@@ -944,7 +956,6 @@ struct cifs_tcon {
bool need_reopen_files:1; /* need to reopen tcon file handles */ bool need_reopen_files:1; /* need to reopen tcon file handles */
bool use_resilient:1; /* use resilient instead of durable handles */ bool use_resilient:1; /* use resilient instead of durable handles */
bool use_persistent:1; /* use persistent instead of durable handles */ bool use_persistent:1; /* use persistent instead of durable handles */
bool print:1; /* set if connection to printer share */
__le32 capabilities; __le32 capabilities;
__u32 share_flags; __u32 share_flags;
__u32 maximal_access; __u32 maximal_access;
...@@ -1147,6 +1158,9 @@ struct cifs_readdata { ...@@ -1147,6 +1158,9 @@ struct cifs_readdata {
struct cifs_readdata *rdata, struct cifs_readdata *rdata,
struct iov_iter *iter); struct iov_iter *iter);
struct kvec iov[2]; struct kvec iov[2];
#ifdef CONFIG_CIFS_SMB_DIRECT
struct smbd_mr *mr;
#endif
unsigned int pagesz; unsigned int pagesz;
unsigned int tailsz; unsigned int tailsz;
unsigned int credits; unsigned int credits;
...@@ -1169,6 +1183,9 @@ struct cifs_writedata { ...@@ -1169,6 +1183,9 @@ struct cifs_writedata {
pid_t pid; pid_t pid;
unsigned int bytes; unsigned int bytes;
int result; int result;
#ifdef CONFIG_CIFS_SMB_DIRECT
struct smbd_mr *mr;
#endif
unsigned int pagesz; unsigned int pagesz;
unsigned int tailsz; unsigned int tailsz;
unsigned int credits; unsigned int credits;
......
...@@ -106,6 +106,10 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, ...@@ -106,6 +106,10 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
struct kvec *, int /* nvec to send */, struct kvec *, int /* nvec to send */,
int * /* type of buf returned */, const int flags, int * /* type of buf returned */, const int flags,
struct kvec * /* resp vec */); struct kvec * /* resp vec */);
extern int smb2_send_recv(const unsigned int xid, struct cifs_ses *pses,
struct kvec *pkvec, int nvec_to_send,
int *pbuftype, const int flags,
struct kvec *presp);
extern int SendReceiveBlockingLock(const unsigned int xid, extern int SendReceiveBlockingLock(const unsigned int xid,
struct cifs_tcon *ptcon, struct cifs_tcon *ptcon,
struct smb_hdr *in_buf , struct smb_hdr *in_buf ,
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "fscache.h" #include "fscache.h"
#include "smbdirect.h"
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
static struct { static struct {
...@@ -1454,6 +1455,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1454,6 +1455,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
struct cifs_readdata *rdata = mid->callback_data; struct cifs_readdata *rdata = mid->callback_data;
char *buf = server->smallbuf; char *buf = server->smallbuf;
unsigned int buflen = get_rfc1002_length(buf) + 4; unsigned int buflen = get_rfc1002_length(buf) + 4;
bool use_rdma_mr = false;
cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n", cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
__func__, mid->mid, rdata->offset, rdata->bytes); __func__, mid->mid, rdata->offset, rdata->bytes);
...@@ -1542,8 +1544,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1542,8 +1544,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
rdata->iov[0].iov_base, server->total_read); rdata->iov[0].iov_base, server->total_read);
/* how much data is in the response? */ /* how much data is in the response? */
data_len = server->ops->read_data_length(buf); #ifdef CONFIG_CIFS_SMB_DIRECT
if (data_offset + data_len > buflen) { use_rdma_mr = rdata->mr;
#endif
data_len = server->ops->read_data_length(buf, use_rdma_mr);
if (!use_rdma_mr && (data_offset + data_len > buflen)) {
/* data_len is corrupt -- discard frame */ /* data_len is corrupt -- discard frame */
rdata->result = -EIO; rdata->result = -EIO;
return cifs_readv_discard(server, mid); return cifs_readv_discard(server, mid);
...@@ -1923,6 +1928,12 @@ cifs_writedata_release(struct kref *refcount) ...@@ -1923,6 +1928,12 @@ cifs_writedata_release(struct kref *refcount)
{ {
struct cifs_writedata *wdata = container_of(refcount, struct cifs_writedata *wdata = container_of(refcount,
struct cifs_writedata, refcount); struct cifs_writedata, refcount);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (wdata->mr) {
smbd_deregister_mr(wdata->mr);
wdata->mr = NULL;
}
#endif
if (wdata->cfile) if (wdata->cfile)
cifsFileInfo_put(wdata->cfile); cifsFileInfo_put(wdata->cfile);
...@@ -4822,10 +4833,11 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, ...@@ -4822,10 +4833,11 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
*target_nodes = NULL; *target_nodes = NULL;
cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name); cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
if (ses == NULL) if (ses == NULL || ses->tcon_ipc == NULL)
return -ENODEV; return -ENODEV;
getDFSRetry: getDFSRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB, rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
if (rc) if (rc)
return rc; return rc;
...@@ -4833,7 +4845,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, ...@@ -4833,7 +4845,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
/* server pointer checked in called function, /* server pointer checked in called function,
but should never be null here anyway */ but should never be null here anyway */
pSMB->hdr.Mid = get_next_mid(ses->server); pSMB->hdr.Mid = get_next_mid(ses->server);
pSMB->hdr.Tid = ses->ipc_tid; pSMB->hdr.Tid = ses->tcon_ipc->tid;
pSMB->hdr.Uid = ses->Suid; pSMB->hdr.Uid = ses->Suid;
if (ses->capabilities & CAP_STATUS32) if (ses->capabilities & CAP_STATUS32)
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
......
This diff is collapsed.
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifs_fs_sb.h" #include "cifs_fs_sb.h"
#include "fscache.h" #include "fscache.h"
#include "smbdirect.h"
static inline int cifs_convert_flags(unsigned int flags) static inline int cifs_convert_flags(unsigned int flags)
{ {
...@@ -2902,7 +2902,12 @@ cifs_readdata_release(struct kref *refcount) ...@@ -2902,7 +2902,12 @@ cifs_readdata_release(struct kref *refcount)
{ {
struct cifs_readdata *rdata = container_of(refcount, struct cifs_readdata *rdata = container_of(refcount,
struct cifs_readdata, refcount); struct cifs_readdata, refcount);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (rdata->mr) {
smbd_deregister_mr(rdata->mr);
rdata->mr = NULL;
}
#endif
if (rdata->cfile) if (rdata->cfile)
cifsFileInfo_put(rdata->cfile); cifsFileInfo_put(rdata->cfile);
...@@ -3031,6 +3036,10 @@ uncached_fill_pages(struct TCP_Server_Info *server, ...@@ -3031,6 +3036,10 @@ uncached_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, 0, n, iter);
#ifdef CONFIG_CIFS_SMB_DIRECT
else if (rdata->mr)
result = n;
#endif
else else
result = cifs_read_page_from_socket(server, page, n); result = cifs_read_page_from_socket(server, page, n);
if (result < 0) if (result < 0)
...@@ -3471,20 +3480,18 @@ static const struct vm_operations_struct cifs_file_vm_ops = { ...@@ -3471,20 +3480,18 @@ static const struct vm_operations_struct cifs_file_vm_ops = {
int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
{ {
int rc, xid; int xid, rc = 0;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
xid = get_xid(); xid = get_xid();
if (!CIFS_CACHE_READ(CIFS_I(inode))) { if (!CIFS_CACHE_READ(CIFS_I(inode)))
rc = cifs_zap_mapping(inode); rc = cifs_zap_mapping(inode);
if (rc) if (!rc)
return rc; rc = generic_file_mmap(file, vma);
} if (!rc)
rc = generic_file_mmap(file, vma);
if (rc == 0)
vma->vm_ops = &cifs_file_vm_ops; vma->vm_ops = &cifs_file_vm_ops;
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -3494,16 +3501,16 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -3494,16 +3501,16 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
int rc, xid; int rc, xid;
xid = get_xid(); xid = get_xid();
rc = cifs_revalidate_file(file); rc = cifs_revalidate_file(file);
if (rc) { if (rc)
cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n", cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
rc); rc);
free_xid(xid); if (!rc)
return rc; rc = generic_file_mmap(file, vma);
} if (!rc)
rc = generic_file_mmap(file, vma);
if (rc == 0)
vma->vm_ops = &cifs_file_vm_ops; vma->vm_ops = &cifs_file_vm_ops;
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -3600,6 +3607,10 @@ readpages_fill_pages(struct TCP_Server_Info *server, ...@@ -3600,6 +3607,10 @@ 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, 0, n, iter);
#ifdef CONFIG_CIFS_SMB_DIRECT
else if (rdata->mr)
result = n;
#endif
else else
result = cifs_read_page_from_socket(server, page, n); result = cifs_read_page_from_socket(server, page, n);
if (result < 0) if (result < 0)
......
...@@ -1049,7 +1049,7 @@ struct inode *cifs_root_iget(struct super_block *sb) ...@@ -1049,7 +1049,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
tcon->resource_id = CIFS_I(inode)->uniqueid; tcon->resource_id = CIFS_I(inode)->uniqueid;
#endif #endif
if (rc && tcon->ipc) { if (rc && tcon->pipe) {
cifs_dbg(FYI, "ipc connection - fake read inode\n"); cifs_dbg(FYI, "ipc connection - fake read inode\n");
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
inode->i_mode |= S_IFDIR; inode->i_mode |= S_IFDIR;
......
...@@ -98,14 +98,11 @@ sesInfoFree(struct cifs_ses *buf_to_free) ...@@ -98,14 +98,11 @@ sesInfoFree(struct cifs_ses *buf_to_free)
kfree(buf_to_free->serverOS); kfree(buf_to_free->serverOS);
kfree(buf_to_free->serverDomain); kfree(buf_to_free->serverDomain);
kfree(buf_to_free->serverNOS); kfree(buf_to_free->serverNOS);
if (buf_to_free->password) { kzfree(buf_to_free->password);
memset(buf_to_free->password, 0, strlen(buf_to_free->password));
kfree(buf_to_free->password);
}
kfree(buf_to_free->user_name); kfree(buf_to_free->user_name);
kfree(buf_to_free->domainName); kfree(buf_to_free->domainName);
kfree(buf_to_free->auth_key.response); kzfree(buf_to_free->auth_key.response);
kfree(buf_to_free); kzfree(buf_to_free);
} }
struct cifs_tcon * struct cifs_tcon *
...@@ -136,10 +133,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) ...@@ -136,10 +133,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free)
} }
atomic_dec(&tconInfoAllocCount); atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem); kfree(buf_to_free->nativeFileSystem);
if (buf_to_free->password) { kzfree(buf_to_free->password);
memset(buf_to_free->password, 0, strlen(buf_to_free->password));
kfree(buf_to_free->password);
}
kfree(buf_to_free); kfree(buf_to_free);
} }
......
...@@ -87,9 +87,11 @@ cifs_read_data_offset(char *buf) ...@@ -87,9 +87,11 @@ cifs_read_data_offset(char *buf)
} }
static unsigned int static unsigned int
cifs_read_data_length(char *buf) cifs_read_data_length(char *buf, bool in_remaining)
{ {
READ_RSP *rsp = (READ_RSP *)buf; READ_RSP *rsp = (READ_RSP *)buf;
/* It's a bug reading remaining data for SMB1 packets */
WARN_ON(in_remaining);
return (le16_to_cpu(rsp->DataLengthHigh) << 16) + return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
le16_to_cpu(rsp->DataLength); le16_to_cpu(rsp->DataLength);
} }
......
...@@ -74,7 +74,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, ...@@ -74,7 +74,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
nr_ioctl_req.Reserved = 0; nr_ioctl_req.Reserved = 0;
rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid, rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
true /* is_fsctl */, false /* use_ipc */, true /* is_fsctl */,
(char *)&nr_ioctl_req, sizeof(nr_ioctl_req), (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
NULL, NULL /* no return info */); NULL, NULL /* no return info */);
if (rc == -EOPNOTSUPP) { if (rc == -EOPNOTSUPP) {
......
...@@ -578,7 +578,7 @@ smb2_is_valid_lease_break(char *buffer) ...@@ -578,7 +578,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 = (struct smb2_oplock_break *)buffer; struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)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;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "smb2status.h" #include "smb2status.h"
#include "smb2glob.h" #include "smb2glob.h"
#include "cifs_ioctl.h" #include "cifs_ioctl.h"
#include "smbdirect.h"
static int static int
change_conf(struct TCP_Server_Info *server) change_conf(struct TCP_Server_Info *server)
...@@ -250,7 +251,11 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) ...@@ -250,7 +251,11 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
/* start with specified wsize, or default */ /* start with specified wsize, or default */
wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
wsize = min_t(unsigned int, wsize, server->max_write); wsize = min_t(unsigned int, wsize, server->max_write);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (server->rdma)
wsize = min_t(unsigned int,
wsize, server->smbd_conn->max_readwrite_size);
#endif
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
...@@ -266,6 +271,11 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) ...@@ -266,6 +271,11 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
/* start with specified rsize, or default */ /* start with specified rsize, or default */
rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
rsize = min_t(unsigned int, rsize, server->max_read); rsize = min_t(unsigned int, rsize, server->max_read);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (server->rdma)
rsize = min_t(unsigned int,
rsize, server->smbd_conn->max_readwrite_size);
#endif
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
...@@ -283,7 +293,6 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -283,7 +293,6 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */, FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
false /* use_ipc */,
NULL /* no data input */, 0 /* no data input */, NULL /* no data input */, 0 /* no data input */,
(char **)&out_buf, &ret_data_len); (char **)&out_buf, &ret_data_len);
if (rc != 0) if (rc != 0)
...@@ -782,7 +791,6 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -782,7 +791,6 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */, FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
false /* use_ipc */,
NULL, 0 /* no input */, NULL, 0 /* no input */,
(char **)&res_key, &ret_data_len); (char **)&res_key, &ret_data_len);
...@@ -848,8 +856,7 @@ smb2_copychunk_range(const unsigned int xid, ...@@ -848,8 +856,7 @@ smb2_copychunk_range(const unsigned int xid,
/* Request server copy to target from src identified by key */ /* Request server copy to target from src identified by key */
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE, trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
true /* is_fsctl */, false /* use_ipc */, true /* is_fsctl */, (char *)pcchunk,
(char *)pcchunk,
sizeof(struct copychunk_ioctl), (char **)&retbuf, sizeof(struct copychunk_ioctl), (char **)&retbuf,
&ret_data_len); &ret_data_len);
if (rc == 0) { if (rc == 0) {
...@@ -947,9 +954,13 @@ smb2_read_data_offset(char *buf) ...@@ -947,9 +954,13 @@ smb2_read_data_offset(char *buf)
} }
static unsigned int static unsigned int
smb2_read_data_length(char *buf) smb2_read_data_length(char *buf, bool in_remaining)
{ {
struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
if (in_remaining)
return le32_to_cpu(rsp->DataRemaining);
return le32_to_cpu(rsp->DataLength); return le32_to_cpu(rsp->DataLength);
} }
...@@ -1006,7 +1017,7 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1006,7 +1017,7 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_SPARSE, cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
true /* is_fctl */, false /* use_ipc */, true /* is_fctl */,
&setsparse, 1, NULL, NULL); &setsparse, 1, NULL, NULL);
if (rc) { if (rc) {
tcon->broken_sparse_sup = true; tcon->broken_sparse_sup = true;
...@@ -1077,7 +1088,7 @@ smb2_duplicate_extents(const unsigned int xid, ...@@ -1077,7 +1088,7 @@ smb2_duplicate_extents(const unsigned int xid,
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
trgtfile->fid.volatile_fid, trgtfile->fid.volatile_fid,
FSCTL_DUPLICATE_EXTENTS_TO_FILE, FSCTL_DUPLICATE_EXTENTS_TO_FILE,
true /* is_fsctl */, false /* use_ipc */, true /* is_fsctl */,
(char *)&dup_ext_buf, (char *)&dup_ext_buf,
sizeof(struct duplicate_extents_to_file), sizeof(struct duplicate_extents_to_file),
NULL, NULL,
...@@ -1112,7 +1123,7 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1112,7 +1123,7 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->fid.volatile_fid,
FSCTL_SET_INTEGRITY_INFORMATION, FSCTL_SET_INTEGRITY_INFORMATION,
true /* is_fsctl */, false /* use_ipc */, true /* is_fsctl */,
(char *)&integr_info, (char *)&integr_info,
sizeof(struct fsctl_set_integrity_information_req), sizeof(struct fsctl_set_integrity_information_req),
NULL, NULL,
...@@ -1132,7 +1143,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1132,7 +1143,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->fid.volatile_fid,
FSCTL_SRV_ENUMERATE_SNAPSHOTS, FSCTL_SRV_ENUMERATE_SNAPSHOTS,
true /* is_fsctl */, false /* use_ipc */, true /* is_fsctl */,
NULL, 0 /* no input data */, NULL, 0 /* no input data */,
(char **)&retbuf, (char **)&retbuf,
&ret_data_len); &ret_data_len);
...@@ -1351,16 +1362,20 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, ...@@ -1351,16 +1362,20 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name); cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
/* /*
* Use any tcon from the current session. Here, the first one. * Try to use the IPC tcon, otherwise just use any
*/ */
spin_lock(&cifs_tcp_ses_lock); tcon = ses->tcon_ipc;
tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, if (tcon == NULL) {
tcon_list); spin_lock(&cifs_tcp_ses_lock);
if (tcon) tcon = list_first_entry_or_null(&ses->tcon_list,
tcon->tc_count++; struct cifs_tcon,
spin_unlock(&cifs_tcp_ses_lock); tcon_list);
if (tcon)
tcon->tc_count++;
spin_unlock(&cifs_tcp_ses_lock);
}
if (!tcon) { if (tcon == NULL) {
cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n", cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
ses); ses);
rc = -ENOTCONN; rc = -ENOTCONN;
...@@ -1389,20 +1404,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, ...@@ -1389,20 +1404,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len); memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
do { do {
/* try first with IPC */
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_DFS_GET_REFERRALS, FSCTL_DFS_GET_REFERRALS,
true /* is_fsctl */, true /* use_ipc */, true /* is_fsctl */,
(char *)dfs_req, dfs_req_size, (char *)dfs_req, dfs_req_size,
(char **)&dfs_rsp, &dfs_rsp_size); (char **)&dfs_rsp, &dfs_rsp_size);
if (rc == -ENOTCONN) {
/* try with normal tcon */
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_DFS_GET_REFERRALS,
true /* is_fsctl */, false /*use_ipc*/,
(char *)dfs_req, dfs_req_size,
(char **)&dfs_rsp, &dfs_rsp_size);
}
} while (rc == -EAGAIN); } while (rc == -EAGAIN);
if (rc) { if (rc) {
...@@ -1421,7 +1427,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, ...@@ -1421,7 +1427,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
} }
out: out:
if (tcon) { if (tcon && !tcon->ipc) {
/* ipc tcons are not refcounted */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
tcon->tc_count--; tcon->tc_count--;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
...@@ -1713,8 +1720,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, ...@@ -1713,8 +1720,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
true /* is_fctl */, false /* use_ipc */, true /* is_fctl */, (char *)&fsctl_buf,
(char *)&fsctl_buf,
sizeof(struct file_zero_data_information), NULL, NULL); sizeof(struct file_zero_data_information), NULL, NULL);
free_xid(xid); free_xid(xid);
return rc; return rc;
...@@ -1748,8 +1754,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, ...@@ -1748,8 +1754,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
true /* is_fctl */, false /* use_ipc */, true /* is_fctl */, (char *)&fsctl_buf,
(char *)&fsctl_buf,
sizeof(struct file_zero_data_information), NULL, NULL); sizeof(struct file_zero_data_information), NULL, NULL);
free_xid(xid); free_xid(xid);
return rc; return rc;
...@@ -2411,6 +2416,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, ...@@ -2411,6 +2416,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
struct iov_iter iter; struct iov_iter iter;
struct kvec iov; struct kvec iov;
int length; int length;
bool use_rdma_mr = false;
if (shdr->Command != SMB2_READ) { if (shdr->Command != SMB2_READ) {
cifs_dbg(VFS, "only big read responses are supported\n"); cifs_dbg(VFS, "only big read responses are supported\n");
...@@ -2437,7 +2443,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, ...@@ -2437,7 +2443,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
} }
data_offset = server->ops->read_data_offset(buf) + 4; data_offset = server->ops->read_data_offset(buf) + 4;
data_len = server->ops->read_data_length(buf); #ifdef CONFIG_CIFS_SMB_DIRECT
use_rdma_mr = rdata->mr;
#endif
data_len = server->ops->read_data_length(buf, use_rdma_mr);
if (data_offset < server->vals->read_rsp_size) { if (data_offset < server->vals->read_rsp_size) {
/* /*
......
This diff is collapsed.
...@@ -195,7 +195,7 @@ struct smb2_symlink_err_rsp { ...@@ -195,7 +195,7 @@ struct smb2_symlink_err_rsp {
#define SMB2_CLIENT_GUID_SIZE 16 #define SMB2_CLIENT_GUID_SIZE 16
struct smb2_negotiate_req { struct smb2_negotiate_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 36 */ __le16 StructureSize; /* Must be 36 */
__le16 DialectCount; __le16 DialectCount;
__le16 SecurityMode; __le16 SecurityMode;
...@@ -282,7 +282,7 @@ struct smb2_negotiate_rsp { ...@@ -282,7 +282,7 @@ struct smb2_negotiate_rsp {
#define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04 #define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04
struct smb2_sess_setup_req { struct smb2_sess_setup_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 25 */ __le16 StructureSize; /* Must be 25 */
__u8 Flags; __u8 Flags;
__u8 SecurityMode; __u8 SecurityMode;
...@@ -308,7 +308,7 @@ struct smb2_sess_setup_rsp { ...@@ -308,7 +308,7 @@ struct smb2_sess_setup_rsp {
} __packed; } __packed;
struct smb2_logoff_req { struct smb2_logoff_req {
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;
...@@ -323,7 +323,7 @@ struct smb2_logoff_rsp { ...@@ -323,7 +323,7 @@ struct smb2_logoff_rsp {
#define SMB2_SHAREFLAG_CLUSTER_RECONNECT 0x0001 #define SMB2_SHAREFLAG_CLUSTER_RECONNECT 0x0001
struct smb2_tree_connect_req { struct smb2_tree_connect_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 9 */ __le16 StructureSize; /* Must be 9 */
__le16 Reserved; /* Flags in SMB3.1.1 */ __le16 Reserved; /* Flags in SMB3.1.1 */
__le16 PathOffset; __le16 PathOffset;
...@@ -375,7 +375,7 @@ struct smb2_tree_connect_rsp { ...@@ -375,7 +375,7 @@ struct smb2_tree_connect_rsp {
#define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */ #define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */
struct smb2_tree_disconnect_req { struct smb2_tree_disconnect_req {
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;
...@@ -496,7 +496,7 @@ struct smb2_tree_disconnect_rsp { ...@@ -496,7 +496,7 @@ struct smb2_tree_disconnect_rsp {
#define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9 #define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9
struct smb2_create_req { struct smb2_create_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 57 */ __le16 StructureSize; /* Must be 57 */
__u8 SecurityFlags; __u8 SecurityFlags;
__u8 RequestedOplockLevel; __u8 RequestedOplockLevel;
...@@ -753,7 +753,7 @@ struct duplicate_extents_to_file { ...@@ -753,7 +753,7 @@ struct duplicate_extents_to_file {
} __packed; } __packed;
struct smb2_ioctl_req { struct smb2_ioctl_req {
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;
...@@ -789,7 +789,7 @@ struct smb2_ioctl_rsp { ...@@ -789,7 +789,7 @@ struct smb2_ioctl_rsp {
/* Currently defined values for close flags */ /* Currently defined values for close flags */
#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001) #define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
struct smb2_close_req { struct smb2_close_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 24 */ __le16 StructureSize; /* Must be 24 */
__le16 Flags; __le16 Flags;
__le32 Reserved; __le32 Reserved;
...@@ -812,7 +812,7 @@ struct smb2_close_rsp { ...@@ -812,7 +812,7 @@ struct smb2_close_rsp {
} __packed; } __packed;
struct smb2_flush_req { struct smb2_flush_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 24 */ __le16 StructureSize; /* Must be 24 */
__le16 Reserved1; __le16 Reserved1;
__le32 Reserved2; __le32 Reserved2;
...@@ -830,9 +830,9 @@ struct smb2_flush_rsp { ...@@ -830,9 +830,9 @@ struct smb2_flush_rsp {
#define SMB2_READFLAG_READ_UNBUFFERED 0x01 #define SMB2_READFLAG_READ_UNBUFFERED 0x01
/* Channel field for read and write: exactly one of following flags can be set*/ /* Channel field for read and write: exactly one of following flags can be set*/
#define SMB2_CHANNEL_NONE 0x00000000 #define SMB2_CHANNEL_NONE cpu_to_le32(0x00000000)
#define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ #define SMB2_CHANNEL_RDMA_V1 cpu_to_le32(0x00000001) /* SMB3 or later */
#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002 /* SMB3.02 or later */ #define SMB2_CHANNEL_RDMA_V1_INVALIDATE cpu_to_le32(0x00000002) /* >= SMB3.02 */
/* SMB2 read request without RFC1001 length at the beginning */ /* SMB2 read request without RFC1001 length at the beginning */
struct smb2_read_plain_req { struct smb2_read_plain_req {
...@@ -847,8 +847,8 @@ struct smb2_read_plain_req { ...@@ -847,8 +847,8 @@ struct smb2_read_plain_req {
__le32 MinimumCount; __le32 MinimumCount;
__le32 Channel; /* MBZ except for SMB3 or later */ __le32 Channel; /* MBZ except for SMB3 or later */
__le32 RemainingBytes; __le32 RemainingBytes;
__le16 ReadChannelInfoOffset; /* Reserved MBZ */ __le16 ReadChannelInfoOffset;
__le16 ReadChannelInfoLength; /* Reserved MBZ */ __le16 ReadChannelInfoLength;
__u8 Buffer[1]; __u8 Buffer[1];
} __packed; } __packed;
...@@ -868,7 +868,7 @@ struct smb2_read_rsp { ...@@ -868,7 +868,7 @@ struct smb2_read_rsp {
#define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */ #define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */
struct smb2_write_req { struct smb2_write_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 49 */ __le16 StructureSize; /* Must be 49 */
__le16 DataOffset; /* offset from start of SMB2 header to write data */ __le16 DataOffset; /* offset from start of SMB2 header to write data */
__le32 Length; __le32 Length;
...@@ -877,8 +877,8 @@ struct smb2_write_req { ...@@ -877,8 +877,8 @@ struct smb2_write_req {
__u64 VolatileFileId; /* opaque endianness */ __u64 VolatileFileId; /* opaque endianness */
__le32 Channel; /* Reserved MBZ */ __le32 Channel; /* Reserved MBZ */
__le32 RemainingBytes; __le32 RemainingBytes;
__le16 WriteChannelInfoOffset; /* Reserved MBZ */ __le16 WriteChannelInfoOffset;
__le16 WriteChannelInfoLength; /* Reserved MBZ */ __le16 WriteChannelInfoLength;
__le32 Flags; __le32 Flags;
__u8 Buffer[1]; __u8 Buffer[1];
} __packed; } __packed;
...@@ -907,7 +907,7 @@ struct smb2_lock_element { ...@@ -907,7 +907,7 @@ struct smb2_lock_element {
} __packed; } __packed;
struct smb2_lock_req { struct smb2_lock_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 48 */ __le16 StructureSize; /* Must be 48 */
__le16 LockCount; __le16 LockCount;
__le32 Reserved; __le32 Reserved;
...@@ -924,7 +924,7 @@ struct smb2_lock_rsp { ...@@ -924,7 +924,7 @@ struct smb2_lock_rsp {
} __packed; } __packed;
struct smb2_echo_req { struct smb2_echo_req {
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;
...@@ -942,7 +942,7 @@ struct smb2_echo_rsp { ...@@ -942,7 +942,7 @@ struct smb2_echo_rsp {
#define SMB2_REOPEN 0x10 #define SMB2_REOPEN 0x10
struct smb2_query_directory_req { struct smb2_query_directory_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 33 */ __le16 StructureSize; /* Must be 33 */
__u8 FileInformationClass; __u8 FileInformationClass;
__u8 Flags; __u8 Flags;
...@@ -989,7 +989,7 @@ struct smb2_query_directory_rsp { ...@@ -989,7 +989,7 @@ struct smb2_query_directory_rsp {
#define SL_INDEX_SPECIFIED 0x00000004 #define SL_INDEX_SPECIFIED 0x00000004
struct smb2_query_info_req { struct smb2_query_info_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 41 */ __le16 StructureSize; /* Must be 41 */
__u8 InfoType; __u8 InfoType;
__u8 FileInfoClass; __u8 FileInfoClass;
...@@ -1013,7 +1013,7 @@ struct smb2_query_info_rsp { ...@@ -1013,7 +1013,7 @@ struct smb2_query_info_rsp {
} __packed; } __packed;
struct smb2_set_info_req { struct smb2_set_info_req {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 33 */ __le16 StructureSize; /* Must be 33 */
__u8 InfoType; __u8 InfoType;
__u8 FileInfoClass; __u8 FileInfoClass;
...@@ -1031,7 +1031,19 @@ struct smb2_set_info_rsp { ...@@ -1031,7 +1031,19 @@ struct smb2_set_info_rsp {
__le16 StructureSize; /* Must be 2 */ __le16 StructureSize; /* Must be 2 */
} __packed; } __packed;
struct smb2_oplock_break { /* oplock break without an rfc1002 header */
struct smb2_oplock_break_req {
struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 24 */
__u8 OplockLevel;
__u8 Reserved;
__le32 Reserved2;
__u64 PersistentFid;
__u64 VolatileFid;
} __packed;
/* oplock break with an rfc1002 header */
struct smb2_oplock_break_rsp {
struct smb2_hdr hdr; struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 24 */ __le16 StructureSize; /* Must be 24 */
__u8 OplockLevel; __u8 OplockLevel;
...@@ -1057,7 +1069,7 @@ struct smb2_lease_break { ...@@ -1057,7 +1069,7 @@ struct smb2_lease_break {
} __packed; } __packed;
struct smb2_lease_ack { struct smb2_lease_ack {
struct smb2_hdr hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 36 */ __le16 StructureSize; /* Must be 36 */
__le16 Reserved; __le16 Reserved;
__le32 Flags; __le32 Flags;
......
...@@ -125,8 +125,7 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, ...@@ -125,8 +125,7 @@ extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
struct smb2_err_rsp **err_buf); struct smb2_err_rsp **err_buf);
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 opcode, u64 persistent_fid, u64 volatile_fid, u32 opcode,
bool is_fsctl, bool use_ipc, bool is_fsctl, char *in_data, u32 indatalen,
char *in_data, u32 indatalen,
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);
......
This diff is collapsed.
/*
* Copyright (C) 2017, Microsoft Corporation.
*
* Author(s): Long Li <longli@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.
*/
#ifndef _SMBDIRECT_H
#define _SMBDIRECT_H
#ifdef CONFIG_CIFS_SMB_DIRECT
#define cifs_rdma_enabled(server) ((server)->rdma)
#include "cifsglob.h"
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
#include <linux/mempool.h>
extern int rdma_readwrite_threshold;
extern int smbd_max_frmr_depth;
extern int smbd_keep_alive_interval;
extern int smbd_max_receive_size;
extern int smbd_max_fragmented_recv_size;
extern int smbd_max_send_size;
extern int smbd_send_credit_target;
extern int smbd_receive_credit_max;
enum keep_alive_status {
KEEP_ALIVE_NONE,
KEEP_ALIVE_PENDING,
KEEP_ALIVE_SENT,
};
enum smbd_connection_status {
SMBD_CREATED,
SMBD_CONNECTING,
SMBD_CONNECTED,
SMBD_NEGOTIATE_FAILED,
SMBD_DISCONNECTING,
SMBD_DISCONNECTED,
SMBD_DESTROYED
};
/*
* The context for the SMBDirect transport
* Everything related to the transport is here. It has several logical parts
* 1. RDMA related structures
* 2. SMBDirect connection parameters
* 3. Memory registrations
* 4. Receive and reassembly queues for data receive path
* 5. mempools for allocating packets
*/
struct smbd_connection {
enum smbd_connection_status transport_status;
/* RDMA related */
struct rdma_cm_id *id;
struct ib_qp_init_attr qp_attr;
struct ib_pd *pd;
struct ib_cq *send_cq, *recv_cq;
struct ib_device_attr dev_attr;
int ri_rc;
struct completion ri_done;
wait_queue_head_t conn_wait;
wait_queue_head_t wait_destroy;
struct completion negotiate_completion;
bool negotiate_done;
struct work_struct destroy_work;
struct work_struct disconnect_work;
struct work_struct recv_done_work;
struct work_struct post_send_credits_work;
spinlock_t lock_new_credits_offered;
int new_credits_offered;
/* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
int receive_credit_max;
int send_credit_target;
int max_send_size;
int max_fragmented_recv_size;
int max_fragmented_send_size;
int max_receive_size;
int keep_alive_interval;
int max_readwrite_size;
enum keep_alive_status keep_alive_requested;
int protocol;
atomic_t send_credits;
atomic_t receive_credits;
int receive_credit_target;
int fragment_reassembly_remaining;
/* Memory registrations */
/* Maximum number of RDMA read/write outstanding on this connection */
int responder_resources;
/* Maximum number of SGEs in a RDMA write/read */
int max_frmr_depth;
/*
* If payload is less than or equal to the threshold,
* use RDMA send/recv to send upper layer I/O.
* If payload is more than the threshold,
* use RDMA read/write through memory registration for I/O.
*/
int rdma_readwrite_threshold;
enum ib_mr_type mr_type;
struct list_head mr_list;
spinlock_t mr_list_lock;
/* The number of available MRs ready for memory registration */
atomic_t mr_ready_count;
atomic_t mr_used_count;
wait_queue_head_t wait_mr;
struct work_struct mr_recovery_work;
/* Used by transport to wait until all MRs are returned */
wait_queue_head_t wait_for_mr_cleanup;
/* Activity accoutning */
/* Pending reqeusts issued from upper layer */
int smbd_send_pending;
wait_queue_head_t wait_smbd_send_pending;
int smbd_recv_pending;
wait_queue_head_t wait_smbd_recv_pending;
atomic_t send_pending;
wait_queue_head_t wait_send_pending;
atomic_t send_payload_pending;
wait_queue_head_t wait_send_payload_pending;
/* Receive queue */
struct list_head receive_queue;
int count_receive_queue;
spinlock_t receive_queue_lock;
struct list_head empty_packet_queue;
int count_empty_packet_queue;
spinlock_t empty_packet_queue_lock;
wait_queue_head_t wait_receive_queues;
/* Reassembly queue */
struct list_head reassembly_queue;
spinlock_t reassembly_queue_lock;
wait_queue_head_t wait_reassembly_queue;
/* total data length of reassembly queue */
int reassembly_data_length;
int reassembly_queue_length;
/* the offset to first buffer in reassembly queue */
int first_entry_offset;
bool send_immediate;
wait_queue_head_t wait_send_queue;
/*
* Indicate if we have received a full packet on the connection
* This is used to identify the first SMBD packet of a assembled
* payload (SMB packet) in reassembly queue so we can return a
* RFC1002 length to upper layer to indicate the length of the SMB
* packet received
*/
bool full_packet_received;
struct workqueue_struct *workqueue;
struct delayed_work idle_timer_work;
struct delayed_work send_immediate_work;
/* Memory pool for preallocating buffers */
/* request pool for RDMA send */
struct kmem_cache *request_cache;
mempool_t *request_mempool;
/* response pool for RDMA receive */
struct kmem_cache *response_cache;
mempool_t *response_mempool;
/* for debug purposes */
unsigned int count_get_receive_buffer;
unsigned int count_put_receive_buffer;
unsigned int count_reassembly_queue;
unsigned int count_enqueue_reassembly_queue;
unsigned int count_dequeue_reassembly_queue;
unsigned int count_send_empty;
};
enum smbd_message_type {
SMBD_NEGOTIATE_RESP,
SMBD_TRANSFER_DATA,
};
#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
struct smbd_negotiate_req {
__le16 min_version;
__le16 max_version;
__le16 reserved;
__le16 credits_requested;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
struct smbd_negotiate_resp {
__le16 min_version;
__le16 max_version;
__le16 negotiated_version;
__le16 reserved;
__le16 credits_requested;
__le16 credits_granted;
__le32 status;
__le32 max_readwrite_size;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
struct smbd_data_transfer {
__le16 credits_requested;
__le16 credits_granted;
__le16 flags;
__le16 reserved;
__le32 remaining_data_length;
__le32 data_offset;
__le32 data_length;
__le32 padding;
__u8 buffer[];
} __packed;
/* The packet fields for a registered RDMA buffer */
struct smbd_buffer_descriptor_v1 {
__le64 offset;
__le32 token;
__le32 length;
} __packed;
/* Default maximum number of SGEs in a RDMA send/recv */
#define SMBDIRECT_MAX_SGE 16
/* The context for a SMBD request */
struct smbd_request {
struct smbd_connection *info;
struct ib_cqe cqe;
/* true if this request carries upper layer payload */
bool has_payload;
/* the SGE entries for this packet */
struct ib_sge sge[SMBDIRECT_MAX_SGE];
int num_sge;
/* SMBD packet header follows this structure */
u8 packet[];
};
/* The context for a SMBD response */
struct smbd_response {
struct smbd_connection *info;
struct ib_cqe cqe;
struct ib_sge sge;
enum smbd_message_type type;
/* Link to receive queue or reassembly queue */
struct list_head list;
/* Indicate if this is the 1st packet of a payload */
bool first_segment;
/* SMBD packet header and payload follows this structure */
u8 packet[];
};
/* Create a SMBDirect session */
struct smbd_connection *smbd_get_connection(
struct TCP_Server_Info *server, struct sockaddr *dstaddr);
/* Reconnect SMBDirect session */
int smbd_reconnect(struct TCP_Server_Info *server);
/* Destroy SMBDirect session */
void smbd_destroy(struct smbd_connection *info);
/* Interface for carrying upper layer I/O through send/recv */
int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst);
enum mr_state {
MR_READY,
MR_REGISTERED,
MR_INVALIDATED,
MR_ERROR
};
struct smbd_mr {
struct smbd_connection *conn;
struct list_head list;
enum mr_state state;
struct ib_mr *mr;
struct scatterlist *sgl;
int sgl_count;
enum dma_data_direction dir;
union {
struct ib_reg_wr wr;
struct ib_send_wr inv_wr;
};
struct ib_cqe cqe;
bool need_invalidate;
struct completion invalidate_done;
};
/* Interfaces to register and deregister MR for RDMA read/write */
struct smbd_mr *smbd_register_mr(
struct smbd_connection *info, struct page *pages[], int num_pages,
int tailsz, bool writing, bool need_invalidate);
int smbd_deregister_mr(struct smbd_mr *mr);
#else
#define cifs_rdma_enabled(server) 0
struct smbd_connection {};
static inline void *smbd_get_connection(
struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
static inline void smbd_destroy(struct smbd_connection *info) {}
static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
static inline int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) {return -1; }
#endif
#endif
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "smbdirect.h"
/* Max number of iovectors we can use off the stack when sending requests. */
#define CIFS_MAX_IOV_SIZE 8
void void
cifs_wake_up_task(struct mid_q_entry *mid) cifs_wake_up_task(struct mid_q_entry *mid)
...@@ -229,7 +233,10 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) ...@@ -229,7 +233,10 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
struct socket *ssocket = server->ssocket; struct socket *ssocket = server->ssocket;
struct msghdr smb_msg; struct msghdr smb_msg;
int val = 1; int val = 1;
if (cifs_rdma_enabled(server) && server->smbd_conn) {
rc = smbd_send(server->smbd_conn, rqst);
goto smbd_done;
}
if (ssocket == NULL) if (ssocket == NULL)
return -ENOTSOCK; return -ENOTSOCK;
...@@ -298,7 +305,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst) ...@@ -298,7 +305,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
*/ */
server->tcpStatus = CifsNeedReconnect; server->tcpStatus = CifsNeedReconnect;
} }
smbd_done:
if (rc < 0 && rc != -EINTR) if (rc < 0 && rc != -EINTR)
cifs_dbg(VFS, "Error %d sending data on socket to server\n", cifs_dbg(VFS, "Error %d sending data on socket to server\n",
rc); rc);
...@@ -803,12 +810,16 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, ...@@ -803,12 +810,16 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
const int flags, struct kvec *resp_iov) const int flags, struct kvec *resp_iov)
{ {
struct smb_rqst rqst; struct smb_rqst rqst;
struct kvec *new_iov; struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
int rc; int rc;
new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL); if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
if (!new_iov) new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
return -ENOMEM; GFP_KERNEL);
if (!new_iov)
return -ENOMEM;
} else
new_iov = s_iov;
/* 1st iov is a RFC1001 length followed by the rest of the packet */ /* 1st iov is a RFC1001 length followed by the rest of the packet */
memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
...@@ -823,7 +834,51 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, ...@@ -823,7 +834,51 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rqst.rq_nvec = n_vec + 1; rqst.rq_nvec = n_vec + 1;
rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov); rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
kfree(new_iov); if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
kfree(new_iov);
return rc;
}
/* Like SendReceive2 but iov[0] does not contain an rfc1002 header */
int
smb2_send_recv(const unsigned int xid, struct cifs_ses *ses,
struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
const int flags, struct kvec *resp_iov)
{
struct smb_rqst rqst;
struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
int rc;
int i;
__u32 count;
__be32 rfc1002_marker;
if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
GFP_KERNEL);
if (!new_iov)
return -ENOMEM;
} else
new_iov = s_iov;
/* 1st iov is an RFC1002 Session Message length */
memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
count = 0;
for (i = 1; i < n_vec + 1; i++)
count += new_iov[i].iov_len;
rfc1002_marker = cpu_to_be32(count);
new_iov[0].iov_base = &rfc1002_marker;
new_iov[0].iov_len = 4;
memset(&rqst, 0, sizeof(struct smb_rqst));
rqst.rq_iov = new_iov;
rqst.rq_nvec = n_vec + 1;
rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
kfree(new_iov);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment