aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-29 15:42:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-29 15:42:10 -0400
commit442a9ffabb21f175027e93e72ea05159818271a6 (patch)
treec9c708a36c8af91389527dbf310ef8ee2c4e3409 /fs/cifs
parent4b781474682434e7881f20e9dfbe6687ea619795 (diff)
parent2c0c2a08bed7a3b791f88d09d16ace56acb3dd98 (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS updates from Steve French. * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: (29 commits) cifs: fix oops while traversing open file list (try #4) cifs: Fix comment as d_alloc_root() is replaced by d_make_root() CIFS: Introduce SMB2 mounts as vers=2.1 CIFS: Introduce SMB2 Kconfig option CIFS: Move add/set_credits and get_credits_field to ops structure CIFS: Move protocol specific demultiplex thread calls to ops struct CIFS: Move protocol specific part from cifs_readv_receive to ops struct CIFS: Move header_size/max_header_size to ops structure CIFS: Move protocol specific part from SendReceive2 to ops struct cifs: Include backup intent search flags during searches {try #2) CIFS: Separate protocol specific part from setlk CIFS: Separate protocol specific part from getlk CIFS: Separate protocol specific lock type handling CIFS: Convert lock type to 32 bit variable CIFS: Move locks to cifsFileInfo structure cifs: convert send_nt_cancel into a version specific op cifs: add a smb_version_operations/values structures and a smb_version enum cifs: remove the vers= and version= synonyms for ver= cifs: add warning about change in default cache semantics in 3.7 cifs: display cache= option in /proc/mounts ...
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/Kconfig20
-rw-r--r--fs/cifs/Makefile4
-rw-r--r--fs/cifs/README5
-rw-r--r--fs/cifs/cifs_debug.c56
-rw-r--r--fs/cifs/cifs_debug.h4
-rw-r--r--fs/cifs/cifsfs.c23
-rw-r--r--fs/cifs/cifsglob.h107
-rw-r--r--fs/cifs/cifsproto.h19
-rw-r--r--fs/cifs/cifssmb.c181
-rw-r--r--fs/cifs/connect.c178
-rw-r--r--fs/cifs/file.c683
-rw-r--r--fs/cifs/ioctl.c8
-rw-r--r--fs/cifs/misc.c66
-rw-r--r--fs/cifs/readdir.c15
-rw-r--r--fs/cifs/smb1ops.c154
-rw-r--r--fs/cifs/smb2ops.c27
-rw-r--r--fs/cifs/transport.c76
17 files changed, 1039 insertions, 587 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 2b243af70aa3..a08306a8bec9 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -158,3 +158,23 @@ config CIFS_NFSD_EXPORT
158 depends on CIFS && EXPERIMENTAL && BROKEN 158 depends on CIFS && EXPERIMENTAL && BROKEN
159 help 159 help
160 Allows NFS server to export a CIFS mounted share (nfsd over cifs) 160 Allows NFS server to export a CIFS mounted share (nfsd over cifs)
161
162config CIFS_SMB2
163 bool "SMB2 network file system support (EXPERIMENTAL)"
164 depends on EXPERIMENTAL && INET && BROKEN
165 select NLS
166 select KEYS
167 select FSCACHE
168 select DNS_RESOLVER
169
170 help
171 This enables experimental support for the SMB2 (Server Message Block
172 version 2) protocol. The SMB2 protocol is the successor to the
173 popular CIFS and SMB network file sharing protocols. SMB2 is the
174 native file sharing mechanism for recent versions of Windows
175 operating systems (since Vista). SMB2 enablement will eventually
176 allow users better performance, security and features, than would be
177 possible with cifs. Note that smb2 mount options also are simpler
178 (compared to cifs) due to protocol improvements.
179
180 Unless you are a developer or tester, say N.
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 005d524c3a4a..4b4127544349 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_CIFS) += cifs.o
6cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ 6cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
7 link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ 7 link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \
8 cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ 8 cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
9 readdir.o ioctl.o sess.o export.o 9 readdir.o ioctl.o sess.o export.o smb1ops.o
10 10
11cifs-$(CONFIG_CIFS_ACL) += cifsacl.o 11cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
12 12
@@ -15,3 +15,5 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
15cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o 15cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
16 16
17cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o 17cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
18
19cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o
diff --git a/fs/cifs/README b/fs/cifs/README
index b7d782bab797..22ab7b5b8da7 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -608,11 +608,6 @@ Stats Lists summary resource usage information as well as per
608 in the kernel configuration. 608 in the kernel configuration.
609 609
610Configuration pseudo-files: 610Configuration pseudo-files:
611MultiuserMount If set to one, more than one CIFS session to
612 the same server ip address can be established
613 if more than one uid accesses the same mount
614 point and if the uids user/password mapping
615 information is available. (default is 0)
616PacketSigningEnabled If set to one, cifs packet signing is enabled 611PacketSigningEnabled If set to one, cifs packet signing is enabled
617 and will be used if the server requires 612 and will be used if the server requires
618 it. If set to two, cifs packet signing is 613 it. If set to two, cifs packet signing is
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 270464629416..e8140528ca5c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -57,19 +57,21 @@ cifs_dump_mem(char *label, void *data, int length)
57 } 57 }
58} 58}
59 59
60#ifdef CONFIG_CIFS_DEBUG2
61void cifs_dump_detail(void *buf) 60void cifs_dump_detail(void *buf)
62{ 61{
62#ifdef CONFIG_CIFS_DEBUG2
63 struct smb_hdr *smb = (struct smb_hdr *)buf; 63 struct smb_hdr *smb = (struct smb_hdr *)buf;
64 64
65 cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", 65 cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
66 smb->Command, smb->Status.CifsError, 66 smb->Command, smb->Status.CifsError,
67 smb->Flags, smb->Flags2, smb->Mid, smb->Pid); 67 smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
68 cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); 68 cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb));
69#endif /* CONFIG_CIFS_DEBUG2 */
69} 70}
70 71
71void cifs_dump_mids(struct TCP_Server_Info *server) 72void cifs_dump_mids(struct TCP_Server_Info *server)
72{ 73{
74#ifdef CONFIG_CIFS_DEBUG2
73 struct list_head *tmp; 75 struct list_head *tmp;
74 struct mid_q_entry *mid_entry; 76 struct mid_q_entry *mid_entry;
75 77
@@ -102,8 +104,8 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
102 } 104 }
103 } 105 }
104 spin_unlock(&GlobalMid_Lock); 106 spin_unlock(&GlobalMid_Lock);
105}
106#endif /* CONFIG_CIFS_DEBUG2 */ 107#endif /* CONFIG_CIFS_DEBUG2 */
108}
107 109
108#ifdef CONFIG_PROC_FS 110#ifdef CONFIG_PROC_FS
109static int cifs_debug_data_proc_show(struct seq_file *m, void *v) 111static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
@@ -420,7 +422,6 @@ static struct proc_dir_entry *proc_fs_cifs;
420static const struct file_operations cifsFYI_proc_fops; 422static const struct file_operations cifsFYI_proc_fops;
421static const struct file_operations cifs_lookup_cache_proc_fops; 423static const struct file_operations cifs_lookup_cache_proc_fops;
422static const struct file_operations traceSMB_proc_fops; 424static const struct file_operations traceSMB_proc_fops;
423static const struct file_operations cifs_multiuser_mount_proc_fops;
424static const struct file_operations cifs_security_flags_proc_fops; 425static const struct file_operations cifs_security_flags_proc_fops;
425static const struct file_operations cifs_linux_ext_proc_fops; 426static const struct file_operations cifs_linux_ext_proc_fops;
426 427
@@ -440,8 +441,6 @@ cifs_proc_init(void)
440 proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); 441 proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
441 proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, 442 proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
442 &cifs_linux_ext_proc_fops); 443 &cifs_linux_ext_proc_fops);
443 proc_create("MultiuserMount", 0, proc_fs_cifs,
444 &cifs_multiuser_mount_proc_fops);
445 proc_create("SecurityFlags", 0, proc_fs_cifs, 444 proc_create("SecurityFlags", 0, proc_fs_cifs,
446 &cifs_security_flags_proc_fops); 445 &cifs_security_flags_proc_fops);
447 proc_create("LookupCacheEnabled", 0, proc_fs_cifs, 446 proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
@@ -460,7 +459,6 @@ cifs_proc_clean(void)
460#ifdef CONFIG_CIFS_STATS 459#ifdef CONFIG_CIFS_STATS
461 remove_proc_entry("Stats", proc_fs_cifs); 460 remove_proc_entry("Stats", proc_fs_cifs);
462#endif 461#endif
463 remove_proc_entry("MultiuserMount", proc_fs_cifs);
464 remove_proc_entry("SecurityFlags", proc_fs_cifs); 462 remove_proc_entry("SecurityFlags", proc_fs_cifs);
465 remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); 463 remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
466 remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); 464 remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
@@ -617,52 +615,6 @@ static const struct file_operations traceSMB_proc_fops = {
617 .write = traceSMB_proc_write, 615 .write = traceSMB_proc_write,
618}; 616};
619 617
620static int cifs_multiuser_mount_proc_show(struct seq_file *m, void *v)
621{
622 seq_printf(m, "%d\n", multiuser_mount);
623 return 0;
624}
625
626static int cifs_multiuser_mount_proc_open(struct inode *inode, struct file *fh)
627{
628 return single_open(fh, cifs_multiuser_mount_proc_show, NULL);
629}
630
631static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
632 const char __user *buffer, size_t count, loff_t *ppos)
633{
634 char c;
635 int rc;
636 static bool warned;
637
638 rc = get_user(c, buffer);
639 if (rc)
640 return rc;
641 if (c == '0' || c == 'n' || c == 'N')
642 multiuser_mount = 0;
643 else if (c == '1' || c == 'y' || c == 'Y') {
644 multiuser_mount = 1;
645 if (!warned) {
646 warned = true;
647 printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
648 "mount code is scheduled to be deprecated in "
649 "3.5. Please switch to using the multiuser "
650 "mount option.");
651 }
652 }
653
654 return count;
655}
656
657static const struct file_operations cifs_multiuser_mount_proc_fops = {
658 .owner = THIS_MODULE,
659 .open = cifs_multiuser_mount_proc_open,
660 .read = seq_read,
661 .llseek = seq_lseek,
662 .release = single_release,
663 .write = cifs_multiuser_mount_proc_write,
664};
665
666static int cifs_security_flags_proc_show(struct seq_file *m, void *v) 618static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
667{ 619{
668 seq_printf(m, "0x%x\n", global_secflags); 620 seq_printf(m, "0x%x\n", global_secflags);
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 566e0ae8dc2c..c0c68bb492d7 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -24,10 +24,10 @@
24#define _H_CIFS_DEBUG 24#define _H_CIFS_DEBUG
25 25
26void cifs_dump_mem(char *label, void *data, int length); 26void cifs_dump_mem(char *label, void *data, int length);
27#ifdef CONFIG_CIFS_DEBUG2
28#define DBG2 2
29void cifs_dump_detail(void *); 27void cifs_dump_detail(void *);
30void cifs_dump_mids(struct TCP_Server_Info *); 28void cifs_dump_mids(struct TCP_Server_Info *);
29#ifdef CONFIG_CIFS_DEBUG2
30#define DBG2 2
31#else 31#else
32#define DBG2 0 32#define DBG2 0
33#endif 33#endif
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 0a0fa0250e99..8b6e344eb0ba 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -56,7 +56,6 @@ int traceSMB = 0;
56bool enable_oplocks = true; 56bool enable_oplocks = true;
57unsigned int linuxExtEnabled = 1; 57unsigned int linuxExtEnabled = 1;
58unsigned int lookupCacheEnabled = 1; 58unsigned int lookupCacheEnabled = 1;
59unsigned int multiuser_mount = 0;
60unsigned int global_secflags = CIFSSEC_DEF; 59unsigned int global_secflags = CIFSSEC_DEF;
61/* unsigned int ntlmv2_support = 0; */ 60/* unsigned int ntlmv2_support = 0; */
62unsigned int sign_CIFS_PDUs = 1; 61unsigned int sign_CIFS_PDUs = 1;
@@ -125,7 +124,7 @@ cifs_read_super(struct super_block *sb)
125 goto out_no_root; 124 goto out_no_root;
126 } 125 }
127 126
128 /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ 127 /* do that *after* d_make_root() - we want NULL ->d_op for root here */
129 if (cifs_sb_master_tcon(cifs_sb)->nocase) 128 if (cifs_sb_master_tcon(cifs_sb)->nocase)
130 sb->s_d_op = &cifs_ci_dentry_ops; 129 sb->s_d_op = &cifs_ci_dentry_ops;
131 else 130 else
@@ -329,6 +328,19 @@ cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
329 seq_printf(s, "i"); 328 seq_printf(s, "i");
330} 329}
331 330
331static void
332cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
333{
334 seq_printf(s, ",cache=");
335
336 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
337 seq_printf(s, "strict");
338 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
339 seq_printf(s, "none");
340 else
341 seq_printf(s, "loose");
342}
343
332/* 344/*
333 * cifs_show_options() is for displaying mount options in /proc/mounts. 345 * cifs_show_options() is for displaying mount options in /proc/mounts.
334 * Not all settable options are displayed but most of the important 346 * Not all settable options are displayed but most of the important
@@ -342,7 +354,9 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
342 struct sockaddr *srcaddr; 354 struct sockaddr *srcaddr;
343 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; 355 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
344 356
357 seq_printf(s, ",vers=%s", tcon->ses->server->vals->version_string);
345 cifs_show_security(s, tcon->ses->server); 358 cifs_show_security(s, tcon->ses->server);
359 cifs_show_cache_flavor(s, cifs_sb);
346 360
347 seq_printf(s, ",unc=%s", tcon->treeName); 361 seq_printf(s, ",unc=%s", tcon->treeName);
348 362
@@ -408,8 +422,6 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
408 seq_printf(s, ",rwpidforward"); 422 seq_printf(s, ",rwpidforward");
409 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) 423 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
410 seq_printf(s, ",forcemand"); 424 seq_printf(s, ",forcemand");
411 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
412 seq_printf(s, ",directio");
413 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 425 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
414 seq_printf(s, ",nouser_xattr"); 426 seq_printf(s, ",nouser_xattr");
415 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 427 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
@@ -432,8 +444,6 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
432 seq_printf(s, ",nostrictsync"); 444 seq_printf(s, ",nostrictsync");
433 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) 445 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
434 seq_printf(s, ",noperm"); 446 seq_printf(s, ",noperm");
435 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
436 seq_printf(s, ",strictcache");
437 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) 447 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
438 seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid); 448 seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid);
439 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) 449 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
@@ -945,7 +955,6 @@ cifs_init_once(void *inode)
945 struct cifsInodeInfo *cifsi = inode; 955 struct cifsInodeInfo *cifsi = inode;
946 956
947 inode_init_once(&cifsi->vfs_inode); 957 inode_init_once(&cifsi->vfs_inode);
948 INIT_LIST_HEAD(&cifsi->llist);
949 mutex_init(&cifsi->lock_mutex); 958 mutex_init(&cifsi->lock_mutex);
950} 959}
951 960
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 4ff6313f0a91..20350a93ed99 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -43,6 +43,7 @@
43 43
44#define CIFS_MIN_RCV_POOL 4 44#define CIFS_MIN_RCV_POOL 4
45 45
46#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
46/* 47/*
47 * default attribute cache timeout (jiffies) 48 * default attribute cache timeout (jiffies)
48 */ 49 */
@@ -150,6 +151,57 @@ struct cifs_cred {
150 ***************************************************************** 151 *****************************************************************
151 */ 152 */
152 153
154enum smb_version {
155 Smb_1 = 1,
156 Smb_21,
157};
158
159struct mid_q_entry;
160struct TCP_Server_Info;
161struct cifsFileInfo;
162struct cifs_ses;
163
164struct smb_version_operations {
165 int (*send_cancel)(struct TCP_Server_Info *, void *,
166 struct mid_q_entry *);
167 bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *);
168 /* setup request: allocate mid, sign message */
169 int (*setup_request)(struct cifs_ses *, struct kvec *, unsigned int,
170 struct mid_q_entry **);
171 /* check response: verify signature, map error */
172 int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *,
173 bool);
174 void (*add_credits)(struct TCP_Server_Info *, const unsigned int);
175 void (*set_credits)(struct TCP_Server_Info *, const int);
176 int * (*get_credits_field)(struct TCP_Server_Info *);
177 /* data offset from read response message */
178 unsigned int (*read_data_offset)(char *);
179 /* data length from read response message */
180 unsigned int (*read_data_length)(char *);
181 /* map smb to linux error */
182 int (*map_error)(char *, bool);
183 /* find mid corresponding to the response message */
184 struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
185 void (*dump_detail)(void *);
186 /* verify the message */
187 int (*check_message)(char *, unsigned int);
188 bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
189};
190
191struct smb_version_values {
192 char *version_string;
193 __u32 large_lock_type;
194 __u32 exclusive_lock_type;
195 __u32 shared_lock_type;
196 __u32 unlock_lock_type;
197 size_t header_size;
198 size_t max_header_size;
199 size_t read_rsp_size;
200};
201
202#define HEADER_SIZE(server) (server->vals->header_size)
203#define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
204
153struct smb_vol { 205struct smb_vol {
154 char *username; 206 char *username;
155 char *password; 207 char *password;
@@ -205,6 +257,8 @@ struct smb_vol {
205 bool sockopt_tcp_nodelay:1; 257 bool sockopt_tcp_nodelay:1;
206 unsigned short int port; 258 unsigned short int port;
207 unsigned long actimeo; /* attribute cache timeout (jiffies) */ 259 unsigned long actimeo; /* attribute cache timeout (jiffies) */
260 struct smb_version_operations *ops;
261 struct smb_version_values *vals;
208 char *prepath; 262 char *prepath;
209 struct sockaddr_storage srcaddr; /* allow binding to a local IP */ 263 struct sockaddr_storage srcaddr; /* allow binding to a local IP */
210 struct nls_table *local_nls; 264 struct nls_table *local_nls;
@@ -242,6 +296,8 @@ struct TCP_Server_Info {
242 int srv_count; /* reference counter */ 296 int srv_count; /* reference counter */
243 /* 15 character server name + 0x20 16th byte indicating type = srv */ 297 /* 15 character server name + 0x20 16th byte indicating type = srv */
244 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 298 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
299 struct smb_version_operations *ops;
300 struct smb_version_values *vals;
245 enum statusEnum tcpStatus; /* what we think the status is */ 301 enum statusEnum tcpStatus; /* what we think the status is */
246 char *hostname; /* hostname portion of UNC string */ 302 char *hostname; /* hostname portion of UNC string */
247 struct socket *ssocket; 303 struct socket *ssocket;
@@ -321,16 +377,6 @@ in_flight(struct TCP_Server_Info *server)
321 return num; 377 return num;
322} 378}
323 379
324static inline int*
325get_credits_field(struct TCP_Server_Info *server)
326{
327 /*
328 * This will change to switch statement when we reserve slots for echos
329 * and oplock breaks.
330 */
331 return &server->credits;
332}
333
334static inline bool 380static inline bool
335has_credits(struct TCP_Server_Info *server, int *credits) 381has_credits(struct TCP_Server_Info *server, int *credits)
336{ 382{
@@ -341,16 +387,16 @@ has_credits(struct TCP_Server_Info *server, int *credits)
341 return num > 0; 387 return num > 0;
342} 388}
343 389
344static inline size_t 390static inline void
345header_size(void) 391add_credits(struct TCP_Server_Info *server, const unsigned int add)
346{ 392{
347 return sizeof(struct smb_hdr); 393 server->ops->add_credits(server, add);
348} 394}
349 395
350static inline size_t 396static inline void
351max_header_size(void) 397set_credits(struct TCP_Server_Info *server, const int val)
352{ 398{
353 return MAX_CIFS_HDR_SIZE; 399 server->ops->set_credits(server, val);
354} 400}
355 401
356/* 402/*
@@ -547,8 +593,7 @@ struct cifsLockInfo {
547 __u64 offset; 593 __u64 offset;
548 __u64 length; 594 __u64 length;
549 __u32 pid; 595 __u32 pid;
550 __u8 type; 596 __u32 type;
551 __u16 netfid;
552}; 597};
553 598
554/* 599/*
@@ -573,6 +618,10 @@ struct cifs_search_info {
573struct cifsFileInfo { 618struct cifsFileInfo {
574 struct list_head tlist; /* pointer to next fid owned by tcon */ 619 struct list_head tlist; /* pointer to next fid owned by tcon */
575 struct list_head flist; /* next fid (file instance) for this inode */ 620 struct list_head flist; /* next fid (file instance) for this inode */
621 struct list_head llist; /*
622 * brlocks held by this fid, protected by
623 * lock_mutex from cifsInodeInfo structure
624 */
576 unsigned int uid; /* allows finding which FileInfo structure */ 625 unsigned int uid; /* allows finding which FileInfo structure */
577 __u32 pid; /* process id who opened file */ 626 __u32 pid; /* process id who opened file */
578 __u16 netfid; /* file id from remote */ 627 __u16 netfid; /* file id from remote */
@@ -615,9 +664,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
615 */ 664 */
616 665
617struct cifsInodeInfo { 666struct cifsInodeInfo {
618 struct list_head llist; /* brlocks for this inode */
619 bool can_cache_brlcks; 667 bool can_cache_brlcks;
620 struct mutex lock_mutex; /* protect two fields above */ 668 struct mutex lock_mutex; /*
669 * protect the field above and llist
670 * from every cifsFileInfo structure
671 * from openFileList
672 */
621 /* BB add in lists for dirty pages i.e. write caching info for oplock */ 673 /* BB add in lists for dirty pages i.e. write caching info for oplock */
622 struct list_head openFileList; 674 struct list_head openFileList;
623 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ 675 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
@@ -703,7 +755,6 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
703 755
704#endif 756#endif
705 757
706struct mid_q_entry;
707 758
708/* 759/*
709 * This is the prototype for the mid receive function. This function is for 760 * This is the prototype for the mid receive function. This function is for
@@ -1042,12 +1093,7 @@ GLOBAL_EXTERN atomic_t smBufAllocCount;
1042GLOBAL_EXTERN atomic_t midCount; 1093GLOBAL_EXTERN atomic_t midCount;
1043 1094
1044/* Misc globals */ 1095/* Misc globals */
1045GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions 1096GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */
1046 to be established on existing mount if we
1047 have the uid/password or Kerberos credential
1048 or equivalent for current user */
1049/* enable or disable oplocks */
1050GLOBAL_EXTERN bool enable_oplocks;
1051GLOBAL_EXTERN unsigned int lookupCacheEnabled; 1097GLOBAL_EXTERN unsigned int lookupCacheEnabled;
1052GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent 1098GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent
1053 with more secure ntlmssp2 challenge/resp */ 1099 with more secure ntlmssp2 challenge/resp */
@@ -1074,4 +1120,11 @@ void cifs_oplock_break(struct work_struct *work);
1074extern const struct slow_work_ops cifs_oplock_break_ops; 1120extern const struct slow_work_ops cifs_oplock_break_ops;
1075extern struct workqueue_struct *cifsiod_wq; 1121extern struct workqueue_struct *cifsiod_wq;
1076 1122
1123/* Operations for different SMB versions */
1124#define SMB1_VERSION_STRING "1.0"
1125extern struct smb_version_operations smb1_operations;
1126extern struct smb_version_values smb1_values;
1127#define SMB21_VERSION_STRING "2.1"
1128extern struct smb_version_operations smb21_operations;
1129extern struct smb_version_values smb21_values;
1077#endif /* _CIFS_GLOB_H */ 1130#endif /* _CIFS_GLOB_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 96192c1e380a..5ec21ecf7980 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -78,6 +78,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
78 int * /* bytes returned */ , const int long_op); 78 int * /* bytes returned */ , const int long_op);
79extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, 79extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
80 char *in_buf, int flags); 80 char *in_buf, int flags);
81extern int cifs_setup_request(struct cifs_ses *, struct kvec *, unsigned int,
82 struct mid_q_entry **);
81extern int cifs_check_receive(struct mid_q_entry *mid, 83extern int cifs_check_receive(struct mid_q_entry *mid,
82 struct TCP_Server_Info *server, bool log_error); 84 struct TCP_Server_Info *server, bool log_error);
83extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, 85extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
@@ -88,9 +90,6 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
88 struct smb_hdr *in_buf , 90 struct smb_hdr *in_buf ,
89 struct smb_hdr *out_buf, 91 struct smb_hdr *out_buf,
90 int *bytes_returned); 92 int *bytes_returned);
91extern void cifs_add_credits(struct TCP_Server_Info *server,
92 const unsigned int add);
93extern void cifs_set_credits(struct TCP_Server_Info *server, const int val);
94extern int checkSMB(char *buf, unsigned int length); 93extern int checkSMB(char *buf, unsigned int length);
95extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); 94extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
96extern bool backup_cred(struct cifs_sb_info *); 95extern bool backup_cred(struct cifs_sb_info *);
@@ -192,11 +191,13 @@ extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses,
192 191
193extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, 192extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
194 const char *searchName, const struct nls_table *nls_codepage, 193 const char *searchName, const struct nls_table *nls_codepage,
195 __u16 *searchHandle, struct cifs_search_info *psrch_inf, 194 __u16 *searchHandle, __u16 search_flags,
195 struct cifs_search_info *psrch_inf,
196 int map, const char dirsep); 196 int map, const char dirsep);
197 197
198extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, 198extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
199 __u16 searchHandle, struct cifs_search_info *psrch_inf); 199 __u16 searchHandle, __u16 search_flags,
200 struct cifs_search_info *psrch_inf);
200 201
201extern int CIFSFindClose(const int, struct cifs_tcon *tcon, 202extern int CIFSFindClose(const int, struct cifs_tcon *tcon,
202 const __u16 search_handle); 203 const __u16 search_handle);
@@ -464,6 +465,9 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
464 465
465/* asynchronous read support */ 466/* asynchronous read support */
466struct cifs_readdata { 467struct cifs_readdata {
468 struct kref refcount;
469 struct list_head list;
470 struct completion done;
467 struct cifsFileInfo *cfile; 471 struct cifsFileInfo *cfile;
468 struct address_space *mapping; 472 struct address_space *mapping;
469 __u64 offset; 473 __u64 offset;
@@ -472,12 +476,13 @@ struct cifs_readdata {
472 int result; 476 int result;
473 struct list_head pages; 477 struct list_head pages;
474 struct work_struct work; 478 struct work_struct work;
479 int (*marshal_iov) (struct cifs_readdata *rdata,
480 unsigned int remaining);
475 unsigned int nr_iov; 481 unsigned int nr_iov;
476 struct kvec iov[1]; 482 struct kvec iov[1];
477}; 483};
478 484
479struct cifs_readdata *cifs_readdata_alloc(unsigned int nr_pages); 485void cifs_readdata_release(struct kref *refcount);
480void cifs_readdata_free(struct cifs_readdata *rdata);
481int cifs_async_readv(struct cifs_readdata *rdata); 486int cifs_async_readv(struct cifs_readdata *rdata);
482 487
483/* asynchronous write support */ 488/* asynchronous write support */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index da2f5446fa7a..b5ad716b2642 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -87,7 +87,6 @@ static struct {
87#endif /* CIFS_POSIX */ 87#endif /* CIFS_POSIX */
88 88
89/* Forward declarations */ 89/* Forward declarations */
90static void cifs_readv_complete(struct work_struct *work);
91 90
92/* Mark as invalid, all open files on tree connections since they 91/* Mark as invalid, all open files on tree connections since they
93 were closed when session to server was lost */ 92 were closed when session to server was lost */
@@ -461,7 +460,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
461 server->maxReq = min_t(unsigned int, 460 server->maxReq = min_t(unsigned int,
462 le16_to_cpu(rsp->MaxMpxCount), 461 le16_to_cpu(rsp->MaxMpxCount),
463 cifs_max_pending); 462 cifs_max_pending);
464 cifs_set_credits(server, server->maxReq); 463 set_credits(server, server->maxReq);
465 server->maxBuf = le16_to_cpu(rsp->MaxBufSize); 464 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
466 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 465 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
467 /* even though we do not use raw we might as well set this 466 /* even though we do not use raw we might as well set this
@@ -569,7 +568,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
569 little endian */ 568 little endian */
570 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), 569 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
571 cifs_max_pending); 570 cifs_max_pending);
572 cifs_set_credits(server, server->maxReq); 571 set_credits(server, server->maxReq);
573 /* probably no need to store and check maxvcs */ 572 /* probably no need to store and check maxvcs */
574 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); 573 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
575 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 574 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
@@ -721,7 +720,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
721 struct TCP_Server_Info *server = mid->callback_data; 720 struct TCP_Server_Info *server = mid->callback_data;
722 721
723 DeleteMidQEntry(mid); 722 DeleteMidQEntry(mid);
724 cifs_add_credits(server, 1); 723 add_credits(server, 1);
725} 724}
726 725
727int 726int
@@ -1385,28 +1384,6 @@ openRetry:
1385 return rc; 1384 return rc;
1386} 1385}
1387 1386
1388struct cifs_readdata *
1389cifs_readdata_alloc(unsigned int nr_pages)
1390{
1391 struct cifs_readdata *rdata;
1392
1393 /* readdata + 1 kvec for each page */
1394 rdata = kzalloc(sizeof(*rdata) +
1395 sizeof(struct kvec) * nr_pages, GFP_KERNEL);
1396 if (rdata != NULL) {
1397 INIT_WORK(&rdata->work, cifs_readv_complete);
1398 INIT_LIST_HEAD(&rdata->pages);
1399 }
1400 return rdata;
1401}
1402
1403void
1404cifs_readdata_free(struct cifs_readdata *rdata)
1405{
1406 cifsFileInfo_put(rdata->cfile);
1407 kfree(rdata);
1408}
1409
1410/* 1387/*
1411 * Discard any remaining data in the current SMB. To do this, we borrow the 1388 * Discard any remaining data in the current SMB. To do this, we borrow the
1412 * current bigbuf. 1389 * current bigbuf.
@@ -1423,7 +1400,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1423 1400
1424 length = cifs_read_from_socket(server, server->bigbuf, 1401 length = cifs_read_from_socket(server, server->bigbuf,
1425 min_t(unsigned int, remaining, 1402 min_t(unsigned int, remaining,
1426 CIFSMaxBufSize + max_header_size())); 1403 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1427 if (length < 0) 1404 if (length < 0)
1428 return length; 1405 return length;
1429 server->total_read += length; 1406 server->total_read += length;
@@ -1434,38 +1411,14 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1434 return 0; 1411 return 0;
1435} 1412}
1436 1413
1437static inline size_t
1438read_rsp_size(void)
1439{
1440 return sizeof(READ_RSP);
1441}
1442
1443static inline unsigned int
1444read_data_offset(char *buf)
1445{
1446 READ_RSP *rsp = (READ_RSP *)buf;
1447 return le16_to_cpu(rsp->DataOffset);
1448}
1449
1450static inline unsigned int
1451read_data_length(char *buf)
1452{
1453 READ_RSP *rsp = (READ_RSP *)buf;
1454 return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
1455 le16_to_cpu(rsp->DataLength);
1456}
1457
1458static int 1414static int
1459cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1415cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1460{ 1416{
1461 int length, len; 1417 int length, len;
1462 unsigned int data_offset, remaining, data_len; 1418 unsigned int data_offset, data_len;
1463 struct cifs_readdata *rdata = mid->callback_data; 1419 struct cifs_readdata *rdata = mid->callback_data;
1464 char *buf = server->smallbuf; 1420 char *buf = server->smallbuf;
1465 unsigned int buflen = get_rfc1002_length(buf) + 4; 1421 unsigned int buflen = get_rfc1002_length(buf) + 4;
1466 u64 eof;
1467 pgoff_t eof_index;
1468 struct page *page, *tpage;
1469 1422
1470 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__, 1423 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1471 mid->mid, rdata->offset, rdata->bytes); 1424 mid->mid, rdata->offset, rdata->bytes);
@@ -1475,9 +1428,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1475 * can if there's not enough data. At this point, we've read down to 1428 * can if there's not enough data. At this point, we've read down to
1476 * the Mid. 1429 * the Mid.
1477 */ 1430 */
1478 len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1; 1431 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1432 HEADER_SIZE(server) + 1;
1479 1433
1480 rdata->iov[0].iov_base = buf + header_size() - 1; 1434 rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1481 rdata->iov[0].iov_len = len; 1435 rdata->iov[0].iov_len = len;
1482 1436
1483 length = cifs_readv_from_socket(server, rdata->iov, 1, len); 1437 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
@@ -1486,7 +1440,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1486 server->total_read += length; 1440 server->total_read += length;
1487 1441
1488 /* Was the SMB read successful? */ 1442 /* Was the SMB read successful? */
1489 rdata->result = map_smb_to_linux_error(buf, false); 1443 rdata->result = server->ops->map_error(buf, false);
1490 if (rdata->result != 0) { 1444 if (rdata->result != 0) {
1491 cFYI(1, "%s: server returned error %d", __func__, 1445 cFYI(1, "%s: server returned error %d", __func__,
1492 rdata->result); 1446 rdata->result);
@@ -1494,14 +1448,15 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1494 } 1448 }
1495 1449
1496 /* Is there enough to get to the rest of the READ_RSP header? */ 1450 /* Is there enough to get to the rest of the READ_RSP header? */
1497 if (server->total_read < read_rsp_size()) { 1451 if (server->total_read < server->vals->read_rsp_size) {
1498 cFYI(1, "%s: server returned short header. got=%u expected=%zu", 1452 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1499 __func__, server->total_read, read_rsp_size()); 1453 __func__, server->total_read,
1454 server->vals->read_rsp_size);
1500 rdata->result = -EIO; 1455 rdata->result = -EIO;
1501 return cifs_readv_discard(server, mid); 1456 return cifs_readv_discard(server, mid);
1502 } 1457 }
1503 1458
1504 data_offset = read_data_offset(buf) + 4; 1459 data_offset = server->ops->read_data_offset(buf) + 4;
1505 if (data_offset < server->total_read) { 1460 if (data_offset < server->total_read) {
1506 /* 1461 /*
1507 * win2k8 sometimes sends an offset of 0 when the read 1462 * win2k8 sometimes sends an offset of 0 when the read
@@ -1540,7 +1495,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1540 rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1495 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1541 1496
1542 /* how much data is in the response? */ 1497 /* how much data is in the response? */
1543 data_len = read_data_length(buf); 1498 data_len = server->ops->read_data_length(buf);
1544 if (data_offset + data_len > buflen) { 1499 if (data_offset + data_len > buflen) {
1545 /* data_len is corrupt -- discard frame */ 1500 /* data_len is corrupt -- discard frame */
1546 rdata->result = -EIO; 1501 rdata->result = -EIO;
@@ -1548,64 +1503,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1548 } 1503 }
1549 1504
1550 /* marshal up the page array */ 1505 /* marshal up the page array */
1551 len = 0; 1506 len = rdata->marshal_iov(rdata, data_len);
1552 remaining = data_len; 1507 data_len -= len;
1553 rdata->nr_iov = 1;
1554
1555 /* determine the eof that the server (probably) has */
1556 eof = CIFS_I(rdata->mapping->host)->server_eof;
1557 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
1558 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
1559
1560 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1561 if (remaining >= PAGE_CACHE_SIZE) {
1562 /* enough data to fill the page */
1563 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1564 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
1565 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1566 rdata->nr_iov, page->index,
1567 rdata->iov[rdata->nr_iov].iov_base,
1568 rdata->iov[rdata->nr_iov].iov_len);
1569 ++rdata->nr_iov;
1570 len += PAGE_CACHE_SIZE;
1571 remaining -= PAGE_CACHE_SIZE;
1572 } else if (remaining > 0) {
1573 /* enough for partial page, fill and zero the rest */
1574 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1575 rdata->iov[rdata->nr_iov].iov_len = remaining;
1576 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1577 rdata->nr_iov, page->index,
1578 rdata->iov[rdata->nr_iov].iov_base,
1579 rdata->iov[rdata->nr_iov].iov_len);
1580 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
1581 '\0', PAGE_CACHE_SIZE - remaining);
1582 ++rdata->nr_iov;
1583 len += remaining;
1584 remaining = 0;
1585 } else if (page->index > eof_index) {
1586 /*
1587 * The VFS will not try to do readahead past the
1588 * i_size, but it's possible that we have outstanding
1589 * writes with gaps in the middle and the i_size hasn't
1590 * caught up yet. Populate those with zeroed out pages
1591 * to prevent the VFS from repeatedly attempting to
1592 * fill them until the writes are flushed.
1593 */
1594 zero_user(page, 0, PAGE_CACHE_SIZE);
1595 list_del(&page->lru);
1596 lru_cache_add_file(page);
1597 flush_dcache_page(page);
1598 SetPageUptodate(page);
1599 unlock_page(page);
1600 page_cache_release(page);
1601 } else {
1602 /* no need to hold page hostage */
1603 list_del(&page->lru);
1604 lru_cache_add_file(page);
1605 unlock_page(page);
1606 page_cache_release(page);
1607 }
1608 }
1609 1508
1610 /* issue the read if we have any iovecs left to fill */ 1509 /* issue the read if we have any iovecs left to fill */
1611 if (rdata->nr_iov > 1) { 1510 if (rdata->nr_iov > 1) {
@@ -1621,7 +1520,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1621 rdata->bytes = length; 1520 rdata->bytes = length;
1622 1521
1623 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, 1522 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1624 buflen, remaining); 1523 buflen, data_len);
1625 1524
1626 /* discard anything left over */ 1525 /* discard anything left over */
1627 if (server->total_read < buflen) 1526 if (server->total_read < buflen)
@@ -1632,33 +1531,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1632} 1531}
1633 1532
1634static void 1533static void
1635cifs_readv_complete(struct work_struct *work)
1636{
1637 struct cifs_readdata *rdata = container_of(work,
1638 struct cifs_readdata, work);
1639 struct page *page, *tpage;
1640
1641 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1642 list_del(&page->lru);
1643 lru_cache_add_file(page);
1644
1645 if (rdata->result == 0) {
1646 kunmap(page);
1647 flush_dcache_page(page);
1648 SetPageUptodate(page);
1649 }
1650
1651 unlock_page(page);
1652
1653 if (rdata->result == 0)
1654 cifs_readpage_to_fscache(rdata->mapping->host, page);
1655
1656 page_cache_release(page);
1657 }
1658 cifs_readdata_free(rdata);
1659}
1660
1661static void
1662cifs_readv_callback(struct mid_q_entry *mid) 1534cifs_readv_callback(struct mid_q_entry *mid)
1663{ 1535{
1664 struct cifs_readdata *rdata = mid->callback_data; 1536 struct cifs_readdata *rdata = mid->callback_data;
@@ -1691,7 +1563,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
1691 1563
1692 queue_work(cifsiod_wq, &rdata->work); 1564 queue_work(cifsiod_wq, &rdata->work);
1693 DeleteMidQEntry(mid); 1565 DeleteMidQEntry(mid);
1694 cifs_add_credits(server, 1); 1566 add_credits(server, 1);
1695} 1567}
1696 1568
1697/* cifs_async_readv - send an async write, and set up mid to handle result */ 1569/* cifs_async_readv - send an async write, and set up mid to handle result */
@@ -1744,12 +1616,15 @@ cifs_async_readv(struct cifs_readdata *rdata)
1744 rdata->iov[0].iov_base = smb; 1616 rdata->iov[0].iov_base = smb;
1745 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; 1617 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1746 1618
1619 kref_get(&rdata->refcount);
1747 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, 1620 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1748 cifs_readv_receive, cifs_readv_callback, 1621 cifs_readv_receive, cifs_readv_callback,
1749 rdata, false); 1622 rdata, false);
1750 1623
1751 if (rc == 0) 1624 if (rc == 0)
1752 cifs_stats_inc(&tcon->num_reads); 1625 cifs_stats_inc(&tcon->num_reads);
1626 else
1627 kref_put(&rdata->refcount, cifs_readdata_release);
1753 1628
1754 cifs_small_buf_release(smb); 1629 cifs_small_buf_release(smb);
1755 return rc; 1630 return rc;
@@ -2135,7 +2010,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
2135 2010
2136 queue_work(cifsiod_wq, &wdata->work); 2011 queue_work(cifsiod_wq, &wdata->work);
2137 DeleteMidQEntry(mid); 2012 DeleteMidQEntry(mid);
2138 cifs_add_credits(tcon->ses->server, 1); 2013 add_credits(tcon->ses->server, 1);
2139} 2014}
2140 2015
2141/* cifs_async_writev - send an async write, and set up mid to handle result */ 2016/* cifs_async_writev - send an async write, and set up mid to handle result */
@@ -4344,7 +4219,7 @@ int
4344CIFSFindFirst(const int xid, struct cifs_tcon *tcon, 4219CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4345 const char *searchName, 4220 const char *searchName,
4346 const struct nls_table *nls_codepage, 4221 const struct nls_table *nls_codepage,
4347 __u16 *pnetfid, 4222 __u16 *pnetfid, __u16 search_flags,
4348 struct cifs_search_info *psrch_inf, int remap, const char dirsep) 4223 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4349{ 4224{
4350/* level 257 SMB_ */ 4225/* level 257 SMB_ */
@@ -4416,8 +4291,7 @@ findFirstRetry:
4416 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | 4291 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4417 ATTR_DIRECTORY); 4292 ATTR_DIRECTORY);
4418 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); 4293 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4419 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | 4294 pSMB->SearchFlags = cpu_to_le16(search_flags);
4420 CIFS_SEARCH_RETURN_RESUME);
4421 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); 4295 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4422 4296
4423 /* BB what should we set StorageType to? Does it matter? BB */ 4297 /* BB what should we set StorageType to? Does it matter? BB */
@@ -4487,8 +4361,8 @@ findFirstRetry:
4487 return rc; 4361 return rc;
4488} 4362}
4489 4363
4490int CIFSFindNext(const int xid, struct cifs_tcon *tcon, 4364int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4491 __u16 searchHandle, struct cifs_search_info *psrch_inf) 4365 __u16 search_flags, struct cifs_search_info *psrch_inf)
4492{ 4366{
4493 TRANSACTION2_FNEXT_REQ *pSMB = NULL; 4367 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4494 TRANSACTION2_FNEXT_RSP *pSMBr = NULL; 4368 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
@@ -4531,8 +4405,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
4531 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); 4405 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4532 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); 4406 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4533 pSMB->ResumeKey = psrch_inf->resume_key; 4407 pSMB->ResumeKey = psrch_inf->resume_key;
4534 pSMB->SearchFlags = 4408 pSMB->SearchFlags = cpu_to_le16(search_flags);
4535 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4536 4409
4537 name_len = psrch_inf->resume_name_len; 4410 name_len = psrch_inf->resume_name_len;
4538 params += name_len; 4411 params += name_len;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e0b56d7a19c5..ccafdedd0dbc 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/connect.c 2 * fs/cifs/connect.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2009 4 * Copyright (C) International Business Machines Corp., 2002,2011
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -102,7 +102,7 @@ enum {
102 Opt_srcaddr, Opt_prefixpath, 102 Opt_srcaddr, Opt_prefixpath,
103 Opt_iocharset, Opt_sockopt, 103 Opt_iocharset, Opt_sockopt,
104 Opt_netbiosname, Opt_servern, 104 Opt_netbiosname, Opt_servern,
105 Opt_ver, Opt_sec, 105 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
106 106
107 /* Mount options to be ignored */ 107 /* Mount options to be ignored */
108 Opt_ignore, 108 Opt_ignore,
@@ -210,9 +210,9 @@ static const match_table_t cifs_mount_option_tokens = {
210 { Opt_netbiosname, "netbiosname=%s" }, 210 { Opt_netbiosname, "netbiosname=%s" },
211 { Opt_servern, "servern=%s" }, 211 { Opt_servern, "servern=%s" },
212 { Opt_ver, "ver=%s" }, 212 { Opt_ver, "ver=%s" },
213 { Opt_ver, "vers=%s" }, 213 { Opt_vers, "vers=%s" },
214 { Opt_ver, "version=%s" },
215 { Opt_sec, "sec=%s" }, 214 { Opt_sec, "sec=%s" },
215 { Opt_cache, "cache=%s" },
216 216
217 { Opt_ignore, "cred" }, 217 { Opt_ignore, "cred" },
218 { Opt_ignore, "credentials" }, 218 { Opt_ignore, "credentials" },
@@ -261,6 +261,26 @@ static const match_table_t cifs_secflavor_tokens = {
261 { Opt_sec_err, NULL } 261 { Opt_sec_err, NULL }
262}; 262};
263 263
264/* cache flavors */
265enum {
266 Opt_cache_loose,
267 Opt_cache_strict,
268 Opt_cache_none,
269 Opt_cache_err
270};
271
272static const match_table_t cifs_cacheflavor_tokens = {
273 { Opt_cache_loose, "loose" },
274 { Opt_cache_strict, "strict" },
275 { Opt_cache_none, "none" },
276 { Opt_cache_err, NULL }
277};
278
279static const match_table_t cifs_smb_version_tokens = {
280 { Smb_1, SMB1_VERSION_STRING },
281 { Smb_21, SMB21_VERSION_STRING },
282};
283
264static int ip_connect(struct TCP_Server_Info *server); 284static int ip_connect(struct TCP_Server_Info *server);
265static int generic_ip_connect(struct TCP_Server_Info *server); 285static int generic_ip_connect(struct TCP_Server_Info *server);
266static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); 286static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
@@ -549,7 +569,7 @@ allocate_buffers(struct TCP_Server_Info *server)
549 } 569 }
550 } else if (server->large_buf) { 570 } else if (server->large_buf) {
551 /* we are reusing a dirty large buf, clear its start */ 571 /* we are reusing a dirty large buf, clear its start */
552 memset(server->bigbuf, 0, header_size()); 572 memset(server->bigbuf, 0, HEADER_SIZE(server));
553 } 573 }
554 574
555 if (!server->smallbuf) { 575 if (!server->smallbuf) {
@@ -563,7 +583,7 @@ allocate_buffers(struct TCP_Server_Info *server)
563 /* beginning of smb buffer is cleared in our buf_get */ 583 /* beginning of smb buffer is cleared in our buf_get */
564 } else { 584 } else {
565 /* if existing small buf clear beginning */ 585 /* if existing small buf clear beginning */
566 memset(server->smallbuf, 0, header_size()); 586 memset(server->smallbuf, 0, HEADER_SIZE(server));
567 } 587 }
568 588
569 return true; 589 return true;
@@ -764,25 +784,6 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
764 return false; 784 return false;
765} 785}
766 786
767static struct mid_q_entry *
768find_mid(struct TCP_Server_Info *server, char *buffer)
769{
770 struct smb_hdr *buf = (struct smb_hdr *)buffer;
771 struct mid_q_entry *mid;
772
773 spin_lock(&GlobalMid_Lock);
774 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
775 if (mid->mid == buf->Mid &&
776 mid->mid_state == MID_REQUEST_SUBMITTED &&
777 le16_to_cpu(mid->command) == buf->Command) {
778 spin_unlock(&GlobalMid_Lock);
779 return mid;
780 }
781 }
782 spin_unlock(&GlobalMid_Lock);
783 return NULL;
784}
785
786void 787void
787dequeue_mid(struct mid_q_entry *mid, bool malformed) 788dequeue_mid(struct mid_q_entry *mid, bool malformed)
788{ 789{
@@ -934,7 +935,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
934 unsigned int pdu_length = get_rfc1002_length(buf); 935 unsigned int pdu_length = get_rfc1002_length(buf);
935 936
936 /* make sure this will fit in a large buffer */ 937 /* make sure this will fit in a large buffer */
937 if (pdu_length > CIFSMaxBufSize + max_header_size() - 4) { 938 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
938 cERROR(1, "SMB response too long (%u bytes)", 939 cERROR(1, "SMB response too long (%u bytes)",
939 pdu_length); 940 pdu_length);
940 cifs_reconnect(server); 941 cifs_reconnect(server);
@@ -950,8 +951,8 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
950 } 951 }
951 952
952 /* now read the rest */ 953 /* now read the rest */
953 length = cifs_read_from_socket(server, buf + header_size() - 1, 954 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
954 pdu_length - header_size() + 1 + 4); 955 pdu_length - HEADER_SIZE(server) + 1 + 4);
955 if (length < 0) 956 if (length < 0)
956 return length; 957 return length;
957 server->total_read += length; 958 server->total_read += length;
@@ -967,7 +968,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
967 * 48 bytes is enough to display the header and a little bit 968 * 48 bytes is enough to display the header and a little bit
968 * into the payload for debugging purposes. 969 * into the payload for debugging purposes.
969 */ 970 */
970 length = checkSMB(buf, server->total_read); 971 length = server->ops->check_message(buf, server->total_read);
971 if (length != 0) 972 if (length != 0)
972 cifs_dump_mem("Bad SMB: ", buf, 973 cifs_dump_mem("Bad SMB: ", buf,
973 min_t(unsigned int, server->total_read, 48)); 974 min_t(unsigned int, server->total_read, 48));
@@ -1025,7 +1026,7 @@ cifs_demultiplex_thread(void *p)
1025 continue; 1026 continue;
1026 1027
1027 /* make sure we have enough to get to the MID */ 1028 /* make sure we have enough to get to the MID */
1028 if (pdu_length < header_size() - 1 - 4) { 1029 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
1029 cERROR(1, "SMB response too short (%u bytes)", 1030 cERROR(1, "SMB response too short (%u bytes)",
1030 pdu_length); 1031 pdu_length);
1031 cifs_reconnect(server); 1032 cifs_reconnect(server);
@@ -1035,12 +1036,12 @@ cifs_demultiplex_thread(void *p)
1035 1036
1036 /* read down to the MID */ 1037 /* read down to the MID */
1037 length = cifs_read_from_socket(server, buf + 4, 1038 length = cifs_read_from_socket(server, buf + 4,
1038 header_size() - 1 - 4); 1039 HEADER_SIZE(server) - 1 - 4);
1039 if (length < 0) 1040 if (length < 0)
1040 continue; 1041 continue;
1041 server->total_read += length; 1042 server->total_read += length;
1042 1043
1043 mid_entry = find_mid(server, buf); 1044 mid_entry = server->ops->find_mid(server, buf);
1044 1045
1045 if (!mid_entry || !mid_entry->receive) 1046 if (!mid_entry || !mid_entry->receive)
1046 length = standard_receive3(server, mid_entry); 1047 length = standard_receive3(server, mid_entry);
@@ -1057,12 +1058,13 @@ cifs_demultiplex_thread(void *p)
1057 if (mid_entry != NULL) { 1058 if (mid_entry != NULL) {
1058 if (!mid_entry->multiRsp || mid_entry->multiEnd) 1059 if (!mid_entry->multiRsp || mid_entry->multiEnd)
1059 mid_entry->callback(mid_entry); 1060 mid_entry->callback(mid_entry);
1060 } else if (!is_valid_oplock_break(buf, server)) { 1061 } else if (!server->ops->is_oplock_break(buf, server)) {
1061 cERROR(1, "No task to wake, unknown frame received! " 1062 cERROR(1, "No task to wake, unknown frame received! "
1062 "NumMids %d", atomic_read(&midCount)); 1063 "NumMids %d", atomic_read(&midCount));
1063 cifs_dump_mem("Received Data is: ", buf, header_size()); 1064 cifs_dump_mem("Received Data is: ", buf,
1065 HEADER_SIZE(server));
1064#ifdef CONFIG_CIFS_DEBUG2 1066#ifdef CONFIG_CIFS_DEBUG2
1065 cifs_dump_detail(buf); 1067 server->ops->dump_detail(buf);
1066 cifs_dump_mids(server); 1068 cifs_dump_mids(server);
1067#endif /* CIFS_DEBUG2 */ 1069#endif /* CIFS_DEBUG2 */
1068 1070
@@ -1186,6 +1188,54 @@ static int cifs_parse_security_flavors(char *value,
1186} 1188}
1187 1189
1188static int 1190static int
1191cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1192{
1193 substring_t args[MAX_OPT_ARGS];
1194
1195 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1196 case Opt_cache_loose:
1197 vol->direct_io = false;
1198 vol->strict_io = false;
1199 break;
1200 case Opt_cache_strict:
1201 vol->direct_io = false;
1202 vol->strict_io = true;
1203 break;
1204 case Opt_cache_none:
1205 vol->direct_io = true;
1206 vol->strict_io = false;
1207 break;
1208 default:
1209 cERROR(1, "bad cache= option: %s", value);
1210 return 1;
1211 }
1212 return 0;
1213}
1214
1215static int
1216cifs_parse_smb_version(char *value, struct smb_vol *vol)
1217{
1218 substring_t args[MAX_OPT_ARGS];
1219
1220 switch (match_token(value, cifs_smb_version_tokens, args)) {
1221 case Smb_1:
1222 vol->ops = &smb1_operations;
1223 vol->vals = &smb1_values;
1224 break;
1225#ifdef CONFIG_CIFS_SMB2
1226 case Smb_21:
1227 vol->ops = &smb21_operations;
1228 vol->vals = &smb21_values;
1229 break;
1230#endif
1231 default:
1232 cERROR(1, "Unknown vers= option specified: %s", value);
1233 return 1;
1234 }
1235 return 0;
1236}
1237
1238static int
1189cifs_parse_mount_options(const char *mountdata, const char *devname, 1239cifs_parse_mount_options(const char *mountdata, const char *devname,
1190 struct smb_vol *vol) 1240 struct smb_vol *vol)
1191{ 1241{
@@ -1203,6 +1253,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1203 char *string = NULL; 1253 char *string = NULL;
1204 char *tmp_end, *value; 1254 char *tmp_end, *value;
1205 char delim; 1255 char delim;
1256 bool cache_specified = false;
1257 static bool cache_warned = false;
1206 1258
1207 separator[0] = ','; 1259 separator[0] = ',';
1208 separator[1] = 0; 1260 separator[1] = 0;
@@ -1236,6 +1288,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1236 1288
1237 vol->actimeo = CIFS_DEF_ACTIMEO; 1289 vol->actimeo = CIFS_DEF_ACTIMEO;
1238 1290
1291 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1292 vol->ops = &smb1_operations;
1293 vol->vals = &smb1_values;
1294
1239 if (!mountdata) 1295 if (!mountdata)
1240 goto cifs_parse_mount_err; 1296 goto cifs_parse_mount_err;
1241 1297
@@ -1414,10 +1470,20 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1414 vol->seal = 1; 1470 vol->seal = 1;
1415 break; 1471 break;
1416 case Opt_direct: 1472 case Opt_direct:
1417 vol->direct_io = 1; 1473 cache_specified = true;
1474 vol->direct_io = true;
1475 vol->strict_io = false;
1476 cERROR(1, "The \"directio\" option will be removed in "
1477 "3.7. Please switch to the \"cache=none\" "
1478 "option.");
1418 break; 1479 break;
1419 case Opt_strictcache: 1480 case Opt_strictcache:
1420 vol->strict_io = 1; 1481 cache_specified = true;
1482 vol->direct_io = false;
1483 vol->strict_io = true;
1484 cERROR(1, "The \"strictcache\" option will be removed "
1485 "in 3.7. Please switch to the \"cache=strict\" "
1486 "option.");
1421 break; 1487 break;
1422 case Opt_noac: 1488 case Opt_noac:
1423 printk(KERN_WARNING "CIFS: Mount option noac not " 1489 printk(KERN_WARNING "CIFS: Mount option noac not "
@@ -1821,8 +1887,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1821 if (string == NULL) 1887 if (string == NULL)
1822 goto out_nomem; 1888 goto out_nomem;
1823 1889
1824 if (strnicmp(string, "cifs", 4) == 0 || 1890 if (strnicmp(string, "1", 1) == 0) {
1825 strnicmp(string, "1", 1) == 0) {
1826 /* This is the default */ 1891 /* This is the default */
1827 break; 1892 break;
1828 } 1893 }
@@ -1830,6 +1895,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1830 printk(KERN_WARNING "CIFS: Invalid version" 1895 printk(KERN_WARNING "CIFS: Invalid version"
1831 " specified\n"); 1896 " specified\n");
1832 goto cifs_parse_mount_err; 1897 goto cifs_parse_mount_err;
1898 case Opt_vers:
1899 string = match_strdup(args);
1900 if (string == NULL)
1901 goto out_nomem;
1902
1903 if (cifs_parse_smb_version(string, vol) != 0)
1904 goto cifs_parse_mount_err;
1905 break;
1833 case Opt_sec: 1906 case Opt_sec:
1834 string = match_strdup(args); 1907 string = match_strdup(args);
1835 if (string == NULL) 1908 if (string == NULL)
@@ -1838,6 +1911,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1838 if (cifs_parse_security_flavors(string, vol) != 0) 1911 if (cifs_parse_security_flavors(string, vol) != 0)
1839 goto cifs_parse_mount_err; 1912 goto cifs_parse_mount_err;
1840 break; 1913 break;
1914 case Opt_cache:
1915 cache_specified = true;
1916 string = match_strdup(args);
1917 if (string == NULL)
1918 goto out_nomem;
1919
1920 if (cifs_parse_cache_flavor(string, vol) != 0)
1921 goto cifs_parse_mount_err;
1922 break;
1841 default: 1923 default:
1842 /* 1924 /*
1843 * An option we don't recognize. Save it off for later 1925 * An option we don't recognize. Save it off for later
@@ -1881,6 +1963,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1881 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " 1963 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1882 "specified with no gid= option.\n"); 1964 "specified with no gid= option.\n");
1883 1965
1966 /* FIXME: remove this block in 3.7 */
1967 if (!cache_specified && !cache_warned) {
1968 cache_warned = true;
1969 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1970 "\"cache=loose\". This default will change "
1971 "to \"cache=strict\" in 3.7.\n");
1972 }
1973
1884 kfree(mountdata_copy); 1974 kfree(mountdata_copy);
1885 return 0; 1975 return 0;
1886 1976
@@ -2041,6 +2131,9 @@ match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2041static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr, 2131static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2042 struct smb_vol *vol) 2132 struct smb_vol *vol)
2043{ 2133{
2134 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2135 return 0;
2136
2044 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) 2137 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2045 return 0; 2138 return 0;
2046 2139
@@ -2163,6 +2256,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
2163 goto out_err; 2256 goto out_err;
2164 } 2257 }
2165 2258
2259 tcp_ses->ops = volume_info->ops;
2260 tcp_ses->vals = volume_info->vals;
2166 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); 2261 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2167 tcp_ses->hostname = extract_hostname(volume_info->UNC); 2262 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2168 if (IS_ERR(tcp_ses->hostname)) { 2263 if (IS_ERR(tcp_ses->hostname)) {
@@ -3569,6 +3664,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3569 if (cifs_parse_mount_options(mount_data, devname, volume_info)) 3664 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3570 return -EINVAL; 3665 return -EINVAL;
3571 3666
3667
3572 if (volume_info->nullauth) { 3668 if (volume_info->nullauth) {
3573 cFYI(1, "Anonymous login"); 3669 cFYI(1, "Anonymous login");
3574 kfree(volume_info->username); 3670 kfree(volume_info->username);
@@ -4010,11 +4106,11 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
4010 if (server->maxBuf != 0) 4106 if (server->maxBuf != 0)
4011 return 0; 4107 return 0;
4012 4108
4013 cifs_set_credits(server, 1); 4109 set_credits(server, 1);
4014 rc = CIFSSMBNegotiate(xid, ses); 4110 rc = CIFSSMBNegotiate(xid, ses);
4015 if (rc == -EAGAIN) { 4111 if (rc == -EAGAIN) {
4016 /* retry only once on 1st time connection */ 4112 /* retry only once on 1st time connection */
4017 cifs_set_credits(server, 1); 4113 set_credits(server, 1);
4018 rc = CIFSSMBNegotiate(xid, ses); 4114 rc = CIFSSMBNegotiate(xid, ses);
4019 if (rc == -EAGAIN) 4115 if (rc == -EAGAIN)
4020 rc = -EHOSTDOWN; 4116 rc = -EHOSTDOWN;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 81725e9286e9..253170dfa716 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -264,6 +264,7 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
264 pCifsFile->tlink = cifs_get_tlink(tlink); 264 pCifsFile->tlink = cifs_get_tlink(tlink);
265 mutex_init(&pCifsFile->fh_mutex); 265 mutex_init(&pCifsFile->fh_mutex);
266 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); 266 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
267 INIT_LIST_HEAD(&pCifsFile->llist);
267 268
268 spin_lock(&cifs_file_list_lock); 269 spin_lock(&cifs_file_list_lock);
269 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); 270 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
@@ -334,9 +335,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
334 * is closed anyway. 335 * is closed anyway.
335 */ 336 */
336 mutex_lock(&cifsi->lock_mutex); 337 mutex_lock(&cifsi->lock_mutex);
337 list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) { 338 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
338 if (li->netfid != cifs_file->netfid)
339 continue;
340 list_del(&li->llist); 339 list_del(&li->llist);
341 cifs_del_lock_waiters(li); 340 cifs_del_lock_waiters(li);
342 kfree(li); 341 kfree(li);
@@ -645,7 +644,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
645} 644}
646 645
647static struct cifsLockInfo * 646static struct cifsLockInfo *
648cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) 647cifs_lock_init(__u64 offset, __u64 length, __u8 type)
649{ 648{
650 struct cifsLockInfo *lock = 649 struct cifsLockInfo *lock =
651 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); 650 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
@@ -654,7 +653,6 @@ cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid)
654 lock->offset = offset; 653 lock->offset = offset;
655 lock->length = length; 654 lock->length = length;
656 lock->type = type; 655 lock->type = type;
657 lock->netfid = netfid;
658 lock->pid = current->tgid; 656 lock->pid = current->tgid;
659 INIT_LIST_HEAD(&lock->blist); 657 INIT_LIST_HEAD(&lock->blist);
660 init_waitqueue_head(&lock->block_q); 658 init_waitqueue_head(&lock->block_q);
@@ -672,19 +670,20 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock)
672} 670}
673 671
674static bool 672static bool
675__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, 673cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
676 __u64 length, __u8 type, __u16 netfid, 674 __u64 length, __u8 type, struct cifsFileInfo *cur,
677 struct cifsLockInfo **conf_lock) 675 struct cifsLockInfo **conf_lock)
678{ 676{
679 struct cifsLockInfo *li, *tmp; 677 struct cifsLockInfo *li;
678 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
680 679
681 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { 680 list_for_each_entry(li, &cfile->llist, llist) {
682 if (offset + length <= li->offset || 681 if (offset + length <= li->offset ||
683 offset >= li->offset + li->length) 682 offset >= li->offset + li->length)
684 continue; 683 continue;
685 else if ((type & LOCKING_ANDX_SHARED_LOCK) && 684 else if ((type & server->vals->shared_lock_type) &&
686 ((netfid == li->netfid && current->tgid == li->pid) || 685 ((server->ops->compare_fids(cur, cfile) &&
687 type == li->type)) 686 current->tgid == li->pid) || type == li->type))
688 continue; 687 continue;
689 else { 688 else {
690 *conf_lock = li; 689 *conf_lock = li;
@@ -695,11 +694,23 @@ __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
695} 694}
696 695
697static bool 696static bool
698cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, 697cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
699 struct cifsLockInfo **conf_lock) 698 __u8 type, struct cifsLockInfo **conf_lock)
700{ 699{
701 return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, 700 bool rc = false;
702 lock->type, lock->netfid, conf_lock); 701 struct cifsFileInfo *fid, *tmp;
702 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
703
704 spin_lock(&cifs_file_list_lock);
705 list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) {
706 rc = cifs_find_fid_lock_conflict(fid, offset, length, type,
707 cfile, conf_lock);
708 if (rc)
709 break;
710 }
711 spin_unlock(&cifs_file_list_lock);
712
713 return rc;
703} 714}
704 715
705/* 716/*
@@ -710,22 +721,24 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
710 * the server or 1 otherwise. 721 * the server or 1 otherwise.
711 */ 722 */
712static int 723static int
713cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, 724cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
714 __u8 type, __u16 netfid, struct file_lock *flock) 725 __u8 type, struct file_lock *flock)
715{ 726{
716 int rc = 0; 727 int rc = 0;
717 struct cifsLockInfo *conf_lock; 728 struct cifsLockInfo *conf_lock;
729 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
730 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
718 bool exist; 731 bool exist;
719 732
720 mutex_lock(&cinode->lock_mutex); 733 mutex_lock(&cinode->lock_mutex);
721 734
722 exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, 735 exist = cifs_find_lock_conflict(cfile, offset, length, type,
723 &conf_lock); 736 &conf_lock);
724 if (exist) { 737 if (exist) {
725 flock->fl_start = conf_lock->offset; 738 flock->fl_start = conf_lock->offset;
726 flock->fl_end = conf_lock->offset + conf_lock->length - 1; 739 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
727 flock->fl_pid = conf_lock->pid; 740 flock->fl_pid = conf_lock->pid;
728 if (conf_lock->type & LOCKING_ANDX_SHARED_LOCK) 741 if (conf_lock->type & server->vals->shared_lock_type)
729 flock->fl_type = F_RDLCK; 742 flock->fl_type = F_RDLCK;
730 else 743 else
731 flock->fl_type = F_WRLCK; 744 flock->fl_type = F_WRLCK;
@@ -739,10 +752,11 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
739} 752}
740 753
741static void 754static void
742cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) 755cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
743{ 756{
757 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
744 mutex_lock(&cinode->lock_mutex); 758 mutex_lock(&cinode->lock_mutex);
745 list_add_tail(&lock->llist, &cinode->llist); 759 list_add_tail(&lock->llist, &cfile->llist);
746 mutex_unlock(&cinode->lock_mutex); 760 mutex_unlock(&cinode->lock_mutex);
747} 761}
748 762
@@ -753,10 +767,11 @@ cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock)
753 * 3) -EACCESS, if there is a lock that prevents us and wait is false. 767 * 3) -EACCESS, if there is a lock that prevents us and wait is false.
754 */ 768 */
755static int 769static int
756cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, 770cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
757 bool wait) 771 bool wait)
758{ 772{
759 struct cifsLockInfo *conf_lock; 773 struct cifsLockInfo *conf_lock;
774 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
760 bool exist; 775 bool exist;
761 int rc = 0; 776 int rc = 0;
762 777
@@ -764,9 +779,10 @@ try_again:
764 exist = false; 779 exist = false;
765 mutex_lock(&cinode->lock_mutex); 780 mutex_lock(&cinode->lock_mutex);
766 781
767 exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); 782 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
783 lock->type, &conf_lock);
768 if (!exist && cinode->can_cache_brlcks) { 784 if (!exist && cinode->can_cache_brlcks) {
769 list_add_tail(&lock->llist, &cinode->llist); 785 list_add_tail(&lock->llist, &cfile->llist);
770 mutex_unlock(&cinode->lock_mutex); 786 mutex_unlock(&cinode->lock_mutex);
771 return rc; 787 return rc;
772 } 788 }
@@ -888,7 +904,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
888 for (i = 0; i < 2; i++) { 904 for (i = 0; i < 2; i++) {
889 cur = buf; 905 cur = buf;
890 num = 0; 906 num = 0;
891 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { 907 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
892 if (li->type != types[i]) 908 if (li->type != types[i])
893 continue; 909 continue;
894 cur->Pid = cpu_to_le16(li->pid); 910 cur->Pid = cpu_to_le16(li->pid);
@@ -898,7 +914,8 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
898 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); 914 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
899 if (++num == max_num) { 915 if (++num == max_num) {
900 stored_rc = cifs_lockv(xid, tcon, cfile->netfid, 916 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
901 li->type, 0, num, buf); 917 (__u8)li->type, 0, num,
918 buf);
902 if (stored_rc) 919 if (stored_rc)
903 rc = stored_rc; 920 rc = stored_rc;
904 cur = buf; 921 cur = buf;
@@ -909,7 +926,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
909 926
910 if (num) { 927 if (num) {
911 stored_rc = cifs_lockv(xid, tcon, cfile->netfid, 928 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
912 types[i], 0, num, buf); 929 (__u8)types[i], 0, num, buf);
913 if (stored_rc) 930 if (stored_rc)
914 rc = stored_rc; 931 rc = stored_rc;
915 } 932 }
@@ -1053,8 +1070,8 @@ cifs_push_locks(struct cifsFileInfo *cfile)
1053} 1070}
1054 1071
1055static void 1072static void
1056cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock, 1073cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
1057 bool *wait_flag) 1074 bool *wait_flag, struct TCP_Server_Info *server)
1058{ 1075{
1059 if (flock->fl_flags & FL_POSIX) 1076 if (flock->fl_flags & FL_POSIX)
1060 cFYI(1, "Posix"); 1077 cFYI(1, "Posix");
@@ -1073,38 +1090,50 @@ cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock,
1073 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) 1090 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
1074 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags); 1091 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
1075 1092
1076 *type = LOCKING_ANDX_LARGE_FILES; 1093 *type = server->vals->large_lock_type;
1077 if (flock->fl_type == F_WRLCK) { 1094 if (flock->fl_type == F_WRLCK) {
1078 cFYI(1, "F_WRLCK "); 1095 cFYI(1, "F_WRLCK ");
1096 *type |= server->vals->exclusive_lock_type;
1079 *lock = 1; 1097 *lock = 1;
1080 } else if (flock->fl_type == F_UNLCK) { 1098 } else if (flock->fl_type == F_UNLCK) {
1081 cFYI(1, "F_UNLCK"); 1099 cFYI(1, "F_UNLCK");
1100 *type |= server->vals->unlock_lock_type;
1082 *unlock = 1; 1101 *unlock = 1;
1083 /* Check if unlock includes more than one lock range */ 1102 /* Check if unlock includes more than one lock range */
1084 } else if (flock->fl_type == F_RDLCK) { 1103 } else if (flock->fl_type == F_RDLCK) {
1085 cFYI(1, "F_RDLCK"); 1104 cFYI(1, "F_RDLCK");
1086 *type |= LOCKING_ANDX_SHARED_LOCK; 1105 *type |= server->vals->shared_lock_type;
1087 *lock = 1; 1106 *lock = 1;
1088 } else if (flock->fl_type == F_EXLCK) { 1107 } else if (flock->fl_type == F_EXLCK) {
1089 cFYI(1, "F_EXLCK"); 1108 cFYI(1, "F_EXLCK");
1109 *type |= server->vals->exclusive_lock_type;
1090 *lock = 1; 1110 *lock = 1;
1091 } else if (flock->fl_type == F_SHLCK) { 1111 } else if (flock->fl_type == F_SHLCK) {
1092 cFYI(1, "F_SHLCK"); 1112 cFYI(1, "F_SHLCK");
1093 *type |= LOCKING_ANDX_SHARED_LOCK; 1113 *type |= server->vals->shared_lock_type;
1094 *lock = 1; 1114 *lock = 1;
1095 } else 1115 } else
1096 cFYI(1, "Unknown type of lock"); 1116 cFYI(1, "Unknown type of lock");
1097} 1117}
1098 1118
1099static int 1119static int
1100cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, 1120cifs_mandatory_lock(int xid, struct cifsFileInfo *cfile, __u64 offset,
1121 __u64 length, __u32 type, int lock, int unlock, bool wait)
1122{
1123 return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid,
1124 current->tgid, length, offset, unlock, lock,
1125 (__u8)type, wait, 0);
1126}
1127
1128static int
1129cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
1101 bool wait_flag, bool posix_lck, int xid) 1130 bool wait_flag, bool posix_lck, int xid)
1102{ 1131{
1103 int rc = 0; 1132 int rc = 0;
1104 __u64 length = 1 + flock->fl_end - flock->fl_start; 1133 __u64 length = 1 + flock->fl_end - flock->fl_start;
1105 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 1134 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1106 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1135 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1107 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); 1136 struct TCP_Server_Info *server = tcon->ses->server;
1108 __u16 netfid = cfile->netfid; 1137 __u16 netfid = cfile->netfid;
1109 1138
1110 if (posix_lck) { 1139 if (posix_lck) {
@@ -1114,7 +1143,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type,
1114 if (!rc) 1143 if (!rc)
1115 return rc; 1144 return rc;
1116 1145
1117 if (type & LOCKING_ANDX_SHARED_LOCK) 1146 if (type & server->vals->shared_lock_type)
1118 posix_lock_type = CIFS_RDLCK; 1147 posix_lock_type = CIFS_RDLCK;
1119 else 1148 else
1120 posix_lock_type = CIFS_WRLCK; 1149 posix_lock_type = CIFS_WRLCK;
@@ -1124,38 +1153,35 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type,
1124 return rc; 1153 return rc;
1125 } 1154 }
1126 1155
1127 rc = cifs_lock_test(cinode, flock->fl_start, length, type, netfid, 1156 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
1128 flock);
1129 if (!rc) 1157 if (!rc)
1130 return rc; 1158 return rc;
1131 1159
1132 /* BB we could chain these into one lock request BB */ 1160 /* BB we could chain these into one lock request BB */
1133 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, 1161 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type,
1134 flock->fl_start, 0, 1, type, 0, 0); 1162 1, 0, false);
1135 if (rc == 0) { 1163 if (rc == 0) {
1136 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, 1164 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1137 length, flock->fl_start, 1, 0, 1165 type, 0, 1, false);
1138 type, 0, 0);
1139 flock->fl_type = F_UNLCK; 1166 flock->fl_type = F_UNLCK;
1140 if (rc != 0) 1167 if (rc != 0)
1141 cERROR(1, "Error unlocking previously locked " 1168 cERROR(1, "Error unlocking previously locked "
1142 "range %d during test of lock", rc); 1169 "range %d during test of lock", rc);
1143 return 0; 1170 return 0;
1144 } 1171 }
1145 1172
1146 if (type & LOCKING_ANDX_SHARED_LOCK) { 1173 if (type & server->vals->shared_lock_type) {
1147 flock->fl_type = F_WRLCK; 1174 flock->fl_type = F_WRLCK;
1148 return 0; 1175 return 0;
1149 } 1176 }
1150 1177
1151 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, 1178 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1152 flock->fl_start, 0, 1, 1179 type | server->vals->shared_lock_type, 1, 0,
1153 type | LOCKING_ANDX_SHARED_LOCK, 0, 0); 1180 false);
1154 if (rc == 0) { 1181 if (rc == 0) {
1155 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, 1182 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1156 length, flock->fl_start, 1, 0, 1183 type | server->vals->shared_lock_type,
1157 type | LOCKING_ANDX_SHARED_LOCK, 1184 0, 1, false);
1158 0, 0);
1159 flock->fl_type = F_RDLCK; 1185 flock->fl_type = F_RDLCK;
1160 if (rc != 0) 1186 if (rc != 0)
1161 cERROR(1, "Error unlocking previously locked " 1187 cERROR(1, "Error unlocking previously locked "
@@ -1212,15 +1238,13 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1212 for (i = 0; i < 2; i++) { 1238 for (i = 0; i < 2; i++) {
1213 cur = buf; 1239 cur = buf;
1214 num = 0; 1240 num = 0;
1215 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { 1241 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
1216 if (flock->fl_start > li->offset || 1242 if (flock->fl_start > li->offset ||
1217 (flock->fl_start + length) < 1243 (flock->fl_start + length) <
1218 (li->offset + li->length)) 1244 (li->offset + li->length))
1219 continue; 1245 continue;
1220 if (current->tgid != li->pid) 1246 if (current->tgid != li->pid)
1221 continue; 1247 continue;
1222 if (cfile->netfid != li->netfid)
1223 continue;
1224 if (types[i] != li->type) 1248 if (types[i] != li->type)
1225 continue; 1249 continue;
1226 if (!cinode->can_cache_brlcks) { 1250 if (!cinode->can_cache_brlcks) {
@@ -1233,7 +1257,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1233 cpu_to_le32((u32)(li->offset>>32)); 1257 cpu_to_le32((u32)(li->offset>>32));
1234 /* 1258 /*
1235 * We need to save a lock here to let us add 1259 * We need to save a lock here to let us add
1236 * it again to the inode list if the unlock 1260 * it again to the file's list if the unlock
1237 * range request fails on the server. 1261 * range request fails on the server.
1238 */ 1262 */
1239 list_move(&li->llist, &tmp_llist); 1263 list_move(&li->llist, &tmp_llist);
@@ -1247,10 +1271,10 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1247 * We failed on the unlock range 1271 * We failed on the unlock range
1248 * request - add all locks from 1272 * request - add all locks from
1249 * the tmp list to the head of 1273 * the tmp list to the head of
1250 * the inode list. 1274 * the file's list.
1251 */ 1275 */
1252 cifs_move_llist(&tmp_llist, 1276 cifs_move_llist(&tmp_llist,
1253 &cinode->llist); 1277 &cfile->llist);
1254 rc = stored_rc; 1278 rc = stored_rc;
1255 } else 1279 } else
1256 /* 1280 /*
@@ -1265,7 +1289,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1265 } else { 1289 } else {
1266 /* 1290 /*
1267 * We can cache brlock requests - simply remove 1291 * We can cache brlock requests - simply remove
1268 * a lock from the inode list. 1292 * a lock from the file's list.
1269 */ 1293 */
1270 list_del(&li->llist); 1294 list_del(&li->llist);
1271 cifs_del_lock_waiters(li); 1295 cifs_del_lock_waiters(li);
@@ -1276,7 +1300,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1276 stored_rc = cifs_lockv(xid, tcon, cfile->netfid, 1300 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
1277 types[i], num, 0, buf); 1301 types[i], num, 0, buf);
1278 if (stored_rc) { 1302 if (stored_rc) {
1279 cifs_move_llist(&tmp_llist, &cinode->llist); 1303 cifs_move_llist(&tmp_llist, &cfile->llist);
1280 rc = stored_rc; 1304 rc = stored_rc;
1281 } else 1305 } else
1282 cifs_free_llist(&tmp_llist); 1306 cifs_free_llist(&tmp_llist);
@@ -1289,14 +1313,14 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1289} 1313}
1290 1314
1291static int 1315static int
1292cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, 1316cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1293 bool wait_flag, bool posix_lck, int lock, int unlock, int xid) 1317 bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
1294{ 1318{
1295 int rc = 0; 1319 int rc = 0;
1296 __u64 length = 1 + flock->fl_end - flock->fl_start; 1320 __u64 length = 1 + flock->fl_end - flock->fl_start;
1297 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 1321 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1298 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1322 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1299 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); 1323 struct TCP_Server_Info *server = tcon->ses->server;
1300 __u16 netfid = cfile->netfid; 1324 __u16 netfid = cfile->netfid;
1301 1325
1302 if (posix_lck) { 1326 if (posix_lck) {
@@ -1306,7 +1330,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type,
1306 if (!rc || rc < 0) 1330 if (!rc || rc < 0)
1307 return rc; 1331 return rc;
1308 1332
1309 if (type & LOCKING_ANDX_SHARED_LOCK) 1333 if (type & server->vals->shared_lock_type)
1310 posix_lock_type = CIFS_RDLCK; 1334 posix_lock_type = CIFS_RDLCK;
1311 else 1335 else
1312 posix_lock_type = CIFS_WRLCK; 1336 posix_lock_type = CIFS_WRLCK;
@@ -1323,24 +1347,24 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type,
1323 if (lock) { 1347 if (lock) {
1324 struct cifsLockInfo *lock; 1348 struct cifsLockInfo *lock;
1325 1349
1326 lock = cifs_lock_init(flock->fl_start, length, type, netfid); 1350 lock = cifs_lock_init(flock->fl_start, length, type);
1327 if (!lock) 1351 if (!lock)
1328 return -ENOMEM; 1352 return -ENOMEM;
1329 1353
1330 rc = cifs_lock_add_if(cinode, lock, wait_flag); 1354 rc = cifs_lock_add_if(cfile, lock, wait_flag);
1331 if (rc < 0) 1355 if (rc < 0)
1332 kfree(lock); 1356 kfree(lock);
1333 if (rc <= 0) 1357 if (rc <= 0)
1334 goto out; 1358 goto out;
1335 1359
1336 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, 1360 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1337 flock->fl_start, 0, 1, type, wait_flag, 0); 1361 type, 1, 0, wait_flag);
1338 if (rc) { 1362 if (rc) {
1339 kfree(lock); 1363 kfree(lock);
1340 goto out; 1364 goto out;
1341 } 1365 }
1342 1366
1343 cifs_lock_add(cinode, lock); 1367 cifs_lock_add(cfile, lock);
1344 } else if (unlock) 1368 } else if (unlock)
1345 rc = cifs_unlock_range(cfile, flock, xid); 1369 rc = cifs_unlock_range(cfile, flock, xid);
1346 1370
@@ -1361,7 +1385,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1361 struct cifsInodeInfo *cinode; 1385 struct cifsInodeInfo *cinode;
1362 struct cifsFileInfo *cfile; 1386 struct cifsFileInfo *cfile;
1363 __u16 netfid; 1387 __u16 netfid;
1364 __u8 type; 1388 __u32 type;
1365 1389
1366 rc = -EACCES; 1390 rc = -EACCES;
1367 xid = GetXid(); 1391 xid = GetXid();
@@ -1370,11 +1394,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1370 "end: %lld", cmd, flock->fl_flags, flock->fl_type, 1394 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1371 flock->fl_start, flock->fl_end); 1395 flock->fl_start, flock->fl_end);
1372 1396
1373 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag);
1374
1375 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1376 cfile = (struct cifsFileInfo *)file->private_data; 1397 cfile = (struct cifsFileInfo *)file->private_data;
1377 tcon = tlink_tcon(cfile->tlink); 1398 tcon = tlink_tcon(cfile->tlink);
1399
1400 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1401 tcon->ses->server);
1402
1403 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1378 netfid = cfile->netfid; 1404 netfid = cfile->netfid;
1379 cinode = CIFS_I(file->f_path.dentry->d_inode); 1405 cinode = CIFS_I(file->f_path.dentry->d_inode);
1380 1406
@@ -1539,10 +1565,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1539struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, 1565struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1540 bool fsuid_only) 1566 bool fsuid_only)
1541{ 1567{
1542 struct cifsFileInfo *open_file; 1568 struct cifsFileInfo *open_file, *inv_file = NULL;
1543 struct cifs_sb_info *cifs_sb; 1569 struct cifs_sb_info *cifs_sb;
1544 bool any_available = false; 1570 bool any_available = false;
1545 int rc; 1571 int rc;
1572 unsigned int refind = 0;
1546 1573
1547 /* Having a null inode here (because mapping->host was set to zero by 1574 /* Having a null inode here (because mapping->host was set to zero by
1548 the VFS or MM) should not happen but we had reports of on oops (due to 1575 the VFS or MM) should not happen but we had reports of on oops (due to
@@ -1562,40 +1589,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1562 1589
1563 spin_lock(&cifs_file_list_lock); 1590 spin_lock(&cifs_file_list_lock);
1564refind_writable: 1591refind_writable:
1592 if (refind > MAX_REOPEN_ATT) {
1593 spin_unlock(&cifs_file_list_lock);
1594 return NULL;
1595 }
1565 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1596 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1566 if (!any_available && open_file->pid != current->tgid) 1597 if (!any_available && open_file->pid != current->tgid)
1567 continue; 1598 continue;
1568 if (fsuid_only && open_file->uid != current_fsuid()) 1599 if (fsuid_only && open_file->uid != current_fsuid())
1569 continue; 1600 continue;
1570 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 1601 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
1571 cifsFileInfo_get(open_file);
1572
1573 if (!open_file->invalidHandle) { 1602 if (!open_file->invalidHandle) {
1574 /* found a good writable file */ 1603 /* found a good writable file */
1604 cifsFileInfo_get(open_file);
1575 spin_unlock(&cifs_file_list_lock); 1605 spin_unlock(&cifs_file_list_lock);
1576 return open_file; 1606 return open_file;
1607 } else {
1608 if (!inv_file)
1609 inv_file = open_file;
1577 } 1610 }
1578
1579 spin_unlock(&cifs_file_list_lock);
1580
1581 /* Had to unlock since following call can block */
1582 rc = cifs_reopen_file(open_file, false);
1583 if (!rc)
1584 return open_file;
1585
1586 /* if it fails, try another handle if possible */
1587 cFYI(1, "wp failed on reopen file");
1588 cifsFileInfo_put(open_file);
1589
1590 spin_lock(&cifs_file_list_lock);
1591
1592 /* else we simply continue to the next entry. Thus
1593 we do not loop on reopen errors. If we
1594 can not reopen the file, for example if we
1595 reconnected to a server with another client
1596 racing to delete or lock the file we would not
1597 make progress if we restarted before the beginning
1598 of the loop here. */
1599 } 1611 }
1600 } 1612 }
1601 /* couldn't find useable FH with same pid, try any available */ 1613 /* couldn't find useable FH with same pid, try any available */
@@ -1603,7 +1615,30 @@ refind_writable:
1603 any_available = true; 1615 any_available = true;
1604 goto refind_writable; 1616 goto refind_writable;
1605 } 1617 }
1618
1619 if (inv_file) {
1620 any_available = false;
1621 cifsFileInfo_get(inv_file);
1622 }
1623
1606 spin_unlock(&cifs_file_list_lock); 1624 spin_unlock(&cifs_file_list_lock);
1625
1626 if (inv_file) {
1627 rc = cifs_reopen_file(inv_file, false);
1628 if (!rc)
1629 return inv_file;
1630 else {
1631 spin_lock(&cifs_file_list_lock);
1632 list_move_tail(&inv_file->flist,
1633 &cifs_inode->openFileList);
1634 spin_unlock(&cifs_file_list_lock);
1635 cifsFileInfo_put(inv_file);
1636 spin_lock(&cifs_file_list_lock);
1637 ++refind;
1638 goto refind_writable;
1639 }
1640 }
1641
1607 return NULL; 1642 return NULL;
1608} 1643}
1609 1644
@@ -2339,24 +2374,224 @@ ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2339 return cifs_user_writev(iocb, iov, nr_segs, pos); 2374 return cifs_user_writev(iocb, iov, nr_segs, pos);
2340} 2375}
2341 2376
2377static struct cifs_readdata *
2378cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
2379{
2380 struct cifs_readdata *rdata;
2381
2382 rdata = kzalloc(sizeof(*rdata) +
2383 sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
2384 if (rdata != NULL) {
2385 kref_init(&rdata->refcount);
2386 INIT_LIST_HEAD(&rdata->list);
2387 init_completion(&rdata->done);
2388 INIT_WORK(&rdata->work, complete);
2389 INIT_LIST_HEAD(&rdata->pages);
2390 }
2391 return rdata;
2392}
2393
2394void
2395cifs_readdata_release(struct kref *refcount)
2396{
2397 struct cifs_readdata *rdata = container_of(refcount,
2398 struct cifs_readdata, refcount);
2399
2400 if (rdata->cfile)
2401 cifsFileInfo_put(rdata->cfile);
2402
2403 kfree(rdata);
2404}
2405
2406static int
2407cifs_read_allocate_pages(struct list_head *list, unsigned int npages)
2408{
2409 int rc = 0;
2410 struct page *page, *tpage;
2411 unsigned int i;
2412
2413 for (i = 0; i < npages; i++) {
2414 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2415 if (!page) {
2416 rc = -ENOMEM;
2417 break;
2418 }
2419 list_add(&page->lru, list);
2420 }
2421
2422 if (rc) {
2423 list_for_each_entry_safe(page, tpage, list, lru) {
2424 list_del(&page->lru);
2425 put_page(page);
2426 }
2427 }
2428 return rc;
2429}
2430
2431static void
2432cifs_uncached_readdata_release(struct kref *refcount)
2433{
2434 struct page *page, *tpage;
2435 struct cifs_readdata *rdata = container_of(refcount,
2436 struct cifs_readdata, refcount);
2437
2438 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2439 list_del(&page->lru);
2440 put_page(page);
2441 }
2442 cifs_readdata_release(refcount);
2443}
2444
2445static int
2446cifs_retry_async_readv(struct cifs_readdata *rdata)
2447{
2448 int rc;
2449
2450 do {
2451 if (rdata->cfile->invalidHandle) {
2452 rc = cifs_reopen_file(rdata->cfile, true);
2453 if (rc != 0)
2454 continue;
2455 }
2456 rc = cifs_async_readv(rdata);
2457 } while (rc == -EAGAIN);
2458
2459 return rc;
2460}
2461
2462/**
2463 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2464 * @rdata: the readdata response with list of pages holding data
2465 * @iov: vector in which we should copy the data
2466 * @nr_segs: number of segments in vector
2467 * @offset: offset into file of the first iovec
2468 * @copied: used to return the amount of data copied to the iov
2469 *
2470 * This function copies data from a list of pages in a readdata response into
2471 * an array of iovecs. It will first calculate where the data should go
2472 * based on the info in the readdata and then copy the data into that spot.
2473 */
2474static ssize_t
2475cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2476 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2477{
2478 int rc = 0;
2479 struct iov_iter ii;
2480 size_t pos = rdata->offset - offset;
2481 struct page *page, *tpage;
2482 ssize_t remaining = rdata->bytes;
2483 unsigned char *pdata;
2484
2485 /* set up iov_iter and advance to the correct offset */
2486 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2487 iov_iter_advance(&ii, pos);
2488
2489 *copied = 0;
2490 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2491 ssize_t copy;
2492
2493 /* copy a whole page or whatever's left */
2494 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2495
2496 /* ...but limit it to whatever space is left in the iov */
2497 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2498
2499 /* go while there's data to be copied and no errors */
2500 if (copy && !rc) {
2501 pdata = kmap(page);
2502 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2503 (int)copy);
2504 kunmap(page);
2505 if (!rc) {
2506 *copied += copy;
2507 remaining -= copy;
2508 iov_iter_advance(&ii, copy);
2509 }
2510 }
2511
2512 list_del(&page->lru);
2513 put_page(page);
2514 }
2515
2516 return rc;
2517}
2518
2519static void
2520cifs_uncached_readv_complete(struct work_struct *work)
2521{
2522 struct cifs_readdata *rdata = container_of(work,
2523 struct cifs_readdata, work);
2524
2525 /* if the result is non-zero then the pages weren't kmapped */
2526 if (rdata->result == 0) {
2527 struct page *page;
2528
2529 list_for_each_entry(page, &rdata->pages, lru)
2530 kunmap(page);
2531 }
2532
2533 complete(&rdata->done);
2534 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2535}
2536
2537static int
2538cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata,
2539 unsigned int remaining)
2540{
2541 int len = 0;
2542 struct page *page, *tpage;
2543
2544 rdata->nr_iov = 1;
2545 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2546 if (remaining >= PAGE_SIZE) {
2547 /* enough data to fill the page */
2548 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2549 rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE;
2550 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2551 rdata->nr_iov, page->index,
2552 rdata->iov[rdata->nr_iov].iov_base,
2553 rdata->iov[rdata->nr_iov].iov_len);
2554 ++rdata->nr_iov;
2555 len += PAGE_SIZE;
2556 remaining -= PAGE_SIZE;
2557 } else if (remaining > 0) {
2558 /* enough for partial page, fill and zero the rest */
2559 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2560 rdata->iov[rdata->nr_iov].iov_len = remaining;
2561 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2562 rdata->nr_iov, page->index,
2563 rdata->iov[rdata->nr_iov].iov_base,
2564 rdata->iov[rdata->nr_iov].iov_len);
2565 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2566 '\0', PAGE_SIZE - remaining);
2567 ++rdata->nr_iov;
2568 len += remaining;
2569 remaining = 0;
2570 } else {
2571 /* no need to hold page hostage */
2572 list_del(&page->lru);
2573 put_page(page);
2574 }
2575 }
2576
2577 return len;
2578}
2579
2342static ssize_t 2580static ssize_t
2343cifs_iovec_read(struct file *file, const struct iovec *iov, 2581cifs_iovec_read(struct file *file, const struct iovec *iov,
2344 unsigned long nr_segs, loff_t *poffset) 2582 unsigned long nr_segs, loff_t *poffset)
2345{ 2583{
2346 int rc; 2584 ssize_t rc;
2347 int xid;
2348 ssize_t total_read;
2349 unsigned int bytes_read = 0;
2350 size_t len, cur_len; 2585 size_t len, cur_len;
2351 int iov_offset = 0; 2586 ssize_t total_read = 0;
2587 loff_t offset = *poffset;
2588 unsigned int npages;
2352 struct cifs_sb_info *cifs_sb; 2589 struct cifs_sb_info *cifs_sb;
2353 struct cifs_tcon *pTcon; 2590 struct cifs_tcon *tcon;
2354 struct cifsFileInfo *open_file; 2591 struct cifsFileInfo *open_file;
2355 struct smb_com_read_rsp *pSMBr; 2592 struct cifs_readdata *rdata, *tmp;
2356 struct cifs_io_parms io_parms; 2593 struct list_head rdata_list;
2357 char *read_data; 2594 pid_t pid;
2358 unsigned int rsize;
2359 __u32 pid;
2360 2595
2361 if (!nr_segs) 2596 if (!nr_segs)
2362 return 0; 2597 return 0;
@@ -2365,14 +2600,10 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
2365 if (!len) 2600 if (!len)
2366 return 0; 2601 return 0;
2367 2602
2368 xid = GetXid(); 2603 INIT_LIST_HEAD(&rdata_list);
2369 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 2604 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2370
2371 /* FIXME: set up handlers for larger reads and/or convert to async */
2372 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2373
2374 open_file = file->private_data; 2605 open_file = file->private_data;
2375 pTcon = tlink_tcon(open_file->tlink); 2606 tcon = tlink_tcon(open_file->tlink);
2376 2607
2377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 2608 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2378 pid = open_file->pid; 2609 pid = open_file->pid;
@@ -2382,56 +2613,78 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
2382 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 2613 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
2383 cFYI(1, "attempting read on write only file instance"); 2614 cFYI(1, "attempting read on write only file instance");
2384 2615
2385 for (total_read = 0; total_read < len; total_read += bytes_read) { 2616 do {
2386 cur_len = min_t(const size_t, len - total_read, rsize); 2617 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2387 rc = -EAGAIN; 2618 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
2388 read_data = NULL;
2389 2619
2390 while (rc == -EAGAIN) { 2620 /* allocate a readdata struct */
2391 int buf_type = CIFS_NO_BUFFER; 2621 rdata = cifs_readdata_alloc(npages,
2392 if (open_file->invalidHandle) { 2622 cifs_uncached_readv_complete);
2393 rc = cifs_reopen_file(open_file, true); 2623 if (!rdata) {
2394 if (rc != 0) 2624 rc = -ENOMEM;
2395 break; 2625 goto error;
2396 }
2397 io_parms.netfid = open_file->netfid;
2398 io_parms.pid = pid;
2399 io_parms.tcon = pTcon;
2400 io_parms.offset = *poffset;
2401 io_parms.length = cur_len;
2402 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2403 &read_data, &buf_type);
2404 pSMBr = (struct smb_com_read_rsp *)read_data;
2405 if (read_data) {
2406 char *data_offset = read_data + 4 +
2407 le16_to_cpu(pSMBr->DataOffset);
2408 if (memcpy_toiovecend(iov, data_offset,
2409 iov_offset, bytes_read))
2410 rc = -EFAULT;
2411 if (buf_type == CIFS_SMALL_BUFFER)
2412 cifs_small_buf_release(read_data);
2413 else if (buf_type == CIFS_LARGE_BUFFER)
2414 cifs_buf_release(read_data);
2415 read_data = NULL;
2416 iov_offset += bytes_read;
2417 }
2418 } 2626 }
2419 2627
2420 if (rc || (bytes_read == 0)) { 2628 rc = cifs_read_allocate_pages(&rdata->pages, npages);
2421 if (total_read) { 2629 if (rc)
2422 break; 2630 goto error;
2423 } else { 2631
2424 FreeXid(xid); 2632 rdata->cfile = cifsFileInfo_get(open_file);
2425 return rc; 2633 rdata->offset = offset;
2634 rdata->bytes = cur_len;
2635 rdata->pid = pid;
2636 rdata->marshal_iov = cifs_uncached_read_marshal_iov;
2637
2638 rc = cifs_retry_async_readv(rdata);
2639error:
2640 if (rc) {
2641 kref_put(&rdata->refcount,
2642 cifs_uncached_readdata_release);
2643 break;
2644 }
2645
2646 list_add_tail(&rdata->list, &rdata_list);
2647 offset += cur_len;
2648 len -= cur_len;
2649 } while (len > 0);
2650
2651 /* if at least one read request send succeeded, then reset rc */
2652 if (!list_empty(&rdata_list))
2653 rc = 0;
2654
2655 /* the loop below should proceed in the order of increasing offsets */
2656restart_loop:
2657 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2658 if (!rc) {
2659 ssize_t copied;
2660
2661 /* FIXME: freezable sleep too? */
2662 rc = wait_for_completion_killable(&rdata->done);
2663 if (rc)
2664 rc = -EINTR;
2665 else if (rdata->result)
2666 rc = rdata->result;
2667 else {
2668 rc = cifs_readdata_to_iov(rdata, iov,
2669 nr_segs, *poffset,
2670 &copied);
2671 total_read += copied;
2672 }
2673
2674 /* resend call if it's a retryable error */
2675 if (rc == -EAGAIN) {
2676 rc = cifs_retry_async_readv(rdata);
2677 goto restart_loop;
2426 } 2678 }
2427 } else {
2428 cifs_stats_bytes_read(pTcon, bytes_read);
2429 *poffset += bytes_read;
2430 } 2679 }
2680 list_del_init(&rdata->list);
2681 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2431 } 2682 }
2432 2683
2433 FreeXid(xid); 2684 cifs_stats_bytes_read(tcon, total_read);
2434 return total_read; 2685 *poffset += total_read;
2686
2687 return total_read ? total_read : rc;
2435} 2688}
2436 2689
2437ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, 2690ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
@@ -2606,6 +2859,100 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2606 return rc; 2859 return rc;
2607} 2860}
2608 2861
2862static void
2863cifs_readv_complete(struct work_struct *work)
2864{
2865 struct cifs_readdata *rdata = container_of(work,
2866 struct cifs_readdata, work);
2867 struct page *page, *tpage;
2868
2869 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2870 list_del(&page->lru);
2871 lru_cache_add_file(page);
2872
2873 if (rdata->result == 0) {
2874 kunmap(page);
2875 flush_dcache_page(page);
2876 SetPageUptodate(page);
2877 }
2878
2879 unlock_page(page);
2880
2881 if (rdata->result == 0)
2882 cifs_readpage_to_fscache(rdata->mapping->host, page);
2883
2884 page_cache_release(page);
2885 }
2886 kref_put(&rdata->refcount, cifs_readdata_release);
2887}
2888
2889static int
2890cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2891{
2892 int len = 0;
2893 struct page *page, *tpage;
2894 u64 eof;
2895 pgoff_t eof_index;
2896
2897 /* determine the eof that the server (probably) has */
2898 eof = CIFS_I(rdata->mapping->host)->server_eof;
2899 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2900 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2901
2902 rdata->nr_iov = 1;
2903 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2904 if (remaining >= PAGE_CACHE_SIZE) {
2905 /* enough data to fill the page */
2906 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2907 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2908 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2909 rdata->nr_iov, page->index,
2910 rdata->iov[rdata->nr_iov].iov_base,
2911 rdata->iov[rdata->nr_iov].iov_len);
2912 ++rdata->nr_iov;
2913 len += PAGE_CACHE_SIZE;
2914 remaining -= PAGE_CACHE_SIZE;
2915 } else if (remaining > 0) {
2916 /* enough for partial page, fill and zero the rest */
2917 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2918 rdata->iov[rdata->nr_iov].iov_len = remaining;
2919 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2920 rdata->nr_iov, page->index,
2921 rdata->iov[rdata->nr_iov].iov_base,
2922 rdata->iov[rdata->nr_iov].iov_len);
2923 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2924 '\0', PAGE_CACHE_SIZE - remaining);
2925 ++rdata->nr_iov;
2926 len += remaining;
2927 remaining = 0;
2928 } else if (page->index > eof_index) {
2929 /*
2930 * The VFS will not try to do readahead past the
2931 * i_size, but it's possible that we have outstanding
2932 * writes with gaps in the middle and the i_size hasn't
2933 * caught up yet. Populate those with zeroed out pages
2934 * to prevent the VFS from repeatedly attempting to
2935 * fill them until the writes are flushed.
2936 */
2937 zero_user(page, 0, PAGE_CACHE_SIZE);
2938 list_del(&page->lru);
2939 lru_cache_add_file(page);
2940 flush_dcache_page(page);
2941 SetPageUptodate(page);
2942 unlock_page(page);
2943 page_cache_release(page);
2944 } else {
2945 /* no need to hold page hostage */
2946 list_del(&page->lru);
2947 lru_cache_add_file(page);
2948 unlock_page(page);
2949 page_cache_release(page);
2950 }
2951 }
2952
2953 return len;
2954}
2955
2609static int cifs_readpages(struct file *file, struct address_space *mapping, 2956static int cifs_readpages(struct file *file, struct address_space *mapping,
2610 struct list_head *page_list, unsigned num_pages) 2957 struct list_head *page_list, unsigned num_pages)
2611{ 2958{
@@ -2708,7 +3055,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2708 nr_pages++; 3055 nr_pages++;
2709 } 3056 }
2710 3057
2711 rdata = cifs_readdata_alloc(nr_pages); 3058 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
2712 if (!rdata) { 3059 if (!rdata) {
2713 /* best to give up if we're out of mem */ 3060 /* best to give up if we're out of mem */
2714 list_for_each_entry_safe(page, tpage, &tmplist, lru) { 3061 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
@@ -2722,24 +3069,16 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2722 } 3069 }
2723 3070
2724 spin_lock(&cifs_file_list_lock); 3071 spin_lock(&cifs_file_list_lock);
2725 cifsFileInfo_get(open_file);
2726 spin_unlock(&cifs_file_list_lock); 3072 spin_unlock(&cifs_file_list_lock);
2727 rdata->cfile = open_file; 3073 rdata->cfile = cifsFileInfo_get(open_file);
2728 rdata->mapping = mapping; 3074 rdata->mapping = mapping;
2729 rdata->offset = offset; 3075 rdata->offset = offset;
2730 rdata->bytes = bytes; 3076 rdata->bytes = bytes;
2731 rdata->pid = pid; 3077 rdata->pid = pid;
3078 rdata->marshal_iov = cifs_readpages_marshal_iov;
2732 list_splice_init(&tmplist, &rdata->pages); 3079 list_splice_init(&tmplist, &rdata->pages);
2733 3080
2734 do { 3081 rc = cifs_retry_async_readv(rdata);
2735 if (open_file->invalidHandle) {
2736 rc = cifs_reopen_file(open_file, true);
2737 if (rc != 0)
2738 continue;
2739 }
2740 rc = cifs_async_readv(rdata);
2741 } while (rc == -EAGAIN);
2742
2743 if (rc != 0) { 3082 if (rc != 0) {
2744 list_for_each_entry_safe(page, tpage, &rdata->pages, 3083 list_for_each_entry_safe(page, tpage, &rdata->pages,
2745 lru) { 3084 lru) {
@@ -2748,9 +3087,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2748 unlock_page(page); 3087 unlock_page(page);
2749 page_cache_release(page); 3088 page_cache_release(page);
2750 } 3089 }
2751 cifs_readdata_free(rdata); 3090 kref_put(&rdata->refcount, cifs_readdata_release);
2752 break; 3091 break;
2753 } 3092 }
3093
3094 kref_put(&rdata->refcount, cifs_readdata_release);
2754 } 3095 }
2755 3096
2756 return rc; 3097 return rc;
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 4221b5e48a42..6d2667f0c98c 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -51,7 +51,15 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
51 cifs_sb = CIFS_SB(inode->i_sb); 51 cifs_sb = CIFS_SB(inode->i_sb);
52 52
53 switch (command) { 53 switch (command) {
54 static bool warned = false;
54 case CIFS_IOC_CHECKUMOUNT: 55 case CIFS_IOC_CHECKUMOUNT:
56 if (!warned) {
57 warned = true;
58 cERROR(1, "the CIFS_IOC_CHECKMOUNT ioctl will "
59 "be deprecated in 3.7. Please "
60 "migrate away from the use of "
61 "umount.cifs");
62 }
55 cFYI(1, "User unmount attempted"); 63 cFYI(1, "User unmount attempted");
56 if (cifs_sb->mnt_uid == current_uid()) 64 if (cifs_sb->mnt_uid == current_uid())
57 rc = 0; 65 rc = 0;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index c29d1aa2c54f..e2552d2b2e42 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -306,8 +306,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
306 const struct cifs_tcon *treeCon, int word_count 306 const struct cifs_tcon *treeCon, int word_count
307 /* length of fixed section (word count) in two byte units */) 307 /* length of fixed section (word count) in two byte units */)
308{ 308{
309 struct list_head *temp_item;
310 struct cifs_ses *ses;
311 char *temp = (char *) buffer; 309 char *temp = (char *) buffer;
312 310
313 memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ 311 memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
@@ -337,51 +335,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
337 /* Uid is not converted */ 335 /* Uid is not converted */
338 buffer->Uid = treeCon->ses->Suid; 336 buffer->Uid = treeCon->ses->Suid;
339 buffer->Mid = GetNextMid(treeCon->ses->server); 337 buffer->Mid = GetNextMid(treeCon->ses->server);
340 if (multiuser_mount != 0) {
341 /* For the multiuser case, there are few obvious technically */
342 /* possible mechanisms to match the local linux user (uid) */
343 /* to a valid remote smb user (smb_uid): */
344 /* 1) Query Winbind (or other local pam/nss daemon */
345 /* for userid/password/logon_domain or credential */
346 /* 2) Query Winbind for uid to sid to username mapping */
347 /* and see if we have a matching password for existing*/
348 /* session for that user perhas getting password by */
349 /* adding a new pam_cifs module that stores passwords */
350 /* so that the cifs vfs can get at that for all logged*/
351 /* on users */
352 /* 3) (Which is the mechanism we have chosen) */
353 /* Search through sessions to the same server for a */
354 /* a match on the uid that was passed in on mount */
355 /* with the current processes uid (or euid?) and use */
356 /* that smb uid. If no existing smb session for */
357 /* that uid found, use the default smb session ie */
358 /* the smb session for the volume mounted which is */
359 /* the same as would be used if the multiuser mount */
360 /* flag were disabled. */
361
362 /* BB Add support for establishing new tCon and SMB Session */
363 /* with userid/password pairs found on the smb session */
364 /* for other target tcp/ip addresses BB */
365 if (current_fsuid() != treeCon->ses->linux_uid) {
366 cFYI(1, "Multiuser mode and UID "
367 "did not match tcon uid");
368 spin_lock(&cifs_tcp_ses_lock);
369 list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
370 ses = list_entry(temp_item, struct cifs_ses, smb_ses_list);
371 if (ses->linux_uid == current_fsuid()) {
372 if (ses->server == treeCon->ses->server) {
373 cFYI(1, "found matching uid substitute right smb_uid");
374 buffer->Uid = ses->Suid;
375 break;
376 } else {
377 /* BB eventually call cifs_setup_session here */
378 cFYI(1, "local UID found but no smb sess with this server exists");
379 }
380 }
381 }
382 spin_unlock(&cifs_tcp_ses_lock);
383 }
384 }
385 } 338 }
386 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) 339 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
387 buffer->Flags2 |= SMBFLG2_DFS; 340 buffer->Flags2 |= SMBFLG2_DFS;
@@ -700,22 +653,3 @@ backup_cred(struct cifs_sb_info *cifs_sb)
700 653
701 return false; 654 return false;
702} 655}
703
704void
705cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add)
706{
707 spin_lock(&server->req_lock);
708 server->credits += add;
709 server->in_flight--;
710 spin_unlock(&server->req_lock);
711 wake_up(&server->request_q);
712}
713
714void
715cifs_set_credits(struct TCP_Server_Info *server, const int val)
716{
717 spin_lock(&server->req_lock);
718 server->credits = val;
719 server->oplocks = val > 1 ? enable_oplocks : false;
720 spin_unlock(&server->req_lock);
721}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index e2bbc683e018..0a8224d1c4c5 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -219,6 +219,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
219 219
220static int initiate_cifs_search(const int xid, struct file *file) 220static int initiate_cifs_search(const int xid, struct file *file)
221{ 221{
222 __u16 search_flags;
222 int rc = 0; 223 int rc = 0;
223 char *full_path = NULL; 224 char *full_path = NULL;
224 struct cifsFileInfo *cifsFile; 225 struct cifsFileInfo *cifsFile;
@@ -270,8 +271,12 @@ ffirst_retry:
270 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; 271 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
271 } 272 }
272 273
274 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
275 if (backup_cred(cifs_sb))
276 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
277
273 rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, 278 rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
274 &cifsFile->netfid, &cifsFile->srch_inf, 279 &cifsFile->netfid, search_flags, &cifsFile->srch_inf,
275 cifs_sb->mnt_cifs_flags & 280 cifs_sb->mnt_cifs_flags &
276 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); 281 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
277 if (rc == 0) 282 if (rc == 0)
@@ -502,11 +507,13 @@ static int cifs_save_resume_key(const char *current_entry,
502static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, 507static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
503 struct file *file, char **ppCurrentEntry, int *num_to_ret) 508 struct file *file, char **ppCurrentEntry, int *num_to_ret)
504{ 509{
510 __u16 search_flags;
505 int rc = 0; 511 int rc = 0;
506 int pos_in_buf = 0; 512 int pos_in_buf = 0;
507 loff_t first_entry_in_buffer; 513 loff_t first_entry_in_buffer;
508 loff_t index_to_find = file->f_pos; 514 loff_t index_to_find = file->f_pos;
509 struct cifsFileInfo *cifsFile = file->private_data; 515 struct cifsFileInfo *cifsFile = file->private_data;
516 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
510 /* check if index in the buffer */ 517 /* check if index in the buffer */
511 518
512 if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || 519 if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
@@ -560,10 +567,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
560 cifsFile); 567 cifsFile);
561 } 568 }
562 569
570 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
571 if (backup_cred(cifs_sb))
572 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
573
563 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 574 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
564 (rc == 0) && !cifsFile->srch_inf.endOfSearch) { 575 (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
565 cFYI(1, "calling findnext2"); 576 cFYI(1, "calling findnext2");
566 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, 577 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags,
567 &cifsFile->srch_inf); 578 &cifsFile->srch_inf);
568 /* FindFirst/Next set last_entry to NULL on malformed reply */ 579 /* FindFirst/Next set last_entry to NULL on malformed reply */
569 if (cifsFile->srch_inf.last_entry) 580 if (cifsFile->srch_inf.last_entry)
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
new file mode 100644
index 000000000000..d9d615fbed3f
--- /dev/null
+++ b/fs/cifs/smb1ops.c
@@ -0,0 +1,154 @@
1/*
2 * SMB1 (CIFS) version specific operations
3 *
4 * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License v2 as published
8 * by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "cifsglob.h"
21#include "cifsproto.h"
22#include "cifs_debug.h"
23#include "cifspdu.h"
24
25/*
26 * An NT cancel request header looks just like the original request except:
27 *
28 * The Command is SMB_COM_NT_CANCEL
29 * The WordCount is zeroed out
30 * The ByteCount is zeroed out
31 *
32 * This function mangles an existing request buffer into a
33 * SMB_COM_NT_CANCEL request and then sends it.
34 */
35static int
36send_nt_cancel(struct TCP_Server_Info *server, void *buf,
37 struct mid_q_entry *mid)
38{
39 int rc = 0;
40 struct smb_hdr *in_buf = (struct smb_hdr *)buf;
41
42 /* -4 for RFC1001 length and +2 for BCC field */
43 in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
44 in_buf->Command = SMB_COM_NT_CANCEL;
45 in_buf->WordCount = 0;
46 put_bcc(0, in_buf);
47
48 mutex_lock(&server->srv_mutex);
49 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
50 if (rc) {
51 mutex_unlock(&server->srv_mutex);
52 return rc;
53 }
54 rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
55 mutex_unlock(&server->srv_mutex);
56
57 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
58 in_buf->Mid, rc);
59
60 return rc;
61}
62
63static bool
64cifs_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
65{
66 return ob1->netfid == ob2->netfid;
67}
68
69static unsigned int
70cifs_read_data_offset(char *buf)
71{
72 READ_RSP *rsp = (READ_RSP *)buf;
73 return le16_to_cpu(rsp->DataOffset);
74}
75
76static unsigned int
77cifs_read_data_length(char *buf)
78{
79 READ_RSP *rsp = (READ_RSP *)buf;
80 return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
81 le16_to_cpu(rsp->DataLength);
82}
83
84static struct mid_q_entry *
85cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
86{
87 struct smb_hdr *buf = (struct smb_hdr *)buffer;
88 struct mid_q_entry *mid;
89
90 spin_lock(&GlobalMid_Lock);
91 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
92 if (mid->mid == buf->Mid &&
93 mid->mid_state == MID_REQUEST_SUBMITTED &&
94 le16_to_cpu(mid->command) == buf->Command) {
95 spin_unlock(&GlobalMid_Lock);
96 return mid;
97 }
98 }
99 spin_unlock(&GlobalMid_Lock);
100 return NULL;
101}
102
103static void
104cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add)
105{
106 spin_lock(&server->req_lock);
107 server->credits += add;
108 server->in_flight--;
109 spin_unlock(&server->req_lock);
110 wake_up(&server->request_q);
111}
112
113static void
114cifs_set_credits(struct TCP_Server_Info *server, const int val)
115{
116 spin_lock(&server->req_lock);
117 server->credits = val;
118 server->oplocks = val > 1 ? enable_oplocks : false;
119 spin_unlock(&server->req_lock);
120}
121
122static int *
123cifs_get_credits_field(struct TCP_Server_Info *server)
124{
125 return &server->credits;
126}
127
128struct smb_version_operations smb1_operations = {
129 .send_cancel = send_nt_cancel,
130 .compare_fids = cifs_compare_fids,
131 .setup_request = cifs_setup_request,
132 .check_receive = cifs_check_receive,
133 .add_credits = cifs_add_credits,
134 .set_credits = cifs_set_credits,
135 .get_credits_field = cifs_get_credits_field,
136 .read_data_offset = cifs_read_data_offset,
137 .read_data_length = cifs_read_data_length,
138 .map_error = map_smb_to_linux_error,
139 .find_mid = cifs_find_mid,
140 .check_message = checkSMB,
141 .dump_detail = cifs_dump_detail,
142 .is_oplock_break = is_valid_oplock_break,
143};
144
145struct smb_version_values smb1_values = {
146 .version_string = SMB1_VERSION_STRING,
147 .large_lock_type = LOCKING_ANDX_LARGE_FILES,
148 .exclusive_lock_type = 0,
149 .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
150 .unlock_lock_type = 0,
151 .header_size = sizeof(struct smb_hdr),
152 .max_header_size = MAX_CIFS_HDR_SIZE,
153 .read_rsp_size = sizeof(READ_RSP),
154};
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
new file mode 100644
index 000000000000..f065e89756a1
--- /dev/null
+++ b/fs/cifs/smb2ops.c
@@ -0,0 +1,27 @@
1/*
2 * SMB2 version specific operations
3 *
4 * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License v2 as published
8 * by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "cifsglob.h"
21
22struct smb_version_operations smb21_operations = {
23};
24
25struct smb_version_values smb21_values = {
26 .version_string = SMB21_VERSION_STRING,
27};
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0961336513d5..1b36ffe6a47b 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -304,7 +304,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int optype,
304static int 304static int
305wait_for_free_request(struct TCP_Server_Info *server, const int optype) 305wait_for_free_request(struct TCP_Server_Info *server, const int optype)
306{ 306{
307 return wait_for_free_credits(server, optype, get_credits_field(server)); 307 return wait_for_free_credits(server, optype,
308 server->ops->get_credits_field(server));
308} 309}
309 310
310static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, 311static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
@@ -396,7 +397,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
396 rc = cifs_setup_async_request(server, iov, nvec, &mid); 397 rc = cifs_setup_async_request(server, iov, nvec, &mid);
397 if (rc) { 398 if (rc) {
398 mutex_unlock(&server->srv_mutex); 399 mutex_unlock(&server->srv_mutex);
399 cifs_add_credits(server, 1); 400 add_credits(server, 1);
400 wake_up(&server->request_q); 401 wake_up(&server->request_q);
401 return rc; 402 return rc;
402 } 403 }
@@ -418,7 +419,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
418 return rc; 419 return rc;
419out_err: 420out_err:
420 delete_mid(mid); 421 delete_mid(mid);
421 cifs_add_credits(server, 1); 422 add_credits(server, 1);
422 wake_up(&server->request_q); 423 wake_up(&server->request_q);
423 return rc; 424 return rc;
424} 425}
@@ -483,41 +484,11 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
483 return rc; 484 return rc;
484} 485}
485 486
486/* 487static inline int
487 * An NT cancel request header looks just like the original request except: 488send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
488 *
489 * The Command is SMB_COM_NT_CANCEL
490 * The WordCount is zeroed out
491 * The ByteCount is zeroed out
492 *
493 * This function mangles an existing request buffer into a
494 * SMB_COM_NT_CANCEL request and then sends it.
495 */
496static int
497send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
498 struct mid_q_entry *mid)
499{ 489{
500 int rc = 0; 490 return server->ops->send_cancel ?
501 491 server->ops->send_cancel(server, buf, mid) : 0;
502 /* -4 for RFC1001 length and +2 for BCC field */
503 in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
504 in_buf->Command = SMB_COM_NT_CANCEL;
505 in_buf->WordCount = 0;
506 put_bcc(0, in_buf);
507
508 mutex_lock(&server->srv_mutex);
509 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
510 if (rc) {
511 mutex_unlock(&server->srv_mutex);
512 return rc;
513 }
514 rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
515 mutex_unlock(&server->srv_mutex);
516
517 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
518 in_buf->Mid, rc);
519
520 return rc;
521} 492}
522 493
523int 494int
@@ -544,7 +515,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
544 return map_smb_to_linux_error(mid->resp_buf, log_error); 515 return map_smb_to_linux_error(mid->resp_buf, log_error);
545} 516}
546 517
547static int 518int
548cifs_setup_request(struct cifs_ses *ses, struct kvec *iov, 519cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
549 unsigned int nvec, struct mid_q_entry **ret_mid) 520 unsigned int nvec, struct mid_q_entry **ret_mid)
550{ 521{
@@ -607,12 +578,12 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
607 578
608 mutex_lock(&ses->server->srv_mutex); 579 mutex_lock(&ses->server->srv_mutex);
609 580
610 rc = cifs_setup_request(ses, iov, n_vec, &midQ); 581 rc = ses->server->ops->setup_request(ses, iov, n_vec, &midQ);
611 if (rc) { 582 if (rc) {
612 mutex_unlock(&ses->server->srv_mutex); 583 mutex_unlock(&ses->server->srv_mutex);
613 cifs_small_buf_release(buf); 584 cifs_small_buf_release(buf);
614 /* Update # of requests on wire to server */ 585 /* Update # of requests on wire to server */
615 cifs_add_credits(ses->server, 1); 586 add_credits(ses->server, 1);
616 return rc; 587 return rc;
617 } 588 }
618 589
@@ -636,13 +607,13 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
636 607
637 rc = wait_for_response(ses->server, midQ); 608 rc = wait_for_response(ses->server, midQ);
638 if (rc != 0) { 609 if (rc != 0) {
639 send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ); 610 send_cancel(ses->server, buf, midQ);
640 spin_lock(&GlobalMid_Lock); 611 spin_lock(&GlobalMid_Lock);
641 if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 612 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
642 midQ->callback = DeleteMidQEntry; 613 midQ->callback = DeleteMidQEntry;
643 spin_unlock(&GlobalMid_Lock); 614 spin_unlock(&GlobalMid_Lock);
644 cifs_small_buf_release(buf); 615 cifs_small_buf_release(buf);
645 cifs_add_credits(ses->server, 1); 616 add_credits(ses->server, 1);
646 return rc; 617 return rc;
647 } 618 }
648 spin_unlock(&GlobalMid_Lock); 619 spin_unlock(&GlobalMid_Lock);
@@ -652,7 +623,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
652 623
653 rc = cifs_sync_mid_result(midQ, ses->server); 624 rc = cifs_sync_mid_result(midQ, ses->server);
654 if (rc != 0) { 625 if (rc != 0) {
655 cifs_add_credits(ses->server, 1); 626 add_credits(ses->server, 1);
656 return rc; 627 return rc;
657 } 628 }
658 629
@@ -670,14 +641,15 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
670 else 641 else
671 *pRespBufType = CIFS_SMALL_BUFFER; 642 *pRespBufType = CIFS_SMALL_BUFFER;
672 643
673 rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR); 644 rc = ses->server->ops->check_receive(midQ, ses->server,
645 flags & CIFS_LOG_ERROR);
674 646
675 /* mark it so buf will not be freed by delete_mid */ 647 /* mark it so buf will not be freed by delete_mid */
676 if ((flags & CIFS_NO_RESP) == 0) 648 if ((flags & CIFS_NO_RESP) == 0)
677 midQ->resp_buf = NULL; 649 midQ->resp_buf = NULL;
678out: 650out:
679 delete_mid(midQ); 651 delete_mid(midQ);
680 cifs_add_credits(ses->server, 1); 652 add_credits(ses->server, 1);
681 653
682 return rc; 654 return rc;
683} 655}
@@ -727,7 +699,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
727 if (rc) { 699 if (rc) {
728 mutex_unlock(&ses->server->srv_mutex); 700 mutex_unlock(&ses->server->srv_mutex);
729 /* Update # of requests on wire to server */ 701 /* Update # of requests on wire to server */
730 cifs_add_credits(ses->server, 1); 702 add_credits(ses->server, 1);
731 return rc; 703 return rc;
732 } 704 }
733 705
@@ -753,13 +725,13 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
753 725
754 rc = wait_for_response(ses->server, midQ); 726 rc = wait_for_response(ses->server, midQ);
755 if (rc != 0) { 727 if (rc != 0) {
756 send_nt_cancel(ses->server, in_buf, midQ); 728 send_cancel(ses->server, in_buf, midQ);
757 spin_lock(&GlobalMid_Lock); 729 spin_lock(&GlobalMid_Lock);
758 if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 730 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
759 /* no longer considered to be "in-flight" */ 731 /* no longer considered to be "in-flight" */
760 midQ->callback = DeleteMidQEntry; 732 midQ->callback = DeleteMidQEntry;
761 spin_unlock(&GlobalMid_Lock); 733 spin_unlock(&GlobalMid_Lock);
762 cifs_add_credits(ses->server, 1); 734 add_credits(ses->server, 1);
763 return rc; 735 return rc;
764 } 736 }
765 spin_unlock(&GlobalMid_Lock); 737 spin_unlock(&GlobalMid_Lock);
@@ -767,7 +739,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
767 739
768 rc = cifs_sync_mid_result(midQ, ses->server); 740 rc = cifs_sync_mid_result(midQ, ses->server);
769 if (rc != 0) { 741 if (rc != 0) {
770 cifs_add_credits(ses->server, 1); 742 add_credits(ses->server, 1);
771 return rc; 743 return rc;
772 } 744 }
773 745
@@ -783,7 +755,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
783 rc = cifs_check_receive(midQ, ses->server, 0); 755 rc = cifs_check_receive(midQ, ses->server, 0);
784out: 756out:
785 delete_mid(midQ); 757 delete_mid(midQ);
786 cifs_add_credits(ses->server, 1); 758 add_credits(ses->server, 1);
787 759
788 return rc; 760 return rc;
789} 761}
@@ -898,7 +870,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
898 if (in_buf->Command == SMB_COM_TRANSACTION2) { 870 if (in_buf->Command == SMB_COM_TRANSACTION2) {
899 /* POSIX lock. We send a NT_CANCEL SMB to cause the 871 /* POSIX lock. We send a NT_CANCEL SMB to cause the
900 blocking lock to return. */ 872 blocking lock to return. */
901 rc = send_nt_cancel(ses->server, in_buf, midQ); 873 rc = send_cancel(ses->server, in_buf, midQ);
902 if (rc) { 874 if (rc) {
903 delete_mid(midQ); 875 delete_mid(midQ);
904 return rc; 876 return rc;
@@ -919,7 +891,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
919 891
920 rc = wait_for_response(ses->server, midQ); 892 rc = wait_for_response(ses->server, midQ);
921 if (rc) { 893 if (rc) {
922 send_nt_cancel(ses->server, in_buf, midQ); 894 send_cancel(ses->server, in_buf, midQ);
923 spin_lock(&GlobalMid_Lock); 895 spin_lock(&GlobalMid_Lock);
924 if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 896 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
925 /* no longer considered to be "in-flight" */ 897 /* no longer considered to be "in-flight" */