aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-10-21 11:39:12 -0400
committerSteve French <sfrench@us.ibm.com>2005-10-21 11:39:12 -0400
commitd6d3f5bc68be3c4ab84e6f1f9db92291da671504 (patch)
tree76946c62cc7d1a18203fba50ea87fd567387f637
parentac9b9c667c2e1194e22ebe0a441ae1c37aaa9b90 (diff)
parent23e7dd7d95f6fdc167a6d6ddea79ced0af33bbff (diff)
Merge with /pub/scm/linux/kernel/git/sfrench/cifs-2.6.git/
-rw-r--r--fs/cifs/AUTHORS4
-rw-r--r--fs/cifs/CHANGES60
-rw-r--r--fs/cifs/README24
-rw-r--r--fs/cifs/TODO50
-rw-r--r--fs/cifs/asn1.c3
-rw-r--r--fs/cifs/cifs_debug.c103
-rw-r--r--fs/cifs/cifs_debug.h5
-rw-r--r--fs/cifs/cifs_fs_sb.h3
-rw-r--r--fs/cifs/cifsfs.c80
-rw-r--r--fs/cifs/cifsfs.h3
-rw-r--r--fs/cifs/cifsglob.h98
-rw-r--r--fs/cifs/cifspdu.h174
-rw-r--r--fs/cifs/cifsproto.h32
-rw-r--r--fs/cifs/cifssmb.c659
-rw-r--r--fs/cifs/connect.c219
-rw-r--r--fs/cifs/dir.c108
-rw-r--r--fs/cifs/fcntl.c12
-rw-r--r--fs/cifs/file.c466
-rw-r--r--fs/cifs/inode.c150
-rw-r--r--fs/cifs/link.c5
-rw-r--r--fs/cifs/misc.c123
-rw-r--r--fs/cifs/netmisc.c15
-rw-r--r--fs/cifs/readdir.c84
-rw-r--r--fs/cifs/transport.c331
24 files changed, 2266 insertions, 545 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index 72fdc10dfdd7..8848e4dfa026 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -32,6 +32,10 @@ Domen Puncer
32Jesper Juhl (in particular for lots of whitespace/formatting cleanup) 32Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
33Vince Negri and Dave Stahl (for finding an important caching bug) 33Vince Negri and Dave Stahl (for finding an important caching bug)
34Adrian Bunk (kcalloc cleanups) 34Adrian Bunk (kcalloc cleanups)
35Miklos Szeredi
36Kazeon team for various fixes especially for 2.4 version.
37Asser Ferno (Change Notify support)
38Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
35 39
36Test case and Bug Report contributors 40Test case and Bug Report contributors
37------------------------------------- 41-------------------------------------
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 3196d4c4eed3..5bab24f59053 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,52 @@
1Version 1.39
2------------
3Defer close of a file handle slightly if pending writes depend on that file handle
4(this reduces the EBADF bad file handle errors that can be logged under heavy
5stress on writes).
6
7Version 1.38
8------------
9Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket)
10to be smaller at first (but increasing) so large write performance performance
11over GigE is better. Do not hang thread on illegal byte range lock response
12from Windows (Windows can send an RFC1001 size which does not match smb size) by
13allowing an SMBs TCP length to be up to a few bytes longer than it should be.
14wsize and rsize can now be larger than negotiated buffer size if server
15supports large readx/writex, even when directio mount flag not specified.
16Write size will in many cases now be 16K instead of 4K which greatly helps
17file copy performance on lightly loaded networks. Fix oops in dnotify
18when experimental config flag enabled. Make cifsFYI more granular.
19
20Version 1.37
21------------
22Fix readdir caching when unlink removes file in current search buffer,
23and this is followed by a rewind search to just before the deleted entry.
24Do not attempt to set ctime unless atime and/or mtime change requested
25(most servers throw it away anyway). Fix length check of received smbs
26to be more accurate. Fix big endian problem with mapchars mount option,
27and with a field returned by statfs.
28
29Version 1.36
30------------
31Add support for mounting to older pre-CIFS servers such as Windows9x and ME.
32For these older servers, add option for passing netbios name of server in
33on mount (servernetbiosname). Add suspend support for power management, to
34avoid cifsd thread preventing software suspend from working.
35Add mount option for disabling the default behavior of sending byte range lock
36requests to the server (necessary for certain applications which break with
37mandatory lock behavior such as Evolution), and also mount option for
38requesting case insensitive matching for path based requests (requesting
39case sensitive is the default).
40
1Version 1.35 41Version 1.35
2------------ 42------------
3Add writepage performance improvements. Fix path name conversions 43Add writepage performance improvements. Fix path name conversions
4for long filenames on mounts which were done with "mapchars" mount option 44for long filenames on mounts which were done with "mapchars" mount option
5specified. 45specified. Ensure multiplex ids do not collide. Fix case in which
46rmmod can oops if done soon after last unmount. Fix truncated
47search (readdir) output when resume filename was a long filename.
48Fix filename conversion when mapchars mount option was specified and
49filename was a long filename.
6 50
7Version 1.34 51Version 1.34
8------------ 52------------
@@ -11,7 +55,7 @@ Do not oops if root user kills cifs oplock kernel thread or
11kills the cifsd thread (NB: killing the cifs kernel threads is not 55kills the cifsd thread (NB: killing the cifs kernel threads is not
12recommended, unmount and rmmod cifs will kill them when they are 56recommended, unmount and rmmod cifs will kill them when they are
13no longer needed). Fix readdir to ASCII servers (ie older servers 57no longer needed). Fix readdir to ASCII servers (ie older servers
14which do not support Unicode) and also require asterik. 58which do not support Unicode) and also require asterisk.
15Fix out of memory case in which data could be written one page 59Fix out of memory case in which data could be written one page
16off in the page cache. 60off in the page cache.
17 61
@@ -101,7 +145,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call.
101 145
102Version 1.25 146Version 1.25
103------------ 147------------
104Fix internationlization problem in cifs readdir with filenames that map to 148Fix internationalization problem in cifs readdir with filenames that map to
105longer UTF8 strings than the string on the wire was in Unicode. Add workaround 149longer UTF8 strings than the string on the wire was in Unicode. Add workaround
106for readdir to netapp servers. Fix search rewind (seek into readdir to return 150for readdir to netapp servers. Fix search rewind (seek into readdir to return
107non-consecutive entries). Do not do readdir when server negotiates 151non-consecutive entries). Do not do readdir when server negotiates
@@ -276,7 +320,7 @@ Fix caching problem when files opened by multiple clients in which
276page cache could contain stale data, and write through did 320page cache could contain stale data, and write through did
277not occur often enough while file was still open when read ahead 321not occur often enough while file was still open when read ahead
278(read oplock) not allowed. Treat "sep=" when first mount option 322(read oplock) not allowed. Treat "sep=" when first mount option
279as an overrride of comma as the default separator between mount 323as an override of comma as the default separator between mount
280options. 324options.
281 325
282Version 1.01 326Version 1.01
@@ -286,7 +330,7 @@ Allow passwords longer than 16 bytes. Allow null password string.
286Version 1.00 330Version 1.00
287------------ 331------------
288Gracefully clean up failed mounts when attempting to mount to servers such as 332Gracefully clean up failed mounts when attempting to mount to servers such as
289Windows 98 that terminate tcp sessions during prototocol negotiation. Handle 333Windows 98 that terminate tcp sessions during protocol negotiation. Handle
290embedded commas in mount parsing of passwords. 334embedded commas in mount parsing of passwords.
291 335
292Version 0.99 336Version 0.99
@@ -295,7 +339,7 @@ Invalidate local inode cached pages on oplock break and when last file
295instance is closed so that the client does not continue using stale local 339instance is closed so that the client does not continue using stale local
296copy rather than later modified server copy of file. Do not reconnect 340copy rather than later modified server copy of file. Do not reconnect
297when server drops the tcp session prematurely before negotiate 341when server drops the tcp session prematurely before negotiate
298protocol response. Fix oops in roepen_file when dentry freed. Allow 342protocol response. Fix oops in reopen_file when dentry freed. Allow
299the support for CIFS Unix Extensions to be disabled via proc interface. 343the support for CIFS Unix Extensions to be disabled via proc interface.
300 344
301Version 0.98 345Version 0.98
@@ -637,7 +681,7 @@ versions of 2.4 kernel (now builds and works again on kernels at least as early
637Version 0.41 681Version 0.41
638------------ 682------------
639Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked 683Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
640files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked. 684files now return the correct number of links on fstat as they are repeatedly linked and unlinked.
641 685
642Version 0.40 686Version 0.40
643------------ 687------------
@@ -704,7 +748,7 @@ session)
704and cleaned them up and made them more consistent with other cifs functions. 748and cleaned them up and made them more consistent with other cifs functions.
705 749
7067) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways 7507) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
707(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed, 751(with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
708nor is the symlink support using the Unix extensions 752nor is the symlink support using the Unix extensions
709 753
7108) Started adding the readlink and follow_link code 7548) Started adding the readlink and follow_link code
diff --git a/fs/cifs/README b/fs/cifs/README
index 34b0cf7111f3..bb90941826ad 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -294,8 +294,10 @@ A partial list of the supported mount options follows:
294 during the local client kernel build will be used. 294 during the local client kernel build will be used.
295 If server does not support Unicode, this parameter is 295 If server does not support Unicode, this parameter is
296 unused. 296 unused.
297 rsize default read size 297 rsize default read size (usually 16K)
298 wsize default write size 298 wsize default write size (usually 16K, 32K is often better over GigE)
299 maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
300 pages)
299 rw mount the network share read-write (note that the 301 rw mount the network share read-write (note that the
300 server may still consider the share read-only) 302 server may still consider the share read-only)
301 ro mount network share read-only 303 ro mount network share read-only
@@ -407,6 +409,13 @@ A partial list of the supported mount options follows:
407 This has no effect if the server does not support 409 This has no effect if the server does not support
408 Unicode on the wire. 410 Unicode on the wire.
409 nomapchars Do not translate any of these seven characters (default). 411 nomapchars Do not translate any of these seven characters (default).
412 nocase Request case insensitive path name matching (case
413 sensitive is the default if the server suports it).
414 nobrl Do not send byte range lock requests to the server.
415 This is necessary for certain applications that break
416 with cifs style mandatory byte range locks (and most
417 cifs servers do not yet support requesting advisory
418 byte range locks).
410 remount remount the share (often used to change from ro to rw mounts 419 remount remount the share (often used to change from ro to rw mounts
411 or vice versa) 420 or vice versa)
412 421
@@ -473,9 +482,16 @@ These experimental features and tracing can be enabled by changing flags in
473kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable 482kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
474tracing to the kernel message log type: 483tracing to the kernel message log type:
475 484
476 echo 1 > /proc/fs/cifs/cifsFYI 485 echo 7 > /proc/fs/cifs/cifsFYI
477 486
478and for more extensive tracing including the start of smb requests and responses 487cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel
488logging of various informational messages. 2 enables logging of non-zero
489SMB return codes while 4 enables logging of requests that take longer
490than one second to complete (except for byte range lock requests).
491Setting it to 4 requires defining CONFIG_CIFS_STATS2 manually in the
492source code (typically by setting it in the beginning of cifsglob.h),
493and setting it to seven enables all three. Finally, tracing
494the start of smb requests and responses can be enabled via:
479 495
480 echo 1 > /proc/fs/cifs/traceSMB 496 echo 1 > /proc/fs/cifs/traceSMB
481 497
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index 8cc881694e29..c909298d11ed 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
1version 1.34 April 29, 2005 1version 1.37 October 9, 2005
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -7,14 +7,14 @@ Contributions are welcome. There are plenty of opportunities
7for visible, important contributions to this module. Here 7for visible, important contributions to this module. Here
8is a partial list of the known problems and missing features: 8is a partial list of the known problems and missing features:
9 9
10a) Support for SecurityDescriptors for chmod/chgrp/chown so 10a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown
11these can be supported for Windows servers 11so that these operations can be supported to Windows servers
12 12
13b) Better pam/winbind integration (e.g. to handle uid mapping 13b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS
14better) 14SecurityDescriptors
15 15
16c) multi-user mounts - multiplexed sessionsetups over single vc 16c) Better pam/winbind integration (e.g. to handle uid mapping
17(ie tcp session) - more testing needed 17better)
18 18
19d) Kerberos/SPNEGO session setup support - (started) 19d) Kerberos/SPNEGO session setup support - (started)
20 20
@@ -29,12 +29,17 @@ f) Directory entry caching relies on a 1 second timer, rather than
29using FindNotify or equivalent. - (started) 29using FindNotify or equivalent. - (started)
30 30
31g) A few byte range testcases fail due to POSIX vs. Windows/CIFS 31g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
32style byte range lock differences 32style byte range lock differences. Save byte range locks so
33reconnect can replay them.
33 34
34h) quota support 35h) Support unlock all (unlock 0,MAX_OFFSET)
36by unlocking all known byte range locks that we locked on the file.
35 37
36j) finish writepages support (multi-page write behind for improved 38i) quota support (needs minor kernel change since quota calls
37performance) and syncpage 39to make it to network filesystems or deviceless filesystems)
40
41j) investigate sync behavior (including syncpage) and check
42for proper behavior of intr/nointr
38 43
39k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the 44k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
40extra copy in/out of the socket buffers in some cases. 45extra copy in/out of the socket buffers in some cases.
@@ -57,20 +62,18 @@ p) Add support for storing symlink and fifo info to Windows servers
57in the Extended Attribute format their SFU clients would recognize. 62in the Extended Attribute format their SFU clients would recognize.
58 63
59q) Finish fcntl D_NOTIFY support so kde and gnome file list windows 64q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
60will autorefresh (started) 65will autorefresh (partially complete by Asser). Needs minor kernel
66vfs change to support removing D_NOTIFY on a file.
61 67
62r) Add GUI tool to configure /proc/fs/cifs settings and for display of 68r) Add GUI tool to configure /proc/fs/cifs settings and for display of
63the CIFS statistics (started) 69the CIFS statistics (started)
64 70
65q) implement support for security and trusted categories of xattrs 71s) implement support for security and trusted categories of xattrs
66(requires minor protocol extension) to enable better support for SELINUX 72(requires minor protocol extension) to enable better support for SELINUX
67 73
68r) Implement O_DIRECT flag on open (already supported on mount) 74t) Implement O_DIRECT flag on open (already supported on mount)
69
70s) Allow remapping of last remaining character (\) to +0xF000 which
71(this character is valid for POSIX but not for Windows)
72 75
73t) Create UID mapping facility so server UIDs can be mapped on a per 76u) Create UID mapping facility so server UIDs can be mapped on a per
74mount or a per server basis to client UIDs or nobody if no mapping 77mount or a per server basis to client UIDs or nobody if no mapping
75exists. This is helpful when Unix extensions are negotiated to 78exists. This is helpful when Unix extensions are negotiated to
76allow better permission checking when UIDs differ on the server 79allow better permission checking when UIDs differ on the server
@@ -78,6 +81,17 @@ and client. Add new protocol request to the CIFS protocol
78standard for asking the server for the corresponding name of a 81standard for asking the server for the corresponding name of a
79particular uid. 82particular uid.
80 83
84v) Add support for CIFS Unix and also the newer POSIX extensions to the
85server side for Samba 4.
86
87w) Finish up the dos time conversion routines needed to return old server
88time to the client (default time, of now or time 0 is used now for these
89very old servers)
90
91x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
92
93y) Finish testing of Windows 9x/Windows ME server support (started).
94
81KNOWN BUGS (updated April 29, 2005) 95KNOWN BUGS (updated April 29, 2005)
82==================================== 96====================================
83See http://bugzilla.samba.org - search on product "CifsVFS" for 97See http://bugzilla.samba.org - search on product "CifsVFS" for
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index e02010dd73ec..98539e2afe81 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -191,7 +191,8 @@ asn1_header_decode(struct asn1_ctx *ctx,
191 unsigned char **eoc, 191 unsigned char **eoc,
192 unsigned int *cls, unsigned int *con, unsigned int *tag) 192 unsigned int *cls, unsigned int *con, unsigned int *tag)
193{ 193{
194 unsigned int def, len; 194 unsigned int def = 0;
195 unsigned int len = 0;
195 196
196 if (!asn1_id_decode(ctx, cls, con, tag)) 197 if (!asn1_id_decode(ctx, cls, con, tag))
197 return 0; 198 return 0;
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 4061e43471c1..22a444a3fe4c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -81,6 +81,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
81 buf += length; 81 buf += length;
82 length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION); 82 length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
83 buf += length; 83 buf += length;
84 length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
85 buf += length;
84 length = sprintf(buf, "Servers:"); 86 length = sprintf(buf, "Servers:");
85 buf += length; 87 buf += length;
86 88
@@ -97,7 +99,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
97 } else { 99 } else {
98 length = 100 length =
99 sprintf(buf, 101 sprintf(buf,
100 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", 102 "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
101 i, ses->serverName, ses->serverDomain, 103 i, ses->serverName, ses->serverDomain,
102 atomic_read(&ses->inUse), 104 atomic_read(&ses->inUse),
103 ses->serverOS, ses->serverNOS, 105 ses->serverOS, ses->serverNOS,
@@ -105,12 +107,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
105 buf += length; 107 buf += length;
106 } 108 }
107 if(ses->server) { 109 if(ses->server) {
108 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", 110 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
109 ses->server->tcpStatus, 111 ses->server->tcpStatus,
110 atomic_read(&ses->server->socketUseCount), 112 atomic_read(&ses->server->socketUseCount),
111 ses->server->secMode, 113 ses->server->secMode,
112 atomic_read(&ses->server->inFlight)); 114 atomic_read(&ses->server->inFlight));
113 115
116#ifdef CONFIG_CIFS_STATS2
117 buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
118 atomic_read(&ses->server->inSend),
119 atomic_read(&ses->server->num_waiters));
120#endif
121
114 length = sprintf(buf, "\nMIDs:\n"); 122 length = sprintf(buf, "\nMIDs:\n");
115 buf += length; 123 buf += length;
116 124
@@ -149,7 +157,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
149 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); 157 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
150 length = 158 length =
151 sprintf(buf, 159 sprintf(buf,
152 "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d", 160 "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
153 i, tcon->treeName, 161 i, tcon->treeName,
154 atomic_read(&tcon->useCount), 162 atomic_read(&tcon->useCount),
155 tcon->nativeFileSystem, 163 tcon->nativeFileSystem,
@@ -195,6 +203,49 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
195} 203}
196 204
197#ifdef CONFIG_CIFS_STATS 205#ifdef CONFIG_CIFS_STATS
206
207static int
208cifs_stats_write(struct file *file, const char __user *buffer,
209 unsigned long count, void *data)
210{
211 char c;
212 int rc;
213 struct list_head *tmp;
214 struct cifsTconInfo *tcon;
215
216 rc = get_user(c, buffer);
217 if (rc)
218 return rc;
219
220 if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
221 read_lock(&GlobalSMBSeslock);
222 list_for_each(tmp, &GlobalTreeConnectionList) {
223 tcon = list_entry(tmp, struct cifsTconInfo,
224 cifsConnectionList);
225 atomic_set(&tcon->num_smbs_sent, 0);
226 atomic_set(&tcon->num_writes, 0);
227 atomic_set(&tcon->num_reads, 0);
228 atomic_set(&tcon->num_oplock_brks, 0);
229 atomic_set(&tcon->num_opens, 0);
230 atomic_set(&tcon->num_closes, 0);
231 atomic_set(&tcon->num_deletes, 0);
232 atomic_set(&tcon->num_mkdirs, 0);
233 atomic_set(&tcon->num_rmdirs, 0);
234 atomic_set(&tcon->num_renames, 0);
235 atomic_set(&tcon->num_t2renames, 0);
236 atomic_set(&tcon->num_ffirst, 0);
237 atomic_set(&tcon->num_fnext, 0);
238 atomic_set(&tcon->num_fclose, 0);
239 atomic_set(&tcon->num_hardlinks, 0);
240 atomic_set(&tcon->num_symlinks, 0);
241 atomic_set(&tcon->num_locks, 0);
242 }
243 read_unlock(&GlobalSMBSeslock);
244 }
245
246 return count;
247}
248
198static int 249static int
199cifs_stats_read(char *buf, char **beginBuffer, off_t offset, 250cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
200 int count, int *eof, void *data) 251 int count, int *eof, void *data)
@@ -254,35 +305,51 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
254 buf += sprintf(buf, "\tDISCONNECTED "); 305 buf += sprintf(buf, "\tDISCONNECTED ");
255 length += 14; 306 length += 14;
256 } 307 }
257 item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d", 308 item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
258 atomic_read(&tcon->num_smbs_sent), 309 atomic_read(&tcon->num_smbs_sent),
259 atomic_read(&tcon->num_oplock_brks)); 310 atomic_read(&tcon->num_oplock_brks));
260 buf += item_length; 311 buf += item_length;
261 length += item_length; 312 length += item_length;
262 item_length = sprintf(buf,"\nReads: %d Bytes %lld", 313 item_length = sprintf(buf, "\nReads: %d Bytes: %lld",
263 atomic_read(&tcon->num_reads), 314 atomic_read(&tcon->num_reads),
264 (long long)(tcon->bytes_read)); 315 (long long)(tcon->bytes_read));
265 buf += item_length; 316 buf += item_length;
266 length += item_length; 317 length += item_length;
267 item_length = sprintf(buf,"\nWrites: %d Bytes: %lld", 318 item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
268 atomic_read(&tcon->num_writes), 319 atomic_read(&tcon->num_writes),
269 (long long)(tcon->bytes_written)); 320 (long long)(tcon->bytes_written));
321 buf += item_length;
322 length += item_length;
323 item_length = sprintf(buf,
324 "\nLocks: %d HardLinks: %d Symlinks: %d",
325 atomic_read(&tcon->num_locks),
326 atomic_read(&tcon->num_hardlinks),
327 atomic_read(&tcon->num_symlinks));
328 buf += item_length;
329 length += item_length;
330
331 item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
332 atomic_read(&tcon->num_opens),
333 atomic_read(&tcon->num_closes),
334 atomic_read(&tcon->num_deletes));
270 buf += item_length; 335 buf += item_length;
271 length += item_length; 336 length += item_length;
272 item_length = sprintf(buf, 337 item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d",
273 "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
274 atomic_read(&tcon->num_opens),
275 atomic_read(&tcon->num_deletes),
276 atomic_read(&tcon->num_mkdirs), 338 atomic_read(&tcon->num_mkdirs),
277 atomic_read(&tcon->num_rmdirs)); 339 atomic_read(&tcon->num_rmdirs));
278 buf += item_length; 340 buf += item_length;
279 length += item_length; 341 length += item_length;
280 item_length = sprintf(buf, 342 item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
281 "\nRenames: %d T2 Renames %d",
282 atomic_read(&tcon->num_renames), 343 atomic_read(&tcon->num_renames),
283 atomic_read(&tcon->num_t2renames)); 344 atomic_read(&tcon->num_t2renames));
284 buf += item_length; 345 buf += item_length;
285 length += item_length; 346 length += item_length;
347 item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
348 atomic_read(&tcon->num_ffirst),
349 atomic_read(&tcon->num_fnext),
350 atomic_read(&tcon->num_fclose));
351 buf += item_length;
352 length += item_length;
286 } 353 }
287 read_unlock(&GlobalSMBSeslock); 354 read_unlock(&GlobalSMBSeslock);
288 355
@@ -341,8 +408,10 @@ cifs_proc_init(void)
341 cifs_debug_data_read, NULL); 408 cifs_debug_data_read, NULL);
342 409
343#ifdef CONFIG_CIFS_STATS 410#ifdef CONFIG_CIFS_STATS
344 create_proc_read_entry("Stats", 0, proc_fs_cifs, 411 pde = create_proc_read_entry("Stats", 0, proc_fs_cifs,
345 cifs_stats_read, NULL); 412 cifs_stats_read, NULL);
413 if (pde)
414 pde->write_proc = cifs_stats_write;
346#endif 415#endif
347 pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, 416 pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
348 cifsFYI_read, NULL); 417 cifsFYI_read, NULL);
@@ -360,7 +429,7 @@ cifs_proc_init(void)
360 if (pde) 429 if (pde)
361 pde->write_proc = oplockEnabled_write; 430 pde->write_proc = oplockEnabled_write;
362 431
363 pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs, 432 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
364 quotaEnabled_read, NULL); 433 quotaEnabled_read, NULL);
365 if (pde) 434 if (pde)
366 pde->write_proc = quotaEnabled_write; 435 pde->write_proc = quotaEnabled_write;
@@ -419,7 +488,7 @@ cifs_proc_clean(void)
419 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 488 remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
420 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); 489 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
421 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); 490 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
422 remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs); 491 remove_proc_entry("Experimental",proc_fs_cifs);
423 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); 492 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
424 remove_proc_entry("cifs", proc_root_fs); 493 remove_proc_entry("cifs", proc_root_fs);
425} 494}
@@ -459,6 +528,8 @@ cifsFYI_write(struct file *file, const char __user *buffer,
459 cifsFYI = 0; 528 cifsFYI = 0;
460 else if (c == '1' || c == 'y' || c == 'Y') 529 else if (c == '1' || c == 'y' || c == 'Y')
461 cifsFYI = 1; 530 cifsFYI = 1;
531 else if((c > '1') && (c <= '9'))
532 cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
462 533
463 return count; 534 return count;
464} 535}
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index bf24d2828f68..4304d9dcfb6c 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -26,6 +26,9 @@
26void cifs_dump_mem(char *label, void *data, int length); 26void cifs_dump_mem(char *label, void *data, int length);
27extern int traceSMB; /* flag which enables the function below */ 27extern int traceSMB; /* flag which enables the function below */
28void dump_smb(struct smb_hdr *, int); 28void dump_smb(struct smb_hdr *, int);
29#define CIFS_INFO 0x01
30#define CIFS_RC 0x02
31#define CIFS_TIMER 0x04
29 32
30/* 33/*
31 * debug ON 34 * debug ON
@@ -36,7 +39,7 @@ void dump_smb(struct smb_hdr *, int);
36 39
37/* information message: e.g., configuration, major event */ 40/* information message: e.g., configuration, major event */
38extern int cifsFYI; 41extern int cifsFYI;
39#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) 42#define cifsfyi(format,arg...) if (cifsFYI & CIFS_INFO) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
40 43
41#define cFYI(button,prspec) if (button) cifsfyi prspec 44#define cFYI(button,prspec) if (button) cifsfyi prspec
42 45
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ec00d61d5308..f799f6f0e729 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,6 +24,9 @@
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ 26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
27#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
28#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
29#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
27 30
28struct cifs_sb_info { 31struct cifs_sb_info {
29 struct cifsTconInfo *tcon; /* primary mount */ 32 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 1ebf7dafc1d7..877095a1192a 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -59,6 +59,8 @@ unsigned int ntlmv2_support = 0;
59unsigned int sign_CIFS_PDUs = 1; 59unsigned int sign_CIFS_PDUs = 1;
60extern struct task_struct * oplockThread; /* remove sparse warning */ 60extern struct task_struct * oplockThread; /* remove sparse warning */
61struct task_struct * oplockThread = NULL; 61struct task_struct * oplockThread = NULL;
62extern struct task_struct * dnotifyThread; /* remove sparse warning */
63struct task_struct * dnotifyThread = NULL;
62unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 64unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
63module_param(CIFSMaxBufSize, int, 0); 65module_param(CIFSMaxBufSize, int, 0);
64MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); 66MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -73,6 +75,7 @@ module_param(cifs_max_pending, int, 0);
73MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); 75MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
74 76
75static DECLARE_COMPLETION(cifs_oplock_exited); 77static DECLARE_COMPLETION(cifs_oplock_exited);
78static DECLARE_COMPLETION(cifs_dnotify_exited);
76 79
77extern mempool_t *cifs_sm_req_poolp; 80extern mempool_t *cifs_sm_req_poolp;
78extern mempool_t *cifs_req_poolp; 81extern mempool_t *cifs_req_poolp;
@@ -202,6 +205,10 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
202#endif /* CIFS_EXPERIMENTAL */ 205#endif /* CIFS_EXPERIMENTAL */
203 rc = CIFSSMBQFSInfo(xid, pTcon, buf); 206 rc = CIFSSMBQFSInfo(xid, pTcon, buf);
204 207
208 /* Old Windows servers do not support level 103, retry with level
209 one if old server failed the previous call */
210 if(rc)
211 rc = SMBOldQFSInfo(xid, pTcon, buf);
205 /* 212 /*
206 int f_type; 213 int f_type;
207 __fsid_t f_fsid; 214 __fsid_t f_fsid;
@@ -253,7 +260,7 @@ cifs_alloc_inode(struct super_block *sb)
253 cifs_inode->clientCanCacheAll = FALSE; 260 cifs_inode->clientCanCacheAll = FALSE;
254 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE; 261 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
255 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 262 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
256 263 cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
257 INIT_LIST_HEAD(&cifs_inode->openFileList); 264 INIT_LIST_HEAD(&cifs_inode->openFileList);
258 return &cifs_inode->vfs_inode; 265 return &cifs_inode->vfs_inode;
259} 266}
@@ -398,6 +405,34 @@ static struct quotactl_ops cifs_quotactl_ops = {
398}; 405};
399#endif 406#endif
400 407
408static void cifs_umount_begin(struct super_block * sblock)
409{
410 struct cifs_sb_info *cifs_sb;
411 struct cifsTconInfo * tcon;
412
413 cifs_sb = CIFS_SB(sblock);
414 if(cifs_sb == NULL)
415 return;
416
417 tcon = cifs_sb->tcon;
418 if(tcon == NULL)
419 return;
420 down(&tcon->tconSem);
421 if (atomic_read(&tcon->useCount) == 1)
422 tcon->tidStatus = CifsExiting;
423 up(&tcon->tconSem);
424
425 if(tcon->ses && tcon->ses->server)
426 {
427 cERROR(1,("wake up tasks now - umount begin not complete"));
428 wake_up_all(&tcon->ses->server->request_q);
429 }
430/* BB FIXME - finish add checks for tidStatus BB */
431
432 return;
433}
434
435
401static int cifs_remount(struct super_block *sb, int *flags, char *data) 436static int cifs_remount(struct super_block *sb, int *flags, char *data)
402{ 437{
403 *flags |= MS_NODIRATIME; 438 *flags |= MS_NODIRATIME;
@@ -415,7 +450,7 @@ struct super_operations cifs_super_ops = {
415 unless later we add lazy close of inodes or unless the kernel forgets to call 450 unless later we add lazy close of inodes or unless the kernel forgets to call
416 us with the same number of releases (closes) as opens */ 451 us with the same number of releases (closes) as opens */
417 .show_options = cifs_show_options, 452 .show_options = cifs_show_options,
418/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */ 453/* .umount_begin = cifs_umount_begin, */ /* BB finish in the future */
419 .remount_fs = cifs_remount, 454 .remount_fs = cifs_remount,
420}; 455};
421 456
@@ -783,9 +818,7 @@ static int cifs_oplock_thread(void * dummyarg)
783 do { 818 do {
784 if (try_to_freeze()) 819 if (try_to_freeze())
785 continue; 820 continue;
786 set_current_state(TASK_INTERRUPTIBLE);
787 821
788 schedule_timeout(1*HZ);
789 spin_lock(&GlobalMid_Lock); 822 spin_lock(&GlobalMid_Lock);
790 if(list_empty(&GlobalOplock_Q)) { 823 if(list_empty(&GlobalOplock_Q)) {
791 spin_unlock(&GlobalMid_Lock); 824 spin_unlock(&GlobalMid_Lock);
@@ -834,10 +867,27 @@ static int cifs_oplock_thread(void * dummyarg)
834 } 867 }
835 } else 868 } else
836 spin_unlock(&GlobalMid_Lock); 869 spin_unlock(&GlobalMid_Lock);
870 set_current_state(TASK_INTERRUPTIBLE);
871 schedule_timeout(1); /* yield in case q were corrupt */
837 } 872 }
838 } while(!signal_pending(current)); 873 } while(!signal_pending(current));
839 complete_and_exit (&cifs_oplock_exited, 0);
840 oplockThread = NULL; 874 oplockThread = NULL;
875 complete_and_exit (&cifs_oplock_exited, 0);
876}
877
878static int cifs_dnotify_thread(void * dummyarg)
879{
880 daemonize("cifsdnotifyd");
881 allow_signal(SIGTERM);
882
883 dnotifyThread = current;
884 do {
885 if(try_to_freeze())
886 continue;
887 set_current_state(TASK_INTERRUPTIBLE);
888 schedule_timeout(39*HZ);
889 } while(!signal_pending(current));
890 complete_and_exit (&cifs_dnotify_exited, 0);
841} 891}
842 892
843static int __init 893static int __init
@@ -851,6 +901,10 @@ init_cifs(void)
851 INIT_LIST_HEAD(&GlobalSMBSessionList); 901 INIT_LIST_HEAD(&GlobalSMBSessionList);
852 INIT_LIST_HEAD(&GlobalTreeConnectionList); 902 INIT_LIST_HEAD(&GlobalTreeConnectionList);
853 INIT_LIST_HEAD(&GlobalOplock_Q); 903 INIT_LIST_HEAD(&GlobalOplock_Q);
904#ifdef CONFIG_CIFS_EXPERIMENTAL
905 INIT_LIST_HEAD(&GlobalDnotifyReqList);
906 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
907#endif
854/* 908/*
855 * Initialize Global counters 909 * Initialize Global counters
856 */ 910 */
@@ -886,10 +940,16 @@ init_cifs(void)
886 if (!rc) { 940 if (!rc) {
887 rc = (int)kernel_thread(cifs_oplock_thread, NULL, 941 rc = (int)kernel_thread(cifs_oplock_thread, NULL,
888 CLONE_FS | CLONE_FILES | CLONE_VM); 942 CLONE_FS | CLONE_FILES | CLONE_VM);
889 if(rc > 0) 943 if(rc > 0) {
890 return 0; 944 rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
891 else 945 CLONE_FS | CLONE_FILES | CLONE_VM);
946 if(rc > 0)
947 return 0;
948 else
949 cERROR(1,("error %d create dnotify thread", rc));
950 } else {
892 cERROR(1,("error %d create oplock thread",rc)); 951 cERROR(1,("error %d create oplock thread",rc));
952 }
893 } 953 }
894 cifs_destroy_request_bufs(); 954 cifs_destroy_request_bufs();
895 } 955 }
@@ -918,6 +978,10 @@ exit_cifs(void)
918 send_sig(SIGTERM, oplockThread, 1); 978 send_sig(SIGTERM, oplockThread, 1);
919 wait_for_completion(&cifs_oplock_exited); 979 wait_for_completion(&cifs_oplock_exited);
920 } 980 }
981 if(dnotifyThread) {
982 send_sig(SIGTERM, dnotifyThread, 1);
983 wait_for_completion(&cifs_dnotify_exited);
984 }
921} 985}
922 986
923MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); 987MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 1fd21f66f243..1223fa81dbd2 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -81,6 +81,7 @@ extern int cifs_dir_notify(struct file *, unsigned long arg);
81 81
82/* Functions related to dir entries */ 82/* Functions related to dir entries */
83extern struct dentry_operations cifs_dentry_ops; 83extern struct dentry_operations cifs_dentry_ops;
84extern struct dentry_operations cifs_ci_dentry_ops;
84 85
85/* Functions related to symlinks */ 86/* Functions related to symlinks */
86extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 87extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
@@ -96,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 97extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97extern int cifs_ioctl (struct inode * inode, struct file * filep, 98extern int cifs_ioctl (struct inode * inode, struct file * filep,
98 unsigned int command, unsigned long arg); 99 unsigned int command, unsigned long arg);
99#define CIFS_VERSION "1.35" 100#define CIFS_VERSION "1.39"
100#endif /* _CIFSFS_H */ 101#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 81babab265e1..1ba08f8c5bc4 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -110,8 +110,9 @@ enum protocolEnum {
110 */ 110 */
111 111
112struct TCP_Server_Info { 112struct TCP_Server_Info {
113 char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */ 113 /* 15 character server name + 0x20 16th byte indicating type = srv */
114 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */ 114 char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
115 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
115 struct socket *ssocket; 116 struct socket *ssocket;
116 union { 117 union {
117 struct sockaddr_in sockAddr; 118 struct sockaddr_in sockAddr;
@@ -122,13 +123,17 @@ struct TCP_Server_Info {
122 struct list_head pending_mid_q; 123 struct list_head pending_mid_q;
123 void *Server_NlsInfo; /* BB - placeholder for future NLS info */ 124 void *Server_NlsInfo; /* BB - placeholder for future NLS info */
124 unsigned short server_codepage; /* codepage for the server */ 125 unsigned short server_codepage; /* codepage for the server */
125 unsigned long ip_address; /* IP addr for the server if known */ 126 unsigned long ip_address; /* IP addr for the server if known */
126 enum protocolEnum protocolType; 127 enum protocolEnum protocolType;
127 char versionMajor; 128 char versionMajor;
128 char versionMinor; 129 char versionMinor;
129 unsigned svlocal:1; /* local server or remote */ 130 unsigned svlocal:1; /* local server or remote */
130 atomic_t socketUseCount; /* number of open cifs sessions on socket */ 131 atomic_t socketUseCount; /* number of open cifs sessions on socket */
131 atomic_t inFlight; /* number of requests on the wire to server */ 132 atomic_t inFlight; /* number of requests on the wire to server */
133#ifdef CONFIG_CIFS_STATS2
134 atomic_t inSend; /* requests trying to send */
135 atomic_t num_waiters; /* blocked waiting to get in sendrecv */
136#endif
132 enum statusEnum tcpStatus; /* what we think the status is */ 137 enum statusEnum tcpStatus; /* what we think the status is */
133 struct semaphore tcpSem; 138 struct semaphore tcpSem;
134 struct task_struct *tsk; 139 struct task_struct *tsk;
@@ -147,8 +152,10 @@ struct TCP_Server_Info {
147 /* (returned on Negotiate */ 152 /* (returned on Negotiate */
148 int capabilities; /* allow selective disabling of caps by smb sess */ 153 int capabilities; /* allow selective disabling of caps by smb sess */
149 __u16 timeZone; 154 __u16 timeZone;
155 __u16 CurrentMid; /* multiplex id - rotating counter */
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 156 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */ 157 /* 16th byte of RFC1001 workstation name is always null */
158 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
152 __u32 sequence_number; /* needed for CIFS PDU signature */ 159 __u32 sequence_number; /* needed for CIFS PDU signature */
153 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 160 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
154}; 161};
@@ -214,19 +221,41 @@ struct cifsTconInfo {
214 atomic_t num_reads; 221 atomic_t num_reads;
215 atomic_t num_oplock_brks; 222 atomic_t num_oplock_brks;
216 atomic_t num_opens; 223 atomic_t num_opens;
224 atomic_t num_closes;
217 atomic_t num_deletes; 225 atomic_t num_deletes;
218 atomic_t num_mkdirs; 226 atomic_t num_mkdirs;
219 atomic_t num_rmdirs; 227 atomic_t num_rmdirs;
220 atomic_t num_renames; 228 atomic_t num_renames;
221 atomic_t num_t2renames; 229 atomic_t num_t2renames;
230 atomic_t num_ffirst;
231 atomic_t num_fnext;
232 atomic_t num_fclose;
233 atomic_t num_hardlinks;
234 atomic_t num_symlinks;
235 atomic_t num_locks;
236#ifdef CONFIG_CIFS_STATS2
237 unsigned long long time_writes;
238 unsigned long long time_reads;
239 unsigned long long time_opens;
240 unsigned long long time_deletes;
241 unsigned long long time_closes;
242 unsigned long long time_mkdirs;
243 unsigned long long time_rmdirs;
244 unsigned long long time_renames;
245 unsigned long long time_t2renames;
246 unsigned long long time_ffirst;
247 unsigned long long time_fnext;
248 unsigned long long time_fclose;
249#endif /* CONFIG_CIFS_STATS2 */
222 __u64 bytes_read; 250 __u64 bytes_read;
223 __u64 bytes_written; 251 __u64 bytes_written;
224 spinlock_t stat_lock; 252 spinlock_t stat_lock;
225#endif 253#endif /* CONFIG_CIFS_STATS */
226 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 254 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
227 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ 255 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
228 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 256 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
229 unsigned retry:1; 257 unsigned retry:1;
258 unsigned nocase:1;
230 /* BB add field for back pointer to sb struct? */ 259 /* BB add field for back pointer to sb struct? */
231}; 260};
232 261
@@ -270,6 +299,7 @@ struct cifsFileInfo {
270 struct inode * pInode; /* needed for oplock break */ 299 struct inode * pInode; /* needed for oplock break */
271 unsigned closePend:1; /* file is marked to close */ 300 unsigned closePend:1; /* file is marked to close */
272 unsigned invalidHandle:1; /* file closed via session abend */ 301 unsigned invalidHandle:1; /* file closed via session abend */
302 atomic_t wrtPending; /* handle in use - defer close */
273 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 303 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
274 char * search_resume_name; /* BB removeme BB */ 304 char * search_resume_name; /* BB removeme BB */
275 unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */ 305 unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
@@ -306,6 +336,41 @@ CIFS_SB(struct super_block *sb)
306 return sb->s_fs_info; 336 return sb->s_fs_info;
307} 337}
308 338
339static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
340{
341 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
342 return '/';
343 else
344 return '\\';
345}
346
347#ifdef CONFIG_CIFS_STATS
348#define cifs_stats_inc atomic_inc
349
350static inline void cifs_stats_bytes_written(struct cifsTconInfo *tcon,
351 unsigned int bytes)
352{
353 if (bytes) {
354 spin_lock(&tcon->stat_lock);
355 tcon->bytes_written += bytes;
356 spin_unlock(&tcon->stat_lock);
357 }
358}
359
360static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
361 unsigned int bytes)
362{
363 spin_lock(&tcon->stat_lock);
364 tcon->bytes_read += bytes;
365 spin_unlock(&tcon->stat_lock);
366}
367#else
368
369#define cifs_stats_inc(field) do {} while(0)
370#define cifs_stats_bytes_written(tcon, bytes) do {} while(0)
371#define cifs_stats_bytes_read(tcon, bytes) do {} while(0)
372
373#endif
309 374
310/* one of these for every pending CIFS request to the server */ 375/* one of these for every pending CIFS request to the server */
311struct mid_q_entry { 376struct mid_q_entry {
@@ -313,7 +378,11 @@ struct mid_q_entry {
313 __u16 mid; /* multiplex id */ 378 __u16 mid; /* multiplex id */
314 __u16 pid; /* process id */ 379 __u16 pid; /* process id */
315 __u32 sequence_number; /* for CIFS signing */ 380 __u32 sequence_number; /* for CIFS signing */
316 struct timeval when_sent; /* time when smb sent */ 381 unsigned long when_alloc; /* when mid was created */
382#ifdef CONFIG_CIFS_STATS2
383 unsigned long when_sent; /* time when smb send finished */
384 unsigned long when_received; /* when demux complete (taken off wire) */
385#endif
317 struct cifsSesInfo *ses; /* smb was sent to this server */ 386 struct cifsSesInfo *ses; /* smb was sent to this server */
318 struct task_struct *tsk; /* task waiting for response */ 387 struct task_struct *tsk; /* task waiting for response */
319 struct smb_hdr *resp_buf; /* response buffer */ 388 struct smb_hdr *resp_buf; /* response buffer */
@@ -331,6 +400,20 @@ struct oplock_q_entry {
331 __u16 netfid; 400 __u16 netfid;
332}; 401};
333 402
403/* for pending dnotify requests */
404struct dir_notify_req {
405 struct list_head lhead;
406 __le16 Pid;
407 __le16 PidHigh;
408 __u16 Mid;
409 __u16 Tid;
410 __u16 Uid;
411 __u16 netfid;
412 __u32 filter; /* CompletionFilter (for multishot) */
413 int multishot;
414 struct file * pfile;
415};
416
334#define MID_FREE 0 417#define MID_FREE 0
335#define MID_REQUEST_ALLOCATED 1 418#define MID_REQUEST_ALLOCATED 1
336#define MID_REQUEST_SUBMITTED 2 419#define MID_REQUEST_SUBMITTED 2
@@ -399,6 +482,9 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
399 482
400GLOBAL_EXTERN struct list_head GlobalOplock_Q; 483GLOBAL_EXTERN struct list_head GlobalOplock_Q;
401 484
485GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
486GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */
487
402/* 488/*
403 * Global transaction id (XID) information 489 * Global transaction id (XID) information
404 */ 490 */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index aede6a813167..193f06eb43f9 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -36,9 +36,11 @@
36#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ 36#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
37#define SMB_COM_DELETE 0x06 /* trivial response */ 37#define SMB_COM_DELETE 0x06 /* trivial response */
38#define SMB_COM_RENAME 0x07 /* trivial response */ 38#define SMB_COM_RENAME 0x07 /* trivial response */
39#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
39#define SMB_COM_SETATTR 0x09 /* trivial response */ 40#define SMB_COM_SETATTR 0x09 /* trivial response */
40#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ 41#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
41#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ 42#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
43#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
42#define SMB_COM_READ_ANDX 0x2E 44#define SMB_COM_READ_ANDX 0x2E
43#define SMB_COM_WRITE_ANDX 0x2F 45#define SMB_COM_WRITE_ANDX 0x2F
44#define SMB_COM_TRANSACTION2 0x32 46#define SMB_COM_TRANSACTION2 0x32
@@ -52,6 +54,7 @@
52#define SMB_COM_NT_TRANSACT 0xA0 54#define SMB_COM_NT_TRANSACT 0xA0
53#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 55#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
54#define SMB_COM_NT_CREATE_ANDX 0xA2 56#define SMB_COM_NT_CREATE_ANDX 0xA2
57#define SMB_COM_NT_CANCEL 0xA4 /* no response */
55#define SMB_COM_NT_RENAME 0xA5 /* trivial response */ 58#define SMB_COM_NT_RENAME 0xA5 /* trivial response */
56 59
57/* Transact2 subcommand codes */ 60/* Transact2 subcommand codes */
@@ -59,6 +62,7 @@
59#define TRANS2_FIND_FIRST 0x01 62#define TRANS2_FIND_FIRST 0x01
60#define TRANS2_FIND_NEXT 0x02 63#define TRANS2_FIND_NEXT 0x02
61#define TRANS2_QUERY_FS_INFORMATION 0x03 64#define TRANS2_QUERY_FS_INFORMATION 0x03
65#define TRANS2_SET_FS_INFORMATION 0x04
62#define TRANS2_QUERY_PATH_INFORMATION 0x05 66#define TRANS2_QUERY_PATH_INFORMATION 0x05
63#define TRANS2_SET_PATH_INFORMATION 0x06 67#define TRANS2_SET_PATH_INFORMATION 0x06
64#define TRANS2_QUERY_FILE_INFORMATION 0x07 68#define TRANS2_QUERY_FILE_INFORMATION 0x07
@@ -267,10 +271,18 @@
267/* CreateOptions */ 271/* CreateOptions */
268#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ 272#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
269#define CREATE_WRITE_THROUGH 0x00000002 273#define CREATE_WRITE_THROUGH 0x00000002
270#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ 274#define CREATE_SEQUENTIAL 0x00000004
275#define CREATE_SYNC_ALERT 0x00000010
276#define CREATE_ASYNC_ALERT 0x00000020
277#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
278#define CREATE_NO_EA_KNOWLEDGE 0x00000200
279#define CREATE_EIGHT_DOT_THREE 0x00000400
271#define CREATE_RANDOM_ACCESS 0x00000800 280#define CREATE_RANDOM_ACCESS 0x00000800
272#define CREATE_DELETE_ON_CLOSE 0x00001000 281#define CREATE_DELETE_ON_CLOSE 0x00001000
282#define CREATE_OPEN_BY_ID 0x00002000
273#define OPEN_REPARSE_POINT 0x00200000 283#define OPEN_REPARSE_POINT 0x00200000
284#define CREATE_OPTIONS_MASK 0x007FFFFF
285#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
274 286
275/* ImpersonationLevel flags */ 287/* ImpersonationLevel flags */
276#define SECURITY_ANONYMOUS 0 288#define SECURITY_ANONYMOUS 0
@@ -614,6 +626,7 @@ typedef struct smb_com_findclose_req {
614} FINDCLOSE_REQ; 626} FINDCLOSE_REQ;
615 627
616/* OpenFlags */ 628/* OpenFlags */
629#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
617#define REQ_OPLOCK 0x00000002 630#define REQ_OPLOCK 0x00000002
618#define REQ_BATCHOPLOCK 0x00000004 631#define REQ_BATCHOPLOCK 0x00000004
619#define REQ_OPENDIRONLY 0x00000008 632#define REQ_OPENDIRONLY 0x00000008
@@ -669,6 +682,62 @@ typedef struct smb_com_open_rsp {
669 __u16 ByteCount; /* bct = 0 */ 682 __u16 ByteCount; /* bct = 0 */
670} OPEN_RSP; 683} OPEN_RSP;
671 684
685/* format of legacy open request */
686typedef struct smb_com_openx_req {
687 struct smb_hdr hdr; /* wct = 15 */
688 __u8 AndXCommand;
689 __u8 AndXReserved;
690 __le16 AndXOffset;
691 __le16 OpenFlags;
692 __le16 Mode;
693 __le16 Sattr; /* search attributes */
694 __le16 FileAttributes; /* dos attrs */
695 __le32 CreateTime; /* os2 format */
696 __le16 OpenFunction;
697 __le32 EndOfFile;
698 __le32 Timeout;
699 __le32 Reserved;
700 __le16 ByteCount; /* file name follows */
701 char fileName[1];
702} OPENX_REQ;
703
704typedef struct smb_com_openx_rsp {
705 struct smb_hdr hdr; /* wct = 15 */
706 __u8 AndXCommand;
707 __u8 AndXReserved;
708 __le16 AndXOffset;
709 __u16 Fid;
710 __le16 FileAttributes;
711 __le32 LastWriteTime; /* os2 format */
712 __le32 EndOfFile;
713 __le16 Access;
714 __le16 FileType;
715 __le16 IPCState;
716 __le16 Action;
717 __u32 FileId;
718 __u16 Reserved;
719 __u16 ByteCount;
720} OPENX_RSP;
721
722/* Legacy write request for older servers */
723typedef struct smb_com_writex_req {
724 struct smb_hdr hdr; /* wct = 12 */
725 __u8 AndXCommand;
726 __u8 AndXReserved;
727 __le16 AndXOffset;
728 __u16 Fid;
729 __le32 OffsetLow;
730 __u32 Reserved; /* Timeout */
731 __le16 WriteMode; /* 1 = write through */
732 __le16 Remaining;
733 __le16 Reserved2;
734 __le16 DataLengthLow;
735 __le16 DataOffset;
736 __le16 ByteCount;
737 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
738 char Data[0];
739} WRITEX_REQ;
740
672typedef struct smb_com_write_req { 741typedef struct smb_com_write_req {
673 struct smb_hdr hdr; /* wct = 14 */ 742 struct smb_hdr hdr; /* wct = 14 */
674 __u8 AndXCommand; 743 __u8 AndXCommand;
@@ -700,6 +769,21 @@ typedef struct smb_com_write_rsp {
700 __u16 ByteCount; 769 __u16 ByteCount;
701} WRITE_RSP; 770} WRITE_RSP;
702 771
772/* legacy read request for older servers */
773typedef struct smb_com_readx_req {
774 struct smb_hdr hdr; /* wct = 10 */
775 __u8 AndXCommand;
776 __u8 AndXReserved;
777 __le16 AndXOffset;
778 __u16 Fid;
779 __le32 OffsetLow;
780 __le16 MaxCount;
781 __le16 MinCount; /* obsolete */
782 __le32 Reserved;
783 __le16 Remaining;
784 __le16 ByteCount;
785} READX_REQ;
786
703typedef struct smb_com_read_req { 787typedef struct smb_com_read_req {
704 struct smb_hdr hdr; /* wct = 12 */ 788 struct smb_hdr hdr; /* wct = 12 */
705 __u8 AndXCommand; 789 __u8 AndXCommand;
@@ -876,6 +960,22 @@ typedef struct smb_com_create_directory_rsp {
876 __u16 ByteCount; /* bct = 0 */ 960 __u16 ByteCount; /* bct = 0 */
877} CREATE_DIRECTORY_RSP; 961} CREATE_DIRECTORY_RSP;
878 962
963typedef struct smb_com_query_information_req {
964 struct smb_hdr hdr; /* wct = 0 */
965 __le16 ByteCount; /* 1 + namelen + 1 */
966 __u8 BufferFormat; /* 4 = ASCII */
967 unsigned char FileName[1];
968} QUERY_INFORMATION_REQ;
969
970typedef struct smb_com_query_information_rsp {
971 struct smb_hdr hdr; /* wct = 10 */
972 __le16 attr;
973 __le32 last_write_time;
974 __le32 size;
975 __u16 reserved[5];
976 __le16 ByteCount; /* bcc = 0 */
977} QUERY_INFORMATION_RSP;
978
879typedef struct smb_com_setattr_req { 979typedef struct smb_com_setattr_req {
880 struct smb_hdr hdr; /* wct = 8 */ 980 struct smb_hdr hdr; /* wct = 8 */
881 __le16 attr; 981 __le16 attr;
@@ -1411,6 +1511,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
1411 __u8 Pad; /* may be three bytes *//* followed by data area */ 1511 __u8 Pad; /* may be three bytes *//* followed by data area */
1412} TRANSACTION2_QFSI_RSP; 1512} TRANSACTION2_QFSI_RSP;
1413 1513
1514
1515/* SETFSInfo Levels */
1516#define SMB_SET_CIFS_UNIX_INFO 0x200
1517typedef struct smb_com_transaction2_setfsi_req {
1518 struct smb_hdr hdr; /* wct = 15 */
1519 __le16 TotalParameterCount;
1520 __le16 TotalDataCount;
1521 __le16 MaxParameterCount;
1522 __le16 MaxDataCount;
1523 __u8 MaxSetupCount;
1524 __u8 Reserved;
1525 __le16 Flags;
1526 __le32 Timeout;
1527 __u16 Reserved2;
1528 __le16 ParameterCount; /* 4 */
1529 __le16 ParameterOffset;
1530 __le16 DataCount; /* 12 */
1531 __le16 DataOffset;
1532 __u8 SetupCount; /* one */
1533 __u8 Reserved3;
1534 __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
1535 __le16 ByteCount;
1536 __u8 Pad;
1537 __u16 FileNum; /* Parameters start. */
1538 __le16 InformationLevel;/* Parameters end. */
1539 __le16 ClientUnixMajor; /* Data start. */
1540 __le16 ClientUnixMinor;
1541 __le64 ClientUnixCap; /* Data end */
1542} TRANSACTION2_SETFSI_REQ;
1543
1544typedef struct smb_com_transaction2_setfsi_rsp {
1545 struct smb_hdr hdr; /* wct = 10 */
1546 struct trans2_resp t2;
1547 __u16 ByteCount;
1548} TRANSACTION2_SETFSI_RSP;
1549
1550
1414typedef struct smb_com_transaction2_get_dfs_refer_req { 1551typedef struct smb_com_transaction2_get_dfs_refer_req {
1415 struct smb_hdr hdr; /* wct = 15 */ 1552 struct smb_hdr hdr; /* wct = 15 */
1416 __le16 TotalParameterCount; 1553 __le16 TotalParameterCount;
@@ -1547,16 +1684,32 @@ typedef struct {
1547} FILE_SYSTEM_INFO; /* size info, level 0x103 */ 1684} FILE_SYSTEM_INFO; /* size info, level 0x103 */
1548 1685
1549typedef struct { 1686typedef struct {
1687 __le32 fsid;
1688 __le32 SectorsPerAllocationUnit;
1689 __le32 TotalAllocationUnits;
1690 __le32 FreeAllocationUnits;
1691 __le16 BytesPerSector;
1692} FILE_SYSTEM_ALLOC_INFO;
1693
1694typedef struct {
1550 __le16 MajorVersionNumber; 1695 __le16 MajorVersionNumber;
1551 __le16 MinorVersionNumber; 1696 __le16 MinorVersionNumber;
1552 __le64 Capability; 1697 __le64 Capability;
1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1698} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1699
1700/* Version numbers for CIFS UNIX major and minor. */
1701#define CIFS_UNIX_MAJOR_VERSION 1
1702#define CIFS_UNIX_MINOR_VERSION 0
1703
1554/* Linux/Unix extensions capability flags */ 1704/* Linux/Unix extensions capability flags */
1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1705#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1706#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1707#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1708#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1709#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
1710
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1711#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1712
1560typedef struct { 1713typedef struct {
1561 /* For undefined recommended transfer size return -1 in that field */ 1714 /* For undefined recommended transfer size return -1 in that field */
1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1715 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
@@ -1907,18 +2060,17 @@ struct data_blob {
1907 perhaps add a CreateDevice - to create Pipes and other special .inodes 2060 perhaps add a CreateDevice - to create Pipes and other special .inodes
1908 Also note POSIX open flags 2061 Also note POSIX open flags
1909 2) Close - to return the last write time to do cache across close more safely 2062 2) Close - to return the last write time to do cache across close more safely
1910 3) PosixQFSInfo - to return statfs info 2063 3) FindFirst return unique inode number - what about resume key, two
1911 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes) 2064 forms short (matches readdir) and full (enough info to cache inodes)
1912 5) Mkdir - set mode 2065 4) Mkdir - set mode
1913 2066
1914 And under consideration: 2067 And under consideration:
1915 6) FindClose2 (return nanosecond timestamp ??) 2068 5) FindClose2 (return nanosecond timestamp ??)
1916 7) Use nanosecond timestamps throughout all time fields if 2069 6) Use nanosecond timestamps throughout all time fields if
1917 corresponding attribute flag is set 2070 corresponding attribute flag is set
1918 8) sendfile - handle based copy 2071 7) sendfile - handle based copy
1919 9) Direct i/o 2072 8) Direct i/o
1920 10) "POSIX ACL" support 2073 9) Misc fcntls?
1921 11) Misc fcntls?
1922 2074
1923 what about fixing 64 bit alignment 2075 what about fixing 64 bit alignment
1924 2076
@@ -1974,7 +2126,7 @@ struct data_blob {
1974 2126
1975 */ 2127 */
1976 2128
1977/* xsymlink is a symlink format that can be used 2129/* xsymlink is a symlink format (used by MacOS) that can be used
1978 to save symlink info in a regular file when 2130 to save symlink info in a regular file when
1979 mounted to operating systems that do not 2131 mounted to operating systems that do not
1980 support the cifs Unix extensions or EAs (for xattr 2132 support the cifs Unix extensions or EAs (for xattr
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ea239dea571e..d301149b1bb0 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -47,19 +47,24 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
47 struct smb_hdr * /* input */ , 47 struct smb_hdr * /* input */ ,
48 struct smb_hdr * /* out */ , 48 struct smb_hdr * /* out */ ,
49 int * /* bytes returned */ , const int long_op); 49 int * /* bytes returned */ , const int long_op);
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct kvec *, int /* nvec */,
52 int * /* bytes returned */ , const int long_op);
50extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
51extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
52extern int is_valid_oplock_break(struct smb_hdr *smb); 55extern int is_valid_oplock_break(struct smb_hdr *smb);
53extern int is_size_safe_to_change(struct cifsInodeInfo *); 56extern int is_size_safe_to_change(struct cifsInodeInfo *);
57extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
54extern unsigned int smbCalcSize(struct smb_hdr *ptr); 58extern unsigned int smbCalcSize(struct smb_hdr *ptr);
59extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
55extern int decode_negTokenInit(unsigned char *security_blob, int length, 60extern int decode_negTokenInit(unsigned char *security_blob, int length,
56 enum securityEnum *secType); 61 enum securityEnum *secType);
57extern int cifs_inet_pton(int, char * source, void *dst); 62extern int cifs_inet_pton(int, char * source, void *dst);
58extern int map_smb_to_linux_error(struct smb_hdr *smb); 63extern int map_smb_to_linux_error(struct smb_hdr *smb);
59extern void header_assemble(struct smb_hdr *, char /* command */ , 64extern void header_assemble(struct smb_hdr *, char /* command */ ,
60 const struct cifsTconInfo *, int /* specifies length 65 const struct cifsTconInfo *, int /* length of
61 of fixed section (word count) in two byte units */ 66 fixed section (word count) in two byte units */);
62 ); 67extern __u16 GetNextMid(struct TCP_Server_Info *server);
63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 68extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
64 struct cifsTconInfo *); 69 struct cifsTconInfo *);
65extern void DeleteOplockQEntry(struct oplock_q_entry *); 70extern void DeleteOplockQEntry(struct oplock_q_entry *);
@@ -89,7 +94,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
89 94
90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 95extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
91 const char *searchName, const struct nls_table *nls_codepage, 96 const char *searchName, const struct nls_table *nls_codepage,
92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map); 97 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
93 98
94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 99extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
95 __u16 searchHandle, struct cifs_search_info * psrch_inf); 100 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -101,6 +106,10 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
101 const unsigned char *searchName, 106 const unsigned char *searchName,
102 FILE_ALL_INFO * findData, 107 FILE_ALL_INFO * findData,
103 const struct nls_table *nls_codepage, int remap); 108 const struct nls_table *nls_codepage, int remap);
109extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
110 const unsigned char *searchName,
111 FILE_ALL_INFO * findData,
112 const struct nls_table *nls_codepage, int remap);
104 113
105extern int CIFSSMBUnixQPathInfo(const int xid, 114extern int CIFSSMBUnixQPathInfo(const int xid,
106 struct cifsTconInfo *tcon, 115 struct cifsTconInfo *tcon,
@@ -125,6 +134,11 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
125 int remap); 134 int remap);
126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 135extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
127 struct kstatfs *FSData); 136 struct kstatfs *FSData);
137extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
138 struct kstatfs *FSData);
139extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
140 __u64 cap);
141
128extern int CIFSSMBQFSAttributeInfo(const int xid, 142extern int CIFSSMBQFSAttributeInfo(const int xid,
129 struct cifsTconInfo *tcon); 143 struct cifsTconInfo *tcon);
130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); 144extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
@@ -207,6 +221,11 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
207 const int access_flags, const int omode, 221 const int access_flags, const int omode,
208 __u16 * netfid, int *pOplock, FILE_ALL_INFO *, 222 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
209 const struct nls_table *nls_codepage, int remap); 223 const struct nls_table *nls_codepage, int remap);
224extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
225 const char *fileName, const int disposition,
226 const int access_flags, const int omode,
227 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
228 const struct nls_table *nls_codepage, int remap);
210extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 229extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
211 const int smb_file_id); 230 const int smb_file_id);
212 231
@@ -222,7 +241,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
222extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 241extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
223 const int netfid, const unsigned int count, 242 const int netfid, const unsigned int count,
224 const __u64 offset, unsigned int *nbytes, 243 const __u64 offset, unsigned int *nbytes,
225 const char __user *buf,const int long_op); 244 struct kvec *iov, const int nvec, const int long_op);
226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 245extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
227 const unsigned char *searchName, __u64 * inode_number, 246 const unsigned char *searchName, __u64 * inode_number,
228 const struct nls_table *nls_codepage, 247 const struct nls_table *nls_codepage,
@@ -264,7 +283,8 @@ extern int CIFSSMBCopy(int xid,
264 int remap_special_chars); 283 int remap_special_chars);
265extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 284extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
266 const int notify_subdirs,const __u16 netfid, 285 const int notify_subdirs,const __u16 netfid,
267 __u32 filter, const struct nls_table *nls_codepage); 286 __u32 filter, struct file * file, int multishot,
287 const struct nls_table *nls_codepage);
268extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 288extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
269 const unsigned char *searchName, char * EAData, 289 const unsigned char *searchName, char * EAData,
270 size_t bufsize, const struct nls_table *nls_codepage, 290 size_t bufsize, const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..9312bfc56682 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -125,6 +125,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon 125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
126 , nls_codepage); 126 , nls_codepage);
127 up(&tcon->ses->sesSem); 127 up(&tcon->ses->sesSem);
128 /* BB FIXME add code to check if wsize needs
129 update due to negotiated smb buffer size
130 shrinking */
128 if(rc == 0) 131 if(rc == 0)
129 atomic_inc(&tconInfoReconnectCount); 132 atomic_inc(&tconInfoReconnectCount);
130 133
@@ -166,11 +169,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
166 169
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); 170 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168 171
169#ifdef CONFIG_CIFS_STATS 172 if(tcon != NULL)
170 if(tcon != NULL) { 173 cifs_stats_inc(&tcon->num_smbs_sent);
171 atomic_inc(&tcon->num_smbs_sent); 174
172 }
173#endif /* CONFIG_CIFS_STATS */
174 return rc; 175 return rc;
175} 176}
176 177
@@ -222,6 +223,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
222 rc = CIFSTCon(0, tcon->ses, tcon->treeName, 223 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
223 tcon, nls_codepage); 224 tcon, nls_codepage);
224 up(&tcon->ses->sesSem); 225 up(&tcon->ses->sesSem);
226 /* BB FIXME add code to check if wsize needs
227 update due to negotiated smb buffer size
228 shrinking */
225 if(rc == 0) 229 if(rc == 0)
226 atomic_inc(&tconInfoReconnectCount); 230 atomic_inc(&tconInfoReconnectCount);
227 231
@@ -269,11 +273,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 273 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
270 wct /*wct */ ); 274 wct /*wct */ );
271 275
272#ifdef CONFIG_CIFS_STATS 276 if(tcon != NULL)
273 if(tcon != NULL) { 277 cifs_stats_inc(&tcon->num_smbs_sent);
274 atomic_inc(&tcon->num_smbs_sent); 278
275 }
276#endif /* CONFIG_CIFS_STATS */
277 return rc; 279 return rc;
278} 280}
279 281
@@ -330,7 +332,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
330 (void **) &pSMB, (void **) &pSMBr); 332 (void **) &pSMB, (void **) &pSMBr);
331 if (rc) 333 if (rc)
332 return rc; 334 return rc;
333 335 pSMB->hdr.Mid = GetNextMid(server);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 336 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security) 337 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 338 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -422,8 +424,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
422 } 424 }
423 425
424 } 426 }
425 if (pSMB) 427
426 cifs_buf_release(pSMB); 428 cifs_buf_release(pSMB);
427 return rc; 429 return rc;
428} 430}
429 431
@@ -518,6 +520,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ 520 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
519 521
520 if(ses->server) { 522 if(ses->server) {
523 pSMB->hdr.Mid = GetNextMid(ses->server);
524
521 if(ses->server->secMode & 525 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 526 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 527 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -537,9 +541,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
537 rc = -ESHUTDOWN; 541 rc = -ESHUTDOWN;
538 } 542 }
539 } 543 }
540 if (pSMB)
541 cifs_small_buf_release(pSMB);
542 up(&ses->sesSem); 544 up(&ses->sesSem);
545 cifs_small_buf_release(pSMB);
543 546
544 /* if session dead then we do not need to do ulogoff, 547 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting 548 since server closed smb session, no sense reporting
@@ -583,14 +586,10 @@ DelFileRetry:
583 pSMB->ByteCount = cpu_to_le16(name_len + 1); 586 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 587 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 588 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
589 cifs_stats_inc(&tcon->num_deletes);
586 if (rc) { 590 if (rc) {
587 cFYI(1, ("Error in RMFile = %d", rc)); 591 cFYI(1, ("Error in RMFile = %d", rc));
588 } 592 }
589#ifdef CONFIG_CIFS_STATS
590 else {
591 atomic_inc(&tcon->num_deletes);
592 }
593#endif
594 593
595 cifs_buf_release(pSMB); 594 cifs_buf_release(pSMB);
596 if (rc == -EAGAIN) 595 if (rc == -EAGAIN)
@@ -632,14 +631,10 @@ RmDirRetry:
632 pSMB->ByteCount = cpu_to_le16(name_len + 1); 631 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
634 cifs_stats_inc(&tcon->num_rmdirs);
635 if (rc) { 635 if (rc) {
636 cFYI(1, ("Error in RMDir = %d", rc)); 636 cFYI(1, ("Error in RMDir = %d", rc));
637 } 637 }
638#ifdef CONFIG_CIFS_STATS
639 else {
640 atomic_inc(&tcon->num_rmdirs);
641 }
642#endif
643 638
644 cifs_buf_release(pSMB); 639 cifs_buf_release(pSMB);
645 if (rc == -EAGAIN) 640 if (rc == -EAGAIN)
@@ -680,20 +675,161 @@ MkDirRetry:
680 pSMB->ByteCount = cpu_to_le16(name_len + 1); 675 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
678 cifs_stats_inc(&tcon->num_mkdirs);
683 if (rc) { 679 if (rc) {
684 cFYI(1, ("Error in Mkdir = %d", rc)); 680 cFYI(1, ("Error in Mkdir = %d", rc));
685 } 681 }
686#ifdef CONFIG_CIFS_STATS 682
687 else {
688 atomic_inc(&tcon->num_mkdirs);
689 }
690#endif
691 cifs_buf_release(pSMB); 683 cifs_buf_release(pSMB);
692 if (rc == -EAGAIN) 684 if (rc == -EAGAIN)
693 goto MkDirRetry; 685 goto MkDirRetry;
694 return rc; 686 return rc;
695} 687}
696 688
689static __u16 convert_disposition(int disposition)
690{
691 __u16 ofun = 0;
692
693 switch (disposition) {
694 case FILE_SUPERSEDE:
695 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
696 break;
697 case FILE_OPEN:
698 ofun = SMBOPEN_OAPPEND;
699 break;
700 case FILE_CREATE:
701 ofun = SMBOPEN_OCREATE;
702 break;
703 case FILE_OPEN_IF:
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
705 break;
706 case FILE_OVERWRITE:
707 ofun = SMBOPEN_OTRUNC;
708 break;
709 case FILE_OVERWRITE_IF:
710 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
711 break;
712 default:
713 cFYI(1,("unknown disposition %d",disposition));
714 ofun = SMBOPEN_OAPPEND; /* regular open */
715 }
716 return ofun;
717}
718
719int
720SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
721 const char *fileName, const int openDisposition,
722 const int access_flags, const int create_options, __u16 * netfid,
723 int *pOplock, FILE_ALL_INFO * pfile_info,
724 const struct nls_table *nls_codepage, int remap)
725{
726 int rc = -EACCES;
727 OPENX_REQ *pSMB = NULL;
728 OPENX_RSP *pSMBr = NULL;
729 int bytes_returned;
730 int name_len;
731 __u16 count;
732
733OldOpenRetry:
734 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
735 (void **) &pSMBr);
736 if (rc)
737 return rc;
738
739 pSMB->AndXCommand = 0xFF; /* none */
740
741 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
742 count = 1; /* account for one byte pad to word boundary */
743 name_len =
744 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
745 fileName, PATH_MAX, nls_codepage, remap);
746 name_len++; /* trailing null */
747 name_len *= 2;
748 } else { /* BB improve check for buffer overruns BB */
749 count = 0; /* no pad */
750 name_len = strnlen(fileName, PATH_MAX);
751 name_len++; /* trailing null */
752 strncpy(pSMB->fileName, fileName, name_len);
753 }
754 if (*pOplock & REQ_OPLOCK)
755 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
756 else if (*pOplock & REQ_BATCHOPLOCK) {
757 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
758 }
759 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
760 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
761 /* 0 = read
762 1 = write
763 2 = rw
764 3 = execute
765 */
766 pSMB->Mode = cpu_to_le16(2);
767 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
768 /* set file as system file if special file such
769 as fifo and server expecting SFU style and
770 no Unix extensions */
771
772 if(create_options & CREATE_OPTION_SPECIAL)
773 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
774 else
775 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
776
777 /* if ((omode & S_IWUGO) == 0)
778 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
779 /* Above line causes problems due to vfs splitting create into two
780 pieces - need to set mode after file created not while it is
781 being created */
782
783 /* BB FIXME BB */
784/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
785 /* BB FIXME END BB */
786
787 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
788 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
789 count += name_len;
790 pSMB->hdr.smb_buf_length += count;
791
792 pSMB->ByteCount = cpu_to_le16(count);
793 /* long_op set to 1 to allow for oplock break timeouts */
794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
795 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
796 cifs_stats_inc(&tcon->num_opens);
797 if (rc) {
798 cFYI(1, ("Error in Open = %d", rc));
799 } else {
800 /* BB verify if wct == 15 */
801
802/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
803
804 *netfid = pSMBr->Fid; /* cifs fid stays in le */
805 /* Let caller know file was created so we can set the mode. */
806 /* Do we care about the CreateAction in any other cases? */
807 /* BB FIXME BB */
808/* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
809 *pOplock |= CIFS_CREATE_ACTION; */
810 /* BB FIXME END */
811
812 if(pfile_info) {
813 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
814 pfile_info->LastAccessTime = 0; /* BB fixme */
815 pfile_info->LastWriteTime = 0; /* BB fixme */
816 pfile_info->ChangeTime = 0; /* BB fixme */
817 pfile_info->Attributes =
818 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
819 /* the file_info buf is endian converted by caller */
820 pfile_info->AllocationSize =
821 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
822 pfile_info->EndOfFile = pfile_info->AllocationSize;
823 pfile_info->NumberOfLinks = cpu_to_le32(1);
824 }
825 }
826
827 cifs_buf_release(pSMB);
828 if (rc == -EAGAIN)
829 goto OldOpenRetry;
830 return rc;
831}
832
697int 833int
698CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, 834CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition, 835 const char *fileName, const int openDisposition,
@@ -738,7 +874,13 @@ openRetry:
738 } 874 }
739 pSMB->DesiredAccess = cpu_to_le32(access_flags); 875 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0; 876 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 877 /* set file as system file if special file such
878 as fifo and server expecting SFU style and
879 no Unix extensions */
880 if(create_options & CREATE_OPTION_SPECIAL)
881 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
882 else
883 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */ 884 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other 885 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */ 886 servers such as Samba */
@@ -752,7 +894,7 @@ openRetry:
752 being created */ 894 being created */
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 895 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 896 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options); 897 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
756 /* BB Expirement with various impersonation levels and verify */ 898 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 899 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags = 900 pSMB->SecurityFlags =
@@ -765,6 +907,7 @@ openRetry:
765 /* long_op set to 1 to allow for oplock break timeouts */ 907 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1); 909 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
910 cifs_stats_inc(&tcon->num_opens);
768 if (rc) { 911 if (rc) {
769 cFYI(1, ("Error in Open = %d", rc)); 912 cFYI(1, ("Error in Open = %d", rc));
770 } else { 913 } else {
@@ -782,11 +925,8 @@ openRetry:
782 pfile_info->EndOfFile = pSMBr->EndOfFile; 925 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1); 926 pfile_info->NumberOfLinks = cpu_to_le32(1);
784 } 927 }
785
786#ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
788#endif
789 } 928 }
929
790 cifs_buf_release(pSMB); 930 cifs_buf_release(pSMB);
791 if (rc == -EAGAIN) 931 if (rc == -EAGAIN)
792 goto openRetry; 932 goto openRetry;
@@ -807,11 +947,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
807 READ_RSP *pSMBr = NULL; 947 READ_RSP *pSMBr = NULL;
808 char *pReadData = NULL; 948 char *pReadData = NULL;
809 int bytes_returned; 949 int bytes_returned;
950 int wct;
810 951
811 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 952 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
953 if(tcon->ses->capabilities & CAP_LARGE_FILES)
954 wct = 12;
955 else
956 wct = 10; /* old style read */
812 957
813 *nbytes = 0; 958 *nbytes = 0;
814 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, 959 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
815 (void **) &pSMBr); 960 (void **) &pSMBr);
816 if (rc) 961 if (rc)
817 return rc; 962 return rc;
@@ -823,14 +968,26 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
823 pSMB->AndXCommand = 0xFF; /* none */ 968 pSMB->AndXCommand = 0xFF; /* none */
824 pSMB->Fid = netfid; 969 pSMB->Fid = netfid;
825 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 970 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
826 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 971 if(wct == 12)
972 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
973 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
974 return -EIO;
975
827 pSMB->Remaining = 0; 976 pSMB->Remaining = 0;
828 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 977 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
829 pSMB->MaxCountHigh = cpu_to_le32(count >> 16); 978 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
830 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ 979 if(wct == 12)
831 980 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
981 else {
982 /* old style read */
983 struct smb_com_readx_req * pSMBW =
984 (struct smb_com_readx_req *)pSMB;
985 pSMBW->ByteCount = 0;
986 }
987
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
990 cifs_stats_inc(&tcon->num_reads);
834 if (rc) { 991 if (rc) {
835 cERROR(1, ("Send error in read = %d", rc)); 992 cERROR(1, ("Send error in read = %d", rc));
836 } else { 993 } else {
@@ -876,12 +1033,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
876 int rc = -EACCES; 1033 int rc = -EACCES;
877 WRITE_REQ *pSMB = NULL; 1034 WRITE_REQ *pSMB = NULL;
878 WRITE_RSP *pSMBr = NULL; 1035 WRITE_RSP *pSMBr = NULL;
879 int bytes_returned; 1036 int bytes_returned, wct;
880 __u32 bytes_sent; 1037 __u32 bytes_sent;
881 __u16 byte_count; 1038 __u16 byte_count;
882 1039
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/ 1040 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, 1041 if(tcon->ses == NULL)
1042 return -ECONNABORTED;
1043
1044 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1045 wct = 14;
1046 else
1047 wct = 12;
1048
1049 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
885 (void **) &pSMBr); 1050 (void **) &pSMBr);
886 if (rc) 1051 if (rc)
887 return rc; 1052 return rc;
@@ -892,7 +1057,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
892 pSMB->AndXCommand = 0xFF; /* none */ 1057 pSMB->AndXCommand = 0xFF; /* none */
893 pSMB->Fid = netfid; 1058 pSMB->Fid = netfid;
894 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1059 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
895 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1060 if(wct == 14)
1061 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1062 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1063 return -EIO;
1064
896 pSMB->Reserved = 0xFFFFFFFF; 1065 pSMB->Reserved = 0xFFFFFFFF;
897 pSMB->WriteMode = 0; 1066 pSMB->WriteMode = 0;
898 pSMB->Remaining = 0; 1067 pSMB->Remaining = 0;
@@ -911,7 +1080,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
911 if (bytes_sent > count) 1080 if (bytes_sent > count)
912 bytes_sent = count; 1081 bytes_sent = count;
913 pSMB->DataOffset = 1082 pSMB->DataOffset =
914 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1083 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
915 if(buf) 1084 if(buf)
916 memcpy(pSMB->Data,buf,bytes_sent); 1085 memcpy(pSMB->Data,buf,bytes_sent);
917 else if(ubuf) { 1086 else if(ubuf) {
@@ -919,20 +1088,31 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
919 cifs_buf_release(pSMB); 1088 cifs_buf_release(pSMB);
920 return -EFAULT; 1089 return -EFAULT;
921 } 1090 }
922 } else { 1091 } else if (count != 0) {
923 /* No buffer */ 1092 /* No buffer */
924 cifs_buf_release(pSMB); 1093 cifs_buf_release(pSMB);
925 return -EINVAL; 1094 return -EINVAL;
1095 } /* else setting file size with write of zero bytes */
1096 if(wct == 14)
1097 byte_count = bytes_sent + 1; /* pad */
1098 else /* wct == 12 */ {
1099 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
926 } 1100 }
927
928 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
929 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); 1101 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
930 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); 1102 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
931 pSMB->hdr.smb_buf_length += bytes_sent+1; 1103 pSMB->hdr.smb_buf_length += byte_count;
932 pSMB->ByteCount = cpu_to_le16(byte_count); 1104
1105 if(wct == 14)
1106 pSMB->ByteCount = cpu_to_le16(byte_count);
1107 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1108 struct smb_com_writex_req * pSMBW =
1109 (struct smb_com_writex_req *)pSMB;
1110 pSMBW->ByteCount = cpu_to_le16(byte_count);
1111 }
933 1112
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1113 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op); 1114 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1115 cifs_stats_inc(&tcon->num_writes);
936 if (rc) { 1116 if (rc) {
937 cFYI(1, ("Send error in write = %d", rc)); 1117 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = 0; 1118 *nbytes = 0;
@@ -951,56 +1131,72 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 1131}
952 1132
953#ifdef CONFIG_CIFS_EXPERIMENTAL 1133#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1134int
1135CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 1136 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 1137 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
957 const int long_op) 1138 int n_vec, const int long_op)
958{ 1139{
959 int rc = -EACCES; 1140 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 1141 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 1142 int bytes_returned, wct;
962 /*int bytes_returned;*/ 1143 int smb_hdr_len;
963 unsigned bytes_sent;
964 __u16 byte_count;
965 1144
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
967 1146 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1147 wct = 14;
1148 else
1149 wct = 12;
1150 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
968 if (rc) 1151 if (rc)
969 return rc; 1152 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 1153 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 1154 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 1155 return -ECONNABORTED;
976 1156
977 pSMB->AndXCommand = 0xFF; /* none */ 1157 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 1158 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1159 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1160 if(wct == 14)
1161 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1162 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1163 return -EIO;
981 pSMB->Reserved = 0xFFFFFFFF; 1164 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 1165 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 1166 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 1167
985 if (bytes_sent > count)
986 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1168 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1169 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1170
991 byte_count = bytes_sent + 1 /* pad */ ; 1171 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1172 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
993 pSMB->DataLengthHigh = 0; 1173 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
994 pSMB->hdr.smb_buf_length += byte_count; 1174 if(wct == 14)
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1175 pSMB->hdr.smb_buf_length += count+1;
1176 else /* wct == 12 */
1177 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1178 if(wct == 14)
1179 pSMB->ByteCount = cpu_to_le16(count + 1);
1180 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1181 struct smb_com_writex_req * pSMBW =
1182 (struct smb_com_writex_req *)pSMB;
1183 pSMBW->ByteCount = cpu_to_le16(count + 5);
1184 }
1185 iov[0].iov_base = pSMB;
1186 iov[0].iov_len = smb_hdr_len + 4;
996 1187
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1188 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ 1189 long_op);
1190 cifs_stats_inc(&tcon->num_writes);
999 if (rc) { 1191 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1192 cFYI(1, ("Send error Write2 = %d", rc));
1001 *nbytes = 0; 1193 *nbytes = 0;
1002 } else 1194 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1195 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1196 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1197 *nbytes = (*nbytes) << 16;
1198 *nbytes += le16_to_cpu(pSMBr->Count);
1199 }
1004 1200
1005 cifs_small_buf_release(pSMB); 1201 cifs_small_buf_release(pSMB);
1006 1202
@@ -1009,6 +1205,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1205
1010 return rc; 1206 return rc;
1011} 1207}
1208
1209
1012#endif /* CIFS_EXPERIMENTAL */ 1210#endif /* CIFS_EXPERIMENTAL */
1013 1211
1014int 1212int
@@ -1065,7 +1263,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1065 1263
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1265 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 1266 cifs_stats_inc(&tcon->num_locks);
1069 if (rc) { 1267 if (rc) {
1070 cFYI(1, ("Send error in Lock = %d", rc)); 1268 cFYI(1, ("Send error in Lock = %d", rc));
1071 } 1269 }
@@ -1099,6 +1297,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1099 pSMB->ByteCount = 0; 1297 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1300 cifs_stats_inc(&tcon->num_closes);
1102 if (rc) { 1301 if (rc) {
1103 if(rc!=-EINTR) { 1302 if(rc!=-EINTR) {
1104 /* EINTR is expected when user ctl-c to kill app */ 1303 /* EINTR is expected when user ctl-c to kill app */
@@ -1171,16 +1370,11 @@ renameRetry:
1171 1370
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1373 cifs_stats_inc(&tcon->num_renames);
1174 if (rc) { 1374 if (rc) {
1175 cFYI(1, ("Send error in rename = %d", rc)); 1375 cFYI(1, ("Send error in rename = %d", rc));
1176 } 1376 }
1177 1377
1178#ifdef CONFIG_CIFS_STATS
1179 else {
1180 atomic_inc(&tcon->num_renames);
1181 }
1182#endif
1183
1184 cifs_buf_release(pSMB); 1378 cifs_buf_release(pSMB);
1185 1379
1186 if (rc == -EAGAIN) 1380 if (rc == -EAGAIN)
@@ -1255,14 +1449,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1255 pSMB->ByteCount = cpu_to_le16(byte_count); 1449 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, 1450 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1452 cifs_stats_inc(&pTcon->num_t2renames);
1258 if (rc) { 1453 if (rc) {
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc)); 1454 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1260 } 1455 }
1261#ifdef CONFIG_CIFS_STATS 1456
1262 else {
1263 atomic_inc(&pTcon->num_t2renames);
1264 }
1265#endif
1266 cifs_buf_release(pSMB); 1457 cifs_buf_release(pSMB);
1267 1458
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls 1459 /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -1416,6 +1607,7 @@ createSymLinkRetry:
1416 pSMB->ByteCount = cpu_to_le16(byte_count); 1607 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1608 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1609 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1610 cifs_stats_inc(&tcon->num_symlinks);
1419 if (rc) { 1611 if (rc) {
1420 cFYI(1, 1612 cFYI(1,
1421 ("Send error in SetPathInfo (create symlink) = %d", 1613 ("Send error in SetPathInfo (create symlink) = %d",
@@ -1505,6 +1697,7 @@ createHardLinkRetry:
1505 pSMB->ByteCount = cpu_to_le16(byte_count); 1697 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1698 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1699 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1700 cifs_stats_inc(&tcon->num_hardlinks);
1508 if (rc) { 1701 if (rc) {
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); 1702 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 } 1703 }
@@ -1575,6 +1768,7 @@ winCreateHardLinkRetry:
1575 1768
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1770 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1771 cifs_stats_inc(&tcon->num_hardlinks);
1578 if (rc) { 1772 if (rc) {
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); 1773 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1580 } 1774 }
@@ -1775,8 +1969,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1969 }
1776 } 1970 }
1777qreparse_out: 1971qreparse_out:
1778 if (pSMB) 1972 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1973
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1974 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 1975 since file handle passed in no longer valid */
@@ -2165,6 +2358,67 @@ GetExtAttrOut:
2165 2358
2166#endif /* CONFIG_POSIX */ 2359#endif /* CONFIG_POSIX */
2167 2360
2361/* Legacy Query Path Information call for lookup to old servers such
2362 as Win9x/WinME */
2363int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2364 const unsigned char *searchName,
2365 FILE_ALL_INFO * pFinfo,
2366 const struct nls_table *nls_codepage, int remap)
2367{
2368 QUERY_INFORMATION_REQ * pSMB;
2369 QUERY_INFORMATION_RSP * pSMBr;
2370 int rc = 0;
2371 int bytes_returned;
2372 int name_len;
2373
2374 cFYI(1, ("In SMBQPath path %s", searchName));
2375QInfRetry:
2376 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2377 (void **) &pSMBr);
2378 if (rc)
2379 return rc;
2380
2381 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2382 name_len =
2383 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2384 PATH_MAX, nls_codepage, remap);
2385 name_len++; /* trailing null */
2386 name_len *= 2;
2387 } else {
2388 name_len = strnlen(searchName, PATH_MAX);
2389 name_len++; /* trailing null */
2390 strncpy(pSMB->FileName, searchName, name_len);
2391 }
2392 pSMB->BufferFormat = 0x04;
2393 name_len++; /* account for buffer type byte */
2394 pSMB->hdr.smb_buf_length += (__u16) name_len;
2395 pSMB->ByteCount = cpu_to_le16(name_len);
2396
2397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2399 if (rc) {
2400 cFYI(1, ("Send error in QueryInfo = %d", rc));
2401 } else if (pFinfo) { /* decode response */
2402 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2403 pFinfo->AllocationSize =
2404 cpu_to_le64(le32_to_cpu(pSMBr->size));
2405 pFinfo->EndOfFile = pFinfo->AllocationSize;
2406 pFinfo->Attributes =
2407 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2408 } else
2409 rc = -EIO; /* bad buffer passed in */
2410
2411 cifs_buf_release(pSMB);
2412
2413 if (rc == -EAGAIN)
2414 goto QInfRetry;
2415
2416 return rc;
2417}
2418
2419
2420
2421
2168int 2422int
2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2423CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName, 2424 const unsigned char *searchName,
@@ -2396,7 +2650,7 @@ findUniqueRetry:
2396 if (rc) { 2650 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2651 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2652 } else { /* decode response */
2399 2653 cifs_stats_inc(&tcon->num_ffirst);
2400 /* BB fill in */ 2654 /* BB fill in */
2401 } 2655 }
2402 2656
@@ -2414,7 +2668,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2668 const char *searchName,
2415 const struct nls_table *nls_codepage, 2669 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2670 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2671 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2672{
2419/* level 257 SMB_ */ 2673/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2674 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2695,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2695 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2696 directory name instead of a wildcard */
2443 name_len *= 2; 2697 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2698 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2699 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2700 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2701 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2709,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2709 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2710 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2711 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2712 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2713 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2714 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2715 name_len += 3;
@@ -2496,6 +2750,7 @@ findFirstRetry:
2496 2750
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753 cifs_stats_inc(&tcon->num_ffirst);
2499 2754
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2755 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2501 /* BB Add code to handle unsupported level rc */ 2756 /* BB Add code to handle unsupported level rc */
@@ -2617,7 +2872,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2617 2872
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 2875 cifs_stats_inc(&tcon->num_fnext);
2621 if (rc) { 2876 if (rc) {
2622 if (rc == -EBADF) { 2877 if (rc == -EBADF) {
2623 psrch_inf->endOfSearch = TRUE; 2878 psrch_inf->endOfSearch = TRUE;
@@ -2694,6 +2949,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2949 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2950 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2951 }
2952 cifs_stats_inc(&tcon->num_fclose);
2697 cifs_small_buf_release(pSMB); 2953 cifs_small_buf_release(pSMB);
2698 2954
2699 /* Since session is dead, search handle closed on server already */ 2955 /* Since session is dead, search handle closed on server already */
@@ -2827,7 +3083,10 @@ getDFSRetry:
2827 (void **) &pSMBr); 3083 (void **) &pSMBr);
2828 if (rc) 3084 if (rc)
2829 return rc; 3085 return rc;
2830 3086
3087 /* server pointer checked in called function,
3088 but should never be null here anyway */
3089 pSMB->hdr.Mid = GetNextMid(ses->server);
2831 pSMB->hdr.Tid = ses->ipc_tid; 3090 pSMB->hdr.Tid = ses->ipc_tid;
2832 pSMB->hdr.Uid = ses->Suid; 3091 pSMB->hdr.Uid = ses->Suid;
2833 if (ses->capabilities & CAP_STATUS32) { 3092 if (ses->capabilities & CAP_STATUS32) {
@@ -2968,6 +3227,92 @@ GetDFSRefExit:
2968 return rc; 3227 return rc;
2969} 3228}
2970 3229
3230/* Query File System Info such as free space to old servers such as Win 9x */
3231int
3232SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3233{
3234/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3235 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3236 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3237 FILE_SYSTEM_ALLOC_INFO *response_data;
3238 int rc = 0;
3239 int bytes_returned = 0;
3240 __u16 params, byte_count;
3241
3242 cFYI(1, ("OldQFSInfo"));
3243oldQFSInfoRetry:
3244 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3245 (void **) &pSMBr);
3246 if (rc)
3247 return rc;
3248 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3249 (void **) &pSMBr);
3250 if (rc)
3251 return rc;
3252
3253 params = 2; /* level */
3254 pSMB->TotalDataCount = 0;
3255 pSMB->MaxParameterCount = cpu_to_le16(2);
3256 pSMB->MaxDataCount = cpu_to_le16(1000);
3257 pSMB->MaxSetupCount = 0;
3258 pSMB->Reserved = 0;
3259 pSMB->Flags = 0;
3260 pSMB->Timeout = 0;
3261 pSMB->Reserved2 = 0;
3262 byte_count = params + 1 /* pad */ ;
3263 pSMB->TotalParameterCount = cpu_to_le16(params);
3264 pSMB->ParameterCount = pSMB->TotalParameterCount;
3265 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3266 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3267 pSMB->DataCount = 0;
3268 pSMB->DataOffset = 0;
3269 pSMB->SetupCount = 1;
3270 pSMB->Reserved3 = 0;
3271 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3272 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3273 pSMB->hdr.smb_buf_length += byte_count;
3274 pSMB->ByteCount = cpu_to_le16(byte_count);
3275
3276 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3277 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3278 if (rc) {
3279 cFYI(1, ("Send error in QFSInfo = %d", rc));
3280 } else { /* decode response */
3281 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3282
3283 if (rc || (pSMBr->ByteCount < 18))
3284 rc = -EIO; /* bad smb */
3285 else {
3286 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3287 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3288 pSMBr->ByteCount, data_offset));
3289
3290 response_data =
3291 (FILE_SYSTEM_ALLOC_INFO *)
3292 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3293 FSData->f_bsize =
3294 le16_to_cpu(response_data->BytesPerSector) *
3295 le32_to_cpu(response_data->
3296 SectorsPerAllocationUnit);
3297 FSData->f_blocks =
3298 le32_to_cpu(response_data->TotalAllocationUnits);
3299 FSData->f_bfree = FSData->f_bavail =
3300 le32_to_cpu(response_data->FreeAllocationUnits);
3301 cFYI(1,
3302 ("Blocks: %lld Free: %lld Block size %ld",
3303 (unsigned long long)FSData->f_blocks,
3304 (unsigned long long)FSData->f_bfree,
3305 FSData->f_bsize));
3306 }
3307 }
3308 cifs_buf_release(pSMB);
3309
3310 if (rc == -EAGAIN)
3311 goto oldQFSInfoRetry;
3312
3313 return rc;
3314}
3315
2971int 3316int
2972CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) 3317CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2973{ 3318{
@@ -2989,7 +3334,7 @@ QFSInfoRetry:
2989 params = 2; /* level */ 3334 params = 2; /* level */
2990 pSMB->TotalDataCount = 0; 3335 pSMB->TotalDataCount = 0;
2991 pSMB->MaxParameterCount = cpu_to_le16(2); 3336 pSMB->MaxParameterCount = cpu_to_le16(2);
2992 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 3337 pSMB->MaxDataCount = cpu_to_le16(1000);
2993 pSMB->MaxSetupCount = 0; 3338 pSMB->MaxSetupCount = 0;
2994 pSMB->Reserved = 0; 3339 pSMB->Reserved = 0;
2995 pSMB->Flags = 0; 3340 pSMB->Flags = 0;
@@ -3012,17 +3357,14 @@ QFSInfoRetry:
3012 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 3357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3013 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 3358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3014 if (rc) { 3359 if (rc) {
3015 cERROR(1, ("Send error in QFSInfo = %d", rc)); 3360 cFYI(1, ("Send error in QFSInfo = %d", rc));
3016 } else { /* decode response */ 3361 } else { /* decode response */
3017 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 3362 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3018 3363
3019 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ 3364 if (rc || (pSMBr->ByteCount < 24))
3020 rc = -EIO; /* bad smb */ 3365 rc = -EIO; /* bad smb */
3021 else { 3366 else {
3022 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 3367 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3023 cFYI(1,
3024 ("Decoding qfsinfo response. BCC: %d Offset %d",
3025 pSMBr->ByteCount, data_offset));
3026 3368
3027 response_data = 3369 response_data =
3028 (FILE_SYSTEM_INFO 3370 (FILE_SYSTEM_INFO
@@ -3257,6 +3599,77 @@ QFSUnixRetry:
3257 return rc; 3599 return rc;
3258} 3600}
3259 3601
3602int
3603CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3604{
3605/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3606 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3607 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3608 int rc = 0;
3609 int bytes_returned = 0;
3610 __u16 params, param_offset, offset, byte_count;
3611
3612 cFYI(1, ("In SETFSUnixInfo"));
3613SETFSUnixRetry:
3614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3615 (void **) &pSMBr);
3616 if (rc)
3617 return rc;
3618
3619 params = 4; /* 2 bytes zero followed by info level. */
3620 pSMB->MaxSetupCount = 0;
3621 pSMB->Reserved = 0;
3622 pSMB->Flags = 0;
3623 pSMB->Timeout = 0;
3624 pSMB->Reserved2 = 0;
3625 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3626 offset = param_offset + params;
3627
3628 pSMB->MaxParameterCount = cpu_to_le16(4);
3629 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3630 pSMB->SetupCount = 1;
3631 pSMB->Reserved3 = 0;
3632 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3633 byte_count = 1 /* pad */ + params + 12;
3634
3635 pSMB->DataCount = cpu_to_le16(12);
3636 pSMB->ParameterCount = cpu_to_le16(params);
3637 pSMB->TotalDataCount = pSMB->DataCount;
3638 pSMB->TotalParameterCount = pSMB->ParameterCount;
3639 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3640 pSMB->DataOffset = cpu_to_le16(offset);
3641
3642 /* Params. */
3643 pSMB->FileNum = 0;
3644 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3645
3646 /* Data. */
3647 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3648 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3649 pSMB->ClientUnixCap = cpu_to_le64(cap);
3650
3651 pSMB->hdr.smb_buf_length += byte_count;
3652 pSMB->ByteCount = cpu_to_le16(byte_count);
3653
3654 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3655 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3656 if (rc) {
3657 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3658 } else { /* decode response */
3659 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3660 if (rc) {
3661 rc = -EIO; /* bad smb */
3662 }
3663 }
3664 cifs_buf_release(pSMB);
3665
3666 if (rc == -EAGAIN)
3667 goto SETFSUnixRetry;
3668
3669 return rc;
3670}
3671
3672
3260 3673
3261int 3674int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3675CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3321,16 +3734,16 @@ QFSPosixRetry:
3321 le64_to_cpu(response_data->TotalBlocks); 3734 le64_to_cpu(response_data->TotalBlocks);
3322 FSData->f_bfree = 3735 FSData->f_bfree =
3323 le64_to_cpu(response_data->BlocksAvail); 3736 le64_to_cpu(response_data->BlocksAvail);
3324 if(response_data->UserBlocksAvail == -1) { 3737 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3325 FSData->f_bavail = FSData->f_bfree; 3738 FSData->f_bavail = FSData->f_bfree;
3326 } else { 3739 } else {
3327 FSData->f_bavail = 3740 FSData->f_bavail =
3328 le64_to_cpu(response_data->UserBlocksAvail); 3741 le64_to_cpu(response_data->UserBlocksAvail);
3329 } 3742 }
3330 if(response_data->TotalFileNodes != -1) 3743 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3331 FSData->f_files = 3744 FSData->f_files =
3332 le64_to_cpu(response_data->TotalFileNodes); 3745 le64_to_cpu(response_data->TotalFileNodes);
3333 if(response_data->FreeFileNodes != -1) 3746 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3334 FSData->f_ffree = 3747 FSData->f_ffree =
3335 le64_to_cpu(response_data->FreeFileNodes); 3748 le64_to_cpu(response_data->FreeFileNodes);
3336 } 3749 }
@@ -3376,7 +3789,7 @@ SetEOFRetry:
3376 PATH_MAX, nls_codepage, remap); 3789 PATH_MAX, nls_codepage, remap);
3377 name_len++; /* trailing null */ 3790 name_len++; /* trailing null */
3378 name_len *= 2; 3791 name_len *= 2;
3379 } else { /* BB improve the check for buffer overruns BB */ 3792 } else { /* BB improve the check for buffer overruns BB */
3380 name_len = strnlen(fileName, PATH_MAX); 3793 name_len = strnlen(fileName, PATH_MAX);
3381 name_len++; /* trailing null */ 3794 name_len++; /* trailing null */
3382 strncpy(pSMB->FileName, fileName, name_len); 3795 strncpy(pSMB->FileName, fileName, name_len);
@@ -3384,7 +3797,7 @@ SetEOFRetry:
3384 params = 6 + name_len; 3797 params = 6 + name_len;
3385 data_count = sizeof (struct file_end_of_file_info); 3798 data_count = sizeof (struct file_end_of_file_info);
3386 pSMB->MaxParameterCount = cpu_to_le16(2); 3799 pSMB->MaxParameterCount = cpu_to_le16(2);
3387 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ 3800 pSMB->MaxDataCount = cpu_to_le16(4100);
3388 pSMB->MaxSetupCount = 0; 3801 pSMB->MaxSetupCount = 0;
3389 pSMB->Reserved = 0; 3802 pSMB->Reserved = 0;
3390 pSMB->Flags = 0; 3803 pSMB->Flags = 0;
@@ -3766,7 +4179,7 @@ setPermsRetry:
3766 PATH_MAX, nls_codepage, remap); 4179 PATH_MAX, nls_codepage, remap);
3767 name_len++; /* trailing null */ 4180 name_len++; /* trailing null */
3768 name_len *= 2; 4181 name_len *= 2;
3769 } else { /* BB improve the check for buffer overruns BB */ 4182 } else { /* BB improve the check for buffer overruns BB */
3770 name_len = strnlen(fileName, PATH_MAX); 4183 name_len = strnlen(fileName, PATH_MAX);
3771 name_len++; /* trailing null */ 4184 name_len++; /* trailing null */
3772 strncpy(pSMB->FileName, fileName, name_len); 4185 strncpy(pSMB->FileName, fileName, name_len);
@@ -3839,12 +4252,14 @@ setPermsRetry:
3839} 4252}
3840 4253
3841int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 4254int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3842 const int notify_subdirs, const __u16 netfid, 4255 const int notify_subdirs, const __u16 netfid,
3843 __u32 filter, const struct nls_table *nls_codepage) 4256 __u32 filter, struct file * pfile, int multishot,
4257 const struct nls_table *nls_codepage)
3844{ 4258{
3845 int rc = 0; 4259 int rc = 0;
3846 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4260 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3847 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4261 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4262 struct dir_notify_req *dnotify_req;
3848 int bytes_returned; 4263 int bytes_returned;
3849 4264
3850 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); 4265 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
@@ -3877,6 +4292,28 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, -1); 4292 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3878 if (rc) { 4293 if (rc) {
3879 cFYI(1, ("Error in Notify = %d", rc)); 4294 cFYI(1, ("Error in Notify = %d", rc));
4295 } else {
4296 /* Add file to outstanding requests */
4297 /* BB change to kmem cache alloc */
4298 dnotify_req = (struct dir_notify_req *) kmalloc(
4299 sizeof(struct dir_notify_req),
4300 GFP_KERNEL);
4301 if(dnotify_req) {
4302 dnotify_req->Pid = pSMB->hdr.Pid;
4303 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4304 dnotify_req->Mid = pSMB->hdr.Mid;
4305 dnotify_req->Tid = pSMB->hdr.Tid;
4306 dnotify_req->Uid = pSMB->hdr.Uid;
4307 dnotify_req->netfid = netfid;
4308 dnotify_req->pfile = pfile;
4309 dnotify_req->filter = filter;
4310 dnotify_req->multishot = multishot;
4311 spin_lock(&GlobalMid_Lock);
4312 list_add_tail(&dnotify_req->lhead,
4313 &GlobalDnotifyReqList);
4314 spin_unlock(&GlobalMid_Lock);
4315 } else
4316 rc = -ENOMEM;
3880 } 4317 }
3881 cifs_buf_release(pSMB); 4318 cifs_buf_release(pSMB);
3882 return rc; 4319 return rc;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 47360156cc54..d74367a08d51 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -29,6 +29,8 @@
29#include <linux/utsname.h> 29#include <linux/utsname.h>
30#include <linux/mempool.h> 30#include <linux/mempool.h>
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/completion.h>
33#include <linux/pagevec.h>
32#include <asm/uaccess.h> 34#include <asm/uaccess.h>
33#include <asm/processor.h> 35#include <asm/processor.h>
34#include "cifspdu.h" 36#include "cifspdu.h"
@@ -44,6 +46,8 @@
44#define CIFS_PORT 445 46#define CIFS_PORT 445
45#define RFC1001_PORT 139 47#define RFC1001_PORT 139
46 48
49static DECLARE_COMPLETION(cifsd_complete);
50
47extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, 51extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
48 unsigned char *p24); 52 unsigned char *p24);
49extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 53extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
@@ -60,6 +64,7 @@ struct smb_vol {
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */ 64 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */ 65 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */ 66 char source_rfc1001_name[16]; /* netbios name of client */
67 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
63 uid_t linux_uid; 68 uid_t linux_uid;
64 gid_t linux_gid; 69 gid_t linux_gid;
65 mode_t file_mode; 70 mode_t file_mode;
@@ -74,6 +79,10 @@ struct smb_vol {
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 79 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
75 unsigned direct_io:1; 80 unsigned direct_io:1;
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 81 unsigned remap:1; /* set to remap seven reserved chars in filenames */
82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
83 unsigned sfu_emul:1;
84 unsigned nocase; /* request case insensitive filenames */
85 unsigned nobrl; /* disable sending byte range locks to srv */
77 unsigned int rsize; 86 unsigned int rsize;
78 unsigned int wsize; 87 unsigned int wsize;
79 unsigned int sockopt; 88 unsigned int sockopt;
@@ -82,7 +91,8 @@ struct smb_vol {
82 91
83static int ipv4_connect(struct sockaddr_in *psin_server, 92static int ipv4_connect(struct sockaddr_in *psin_server,
84 struct socket **csocket, 93 struct socket **csocket,
85 char * netb_name); 94 char * netb_name,
95 char * server_netb_name);
86static int ipv6_connect(struct sockaddr_in6 *psin_server, 96static int ipv6_connect(struct sockaddr_in6 *psin_server,
87 struct socket **csocket); 97 struct socket **csocket);
88 98
@@ -175,9 +185,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
175 } else { 185 } else {
176 rc = ipv4_connect(&server->addr.sockAddr, 186 rc = ipv4_connect(&server->addr.sockAddr,
177 &server->ssocket, 187 &server->ssocket,
178 server->workstation_RFC1001_name); 188 server->workstation_RFC1001_name,
189 server->server_RFC1001_name);
179 } 190 }
180 if(rc) { 191 if(rc) {
192 cFYI(1,("reconnect error %d",rc));
181 msleep(3000); 193 msleep(3000);
182 } else { 194 } else {
183 atomic_inc(&tcpSesReconnectCount); 195 atomic_inc(&tcpSesReconnectCount);
@@ -293,12 +305,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
293 byte_count += total_in_buf2; 305 byte_count += total_in_buf2;
294 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); 306 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
295 307
296 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); 308 byte_count = pTargetSMB->smb_buf_length;
297 byte_count += total_in_buf2; 309 byte_count += total_in_buf2;
298 310
299 /* BB also add check that we are not beyond maximum buffer size */ 311 /* BB also add check that we are not beyond maximum buffer size */
300 312
301 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); 313 pTargetSMB->smb_buf_length = byte_count;
302 314
303 if(remaining == total_in_buf2) { 315 if(remaining == total_in_buf2) {
304 cFYI(1,("found the last secondary response")); 316 cFYI(1,("found the last secondary response"));
@@ -323,7 +335,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
323 struct cifsSesInfo *ses; 335 struct cifsSesInfo *ses;
324 struct task_struct *task_to_wake = NULL; 336 struct task_struct *task_to_wake = NULL;
325 struct mid_q_entry *mid_entry; 337 struct mid_q_entry *mid_entry;
326 char *temp; 338 char temp;
327 int isLargeBuf = FALSE; 339 int isLargeBuf = FALSE;
328 int isMultiRsp; 340 int isMultiRsp;
329 int reconnect; 341 int reconnect;
@@ -337,6 +349,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
337 atomic_inc(&tcpSesAllocCount); 349 atomic_inc(&tcpSesAllocCount);
338 length = tcpSesAllocCount.counter; 350 length = tcpSesAllocCount.counter;
339 write_unlock(&GlobalSMBSeslock); 351 write_unlock(&GlobalSMBSeslock);
352 complete(&cifsd_complete);
340 if(length > 1) { 353 if(length > 1) {
341 mempool_resize(cifs_req_poolp, 354 mempool_resize(cifs_req_poolp,
342 length + cifs_min_rcv, 355 length + cifs_min_rcv,
@@ -424,22 +437,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
424 continue; 437 continue;
425 } 438 }
426 439
427 /* the right amount was read from socket - 4 bytes */ 440 /* The right amount was read from socket - 4 bytes */
441 /* so we can now interpret the length field */
442
443 /* the first byte big endian of the length field,
444 is actually not part of the length but the type
445 with the most common, zero, as regular data */
446 temp = *((char *) smb_buffer);
428 447
448 /* Note that FC 1001 length is big endian on the wire,
449 but we convert it here so it is always manipulated
450 as host byte order */
429 pdu_length = ntohl(smb_buffer->smb_buf_length); 451 pdu_length = ntohl(smb_buffer->smb_buf_length);
430 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); 452 smb_buffer->smb_buf_length = pdu_length;
453
454 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
431 455
432 temp = (char *) smb_buffer; 456 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
433 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
434 continue; 457 continue;
435 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { 458 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
436 cFYI(1,("Good RFC 1002 session rsp")); 459 cFYI(1,("Good RFC 1002 session rsp"));
437 continue; 460 continue;
438 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { 461 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
439 /* we get this from Windows 98 instead of 462 /* we get this from Windows 98 instead of
440 an error on SMB negprot response */ 463 an error on SMB negprot response */
441 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", 464 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
442 temp[4])); 465 pdu_length));
443 if(server->tcpStatus == CifsNew) { 466 if(server->tcpStatus == CifsNew) {
444 /* if nack on negprot (rather than 467 /* if nack on negprot (rather than
445 ret of smb negprot error) reconnecting 468 ret of smb negprot error) reconnecting
@@ -461,9 +484,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
461 wake_up(&server->response_q); 484 wake_up(&server->response_q);
462 continue; 485 continue;
463 } 486 }
464 } else if (temp[0] != (char) 0) { 487 } else if (temp != (char) 0) {
465 cERROR(1,("Unknown RFC 1002 frame")); 488 cERROR(1,("Unknown RFC 1002 frame"));
466 cifs_dump_mem(" Received Data: ", temp, length); 489 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
490 length);
467 cifs_reconnect(server); 491 cifs_reconnect(server);
468 csocket = server->ssocket; 492 csocket = server->ssocket;
469 continue; 493 continue;
@@ -533,7 +557,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
533 557
534 dump_smb(smb_buffer, length); 558 dump_smb(smb_buffer, length);
535 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { 559 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
536 cERROR(1, ("Bad SMB Received ")); 560 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
537 continue; 561 continue;
538 } 562 }
539 563
@@ -581,6 +605,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
581multi_t2_fnd: 605multi_t2_fnd:
582 task_to_wake = mid_entry->tsk; 606 task_to_wake = mid_entry->tsk;
583 mid_entry->midState = MID_RESPONSE_RECEIVED; 607 mid_entry->midState = MID_RESPONSE_RECEIVED;
608#ifdef CONFIG_CIFS_STATS2
609 mid_entry->when_received = jiffies;
610#endif
584 break; 611 break;
585 } 612 }
586 } 613 }
@@ -598,7 +625,8 @@ multi_t2_fnd:
598 } else if ((is_valid_oplock_break(smb_buffer) == FALSE) 625 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
599 && (isMultiRsp == FALSE)) { 626 && (isMultiRsp == FALSE)) {
600 cERROR(1, ("No task to wake, unknown frame rcvd!")); 627 cERROR(1, ("No task to wake, unknown frame rcvd!"));
601 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); 628 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
629 sizeof(struct smb_hdr));
602 } 630 }
603 } /* end while !EXITING */ 631 } /* end while !EXITING */
604 632
@@ -676,7 +704,7 @@ multi_t2_fnd:
676 msleep(125); 704 msleep(125);
677 } 705 }
678 706
679 if (list_empty(&server->pending_mid_q)) { 707 if (!list_empty(&server->pending_mid_q)) {
680 /* mpx threads have not exited yet give them 708 /* mpx threads have not exited yet give them
681 at least the smb send timeout time for long ops */ 709 at least the smb send timeout time for long ops */
682 /* due to delays on oplock break requests, we need 710 /* due to delays on oplock break requests, we need
@@ -713,7 +741,7 @@ multi_t2_fnd:
713 GFP_KERNEL); 741 GFP_KERNEL);
714 } 742 }
715 743
716 msleep(250); 744 complete_and_exit(&cifsd_complete, 0);
717 return 0; 745 return 0;
718} 746}
719 747
@@ -737,7 +765,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
737 toupper(system_utsname.nodename[i]); 765 toupper(system_utsname.nodename[i]);
738 } 766 }
739 vol->source_rfc1001_name[15] = 0; 767 vol->source_rfc1001_name[15] = 0;
740 768 /* null target name indicates to use *SMBSERVR default called name
769 if we end up sending RFC1001 session initialize */
770 vol->target_rfc1001_name[0] = 0;
741 vol->linux_uid = current->uid; /* current->euid instead? */ 771 vol->linux_uid = current->uid; /* current->euid instead? */
742 vol->linux_gid = current->gid; 772 vol->linux_gid = current->gid;
743 vol->dir_mode = S_IRWXUGO; 773 vol->dir_mode = S_IRWXUGO;
@@ -747,6 +777,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
747 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 777 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
748 vol->rw = TRUE; 778 vol->rw = TRUE;
749 779
780 /* default is always to request posix paths. */
781 vol->posix_paths = 1;
782
750 if (!options) 783 if (!options)
751 return 1; 784 return 1;
752 785
@@ -987,7 +1020,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
987 /* The string has 16th byte zero still from 1020 /* The string has 16th byte zero still from
988 set at top of the function */ 1021 set at top of the function */
989 if((i==15) && (value[i] != 0)) 1022 if((i==15) && (value[i] != 0))
990 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); 1023 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1024 }
1025 } else if (strnicmp(data, "servern", 7) == 0) {
1026 /* servernetbiosname specified override *SMBSERVER */
1027 if (!value || !*value || (*value == ' ')) {
1028 cFYI(1,("empty server netbiosname specified"));
1029 } else {
1030 /* last byte, type, is 0x20 for servr type */
1031 memset(vol->target_rfc1001_name,0x20,16);
1032
1033 for(i=0;i<15;i++) {
1034 /* BB are there cases in which a comma can be
1035 valid in this workstation netbios name (and need
1036 special handling)? */
1037
1038 /* user or mount helper must uppercase netbiosname */
1039 if (value[i]==0)
1040 break;
1041 else
1042 vol->target_rfc1001_name[i] = value[i];
1043 }
1044 /* The string has 16th byte zero still from
1045 set at top of the function */
1046 if((i==15) && (value[i] != 0))
1047 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
991 } 1048 }
992 } else if (strnicmp(data, "credentials", 4) == 0) { 1049 } else if (strnicmp(data, "credentials", 4) == 0) {
993 /* ignore */ 1050 /* ignore */
@@ -1025,6 +1082,27 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1025 vol->remap = 1; 1082 vol->remap = 1;
1026 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1083 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1027 vol->remap = 0; 1084 vol->remap = 0;
1085 } else if (strnicmp(data, "sfu", 3) == 0) {
1086 vol->sfu_emul = 1;
1087 } else if (strnicmp(data, "nosfu", 5) == 0) {
1088 vol->sfu_emul = 0;
1089 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1090 vol->posix_paths = 1;
1091 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1092 vol->posix_paths = 0;
1093 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1094 (strnicmp(data, "ignorecase", 10) == 0)) {
1095 vol->nocase = 1;
1096 } else if (strnicmp(data, "brl", 3) == 0) {
1097 vol->nobrl = 0;
1098 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1099 (strnicmp(data, "nolock", 6) == 0)) {
1100 vol->nobrl = 1;
1101 /* turn off mandatory locking in mode
1102 if remote locking is turned off since the
1103 local vfs will do advisory */
1104 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1105 vol->file_mode = S_IALLUGO;
1028 } else if (strnicmp(data, "setuids", 7) == 0) { 1106 } else if (strnicmp(data, "setuids", 7) == 0) {
1029 vol->setuids = 1; 1107 vol->setuids = 1;
1030 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1108 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1244,7 +1322,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length)
1244 1322
1245static int 1323static int
1246ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, 1324ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1247 char * netbios_name) 1325 char * netbios_name, char * target_name)
1248{ 1326{
1249 int rc = 0; 1327 int rc = 0;
1250 int connected = 0; 1328 int connected = 0;
@@ -1309,10 +1387,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1309 /* Eventually check for other socket options to change from 1387 /* Eventually check for other socket options to change from
1310 the default. sock_setsockopt not used because it expects 1388 the default. sock_setsockopt not used because it expects
1311 user space buffer */ 1389 user space buffer */
1390 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1391 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1312 (*csocket)->sk->sk_rcvtimeo = 7 * HZ; 1392 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1393 /* make the bufsizes depend on wsize/rsize and max requests */
1394 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1395 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1396 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1397 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1313 1398
1314 /* send RFC1001 sessinit */ 1399 /* send RFC1001 sessinit */
1315
1316 if(psin_server->sin_port == htons(RFC1001_PORT)) { 1400 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1317 /* some servers require RFC1001 sessinit before sending 1401 /* some servers require RFC1001 sessinit before sending
1318 negprot - BB check reconnection in case where second 1402 negprot - BB check reconnection in case where second
@@ -1322,8 +1406,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1322 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); 1406 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1323 if(ses_init_buf) { 1407 if(ses_init_buf) {
1324 ses_init_buf->trailer.session_req.called_len = 32; 1408 ses_init_buf->trailer.session_req.called_len = 32;
1325 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1409 if(target_name && (target_name[0] != 0)) {
1326 DEFAULT_CIFS_CALLED_NAME,16); 1410 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1411 target_name, 16);
1412 } else {
1413 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1414 DEFAULT_CIFS_CALLED_NAME,16);
1415 }
1416
1327 ses_init_buf->trailer.session_req.calling_len = 32; 1417 ses_init_buf->trailer.session_req.calling_len = 32;
1328 /* calling name ends in null (byte 16) from old smb 1418 /* calling name ends in null (byte 16) from old smb
1329 convention. */ 1419 convention. */
@@ -1556,7 +1646,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1556 sin_server.sin_port = htons(volume_info.port); 1646 sin_server.sin_port = htons(volume_info.port);
1557 else 1647 else
1558 sin_server.sin_port = 0; 1648 sin_server.sin_port = 0;
1559 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); 1649 rc = ipv4_connect(&sin_server,&csocket,
1650 volume_info.source_rfc1001_name,
1651 volume_info.target_rfc1001_name);
1560 if (rc < 0) { 1652 if (rc < 0) {
1561 cERROR(1, 1653 cERROR(1,
1562 ("Error connecting to IPv4 socket. Aborting operation")); 1654 ("Error connecting to IPv4 socket. Aborting operation"));
@@ -1606,9 +1698,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1606 kfree(volume_info.password); 1698 kfree(volume_info.password);
1607 FreeXid(xid); 1699 FreeXid(xid);
1608 return rc; 1700 return rc;
1609 } else 1701 }
1610 rc = 0; 1702 wait_for_completion(&cifsd_complete);
1703 rc = 0;
1611 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1704 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1705 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1612 srvTcp->sequence_number = 0; 1706 srvTcp->sequence_number = 0;
1613 } 1707 }
1614 } 1708 }
@@ -1653,17 +1747,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1653 1747
1654 /* search for existing tcon to this server share */ 1748 /* search for existing tcon to this server share */
1655 if (!rc) { 1749 if (!rc) {
1656 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) 1750 if(volume_info.rsize > CIFSMaxBufSize) {
1751 cERROR(1,("rsize %d too large, using MaxBufSize",
1752 volume_info.rsize));
1753 cifs_sb->rsize = CIFSMaxBufSize;
1754 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1657 cifs_sb->rsize = volume_info.rsize; 1755 cifs_sb->rsize = volume_info.rsize;
1658 else 1756 else /* default */
1659 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ 1757 cifs_sb->rsize = CIFSMaxBufSize;
1660 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize)) 1758
1759 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1760 cERROR(1,("wsize %d too large using 4096 instead",
1761 volume_info.wsize));
1762 cifs_sb->wsize = 4096;
1763 } else if(volume_info.wsize)
1661 cifs_sb->wsize = volume_info.wsize; 1764 cifs_sb->wsize = volume_info.wsize;
1662 else 1765 else
1663 cifs_sb->wsize = CIFSMaxBufSize; /* default */ 1766 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1664 if(cifs_sb->rsize < PAGE_CACHE_SIZE) { 1767 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1665 cifs_sb->rsize = PAGE_CACHE_SIZE; 1768 cifs_sb->rsize = PAGE_CACHE_SIZE;
1666 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); 1769 /* Windows ME does this */
1770 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1667 } 1771 }
1668 cifs_sb->mnt_uid = volume_info.linux_uid; 1772 cifs_sb->mnt_uid = volume_info.linux_uid;
1669 cifs_sb->mnt_gid = volume_info.linux_gid; 1773 cifs_sb->mnt_gid = volume_info.linux_gid;
@@ -1681,8 +1785,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 1785 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1682 if(volume_info.no_xattr) 1786 if(volume_info.no_xattr)
1683 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1787 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1788 if(volume_info.sfu_emul)
1789 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1790 if(volume_info.nobrl)
1791 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1792
1684 if(volume_info.direct_io) { 1793 if(volume_info.direct_io) {
1685 cERROR(1,("mounting share using direct i/o")); 1794 cFYI(1,("mounting share using direct i/o"));
1686 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 1795 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1687 } 1796 }
1688 1797
@@ -1696,6 +1805,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1696 to the same server share the last value passed in 1805 to the same server share the last value passed in
1697 for the retry flag is used */ 1806 for the retry flag is used */
1698 tcon->retry = volume_info.retry; 1807 tcon->retry = volume_info.retry;
1808 tcon->nocase = volume_info.nocase;
1699 } else { 1809 } else {
1700 tcon = tconInfoAlloc(); 1810 tcon = tconInfoAlloc();
1701 if (tcon == NULL) 1811 if (tcon == NULL)
@@ -1724,6 +1834,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1724 if (!rc) { 1834 if (!rc) {
1725 atomic_inc(&pSesInfo->inUse); 1835 atomic_inc(&pSesInfo->inUse);
1726 tcon->retry = volume_info.retry; 1836 tcon->retry = volume_info.retry;
1837 tcon->nocase = volume_info.nocase;
1727 } 1838 }
1728 } 1839 }
1729 } 1840 }
@@ -1745,8 +1856,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1745 spin_lock(&GlobalMid_Lock); 1856 spin_lock(&GlobalMid_Lock);
1746 srvTcp->tcpStatus = CifsExiting; 1857 srvTcp->tcpStatus = CifsExiting;
1747 spin_unlock(&GlobalMid_Lock); 1858 spin_unlock(&GlobalMid_Lock);
1748 if(srvTcp->tsk) 1859 if(srvTcp->tsk) {
1749 send_sig(SIGKILL,srvTcp->tsk,1); 1860 send_sig(SIGKILL,srvTcp->tsk,1);
1861 wait_for_completion(&cifsd_complete);
1862 }
1750 } 1863 }
1751 /* If find_unc succeeded then rc == 0 so we can not end */ 1864 /* If find_unc succeeded then rc == 0 so we can not end */
1752 if (tcon) /* up accidently freeing someone elses tcon struct */ 1865 if (tcon) /* up accidently freeing someone elses tcon struct */
@@ -1759,8 +1872,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1759 temp_rc = CIFSSMBLogoff(xid, pSesInfo); 1872 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1760 /* if the socketUseCount is now zero */ 1873 /* if the socketUseCount is now zero */
1761 if((temp_rc == -ESHUTDOWN) && 1874 if((temp_rc == -ESHUTDOWN) &&
1762 (pSesInfo->server->tsk)) 1875 (pSesInfo->server->tsk)) {
1763 send_sig(SIGKILL,pSesInfo->server->tsk,1); 1876 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1877 wait_for_completion(&cifsd_complete);
1878 }
1764 } else 1879 } else
1765 cFYI(1, ("No session or bad tcon")); 1880 cFYI(1, ("No session or bad tcon"));
1766 sesInfoFree(pSesInfo); 1881 sesInfoFree(pSesInfo);
@@ -1783,8 +1898,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1783 cFYI(1,("server negotiated posix acl support")); 1898 cFYI(1,("server negotiated posix acl support"));
1784 sb->s_flags |= MS_POSIXACL; 1899 sb->s_flags |= MS_POSIXACL;
1785 } 1900 }
1901
1902 /* Try and negotiate POSIX pathnames if we can. */
1903 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1904 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1905 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1906 cFYI(1,("negotiated posix pathnames support"));
1907 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1908 } else {
1909 cFYI(1,("posix pathnames support requested but not supported"));
1910 }
1911 }
1786 } 1912 }
1787 } 1913 }
1914 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1915 cifs_sb->wsize = min(cifs_sb->wsize,
1916 (tcon->ses->server->maxBuf -
1917 MAX_CIFS_HDR_SIZE));
1918 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1919 cifs_sb->rsize = min(cifs_sb->rsize,
1920 (tcon->ses->server->maxBuf -
1921 MAX_CIFS_HDR_SIZE));
1788 } 1922 }
1789 1923
1790 /* volume_info.password is freed above when existing session found 1924 /* volume_info.password is freed above when existing session found
@@ -1832,6 +1966,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1832 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 1966 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1833 NULL /* no tCon exists yet */ , 13 /* wct */ ); 1967 NULL /* no tCon exists yet */ , 13 /* wct */ );
1834 1968
1969 smb_buffer->Mid = GetNextMid(ses->server);
1835 pSMB->req_no_secext.AndXCommand = 0xFF; 1970 pSMB->req_no_secext.AndXCommand = 0xFF;
1836 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 1971 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1837 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 1972 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
@@ -2107,6 +2242,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2107 /* send SMBsessionSetup here */ 2242 /* send SMBsessionSetup here */
2108 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2243 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2109 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2244 NULL /* no tCon exists yet */ , 12 /* wct */ );
2245
2246 smb_buffer->Mid = GetNextMid(ses->server);
2110 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2247 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2111 pSMB->req.AndXCommand = 0xFF; 2248 pSMB->req.AndXCommand = 0xFF;
2112 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2249 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
@@ -2373,6 +2510,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2373 /* send SMBsessionSetup here */ 2510 /* send SMBsessionSetup here */
2374 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2511 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2375 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2512 NULL /* no tCon exists yet */ , 12 /* wct */ );
2513
2514 smb_buffer->Mid = GetNextMid(ses->server);
2376 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2515 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2377 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2516 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2378 2517
@@ -2715,6 +2854,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2715 /* send SMBsessionSetup here */ 2854 /* send SMBsessionSetup here */
2716 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2855 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2717 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2856 NULL /* no tCon exists yet */ , 12 /* wct */ );
2857
2858 smb_buffer->Mid = GetNextMid(ses->server);
2718 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2859 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2719 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2860 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2720 pSMB->req.AndXCommand = 0xFF; 2861 pSMB->req.AndXCommand = 0xFF;
@@ -3086,6 +3227,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3086 3227
3087 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, 3228 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3088 NULL /*no tid */ , 4 /*wct */ ); 3229 NULL /*no tid */ , 4 /*wct */ );
3230
3231 smb_buffer->Mid = GetNextMid(ses->server);
3089 smb_buffer->Uid = ses->Suid; 3232 smb_buffer->Uid = ses->Suid;
3090 pSMB = (TCONX_REQ *) smb_buffer; 3233 pSMB = (TCONX_REQ *) smb_buffer;
3091 pSMBr = (TCONX_RSP *) smb_buffer_response; 3234 pSMBr = (TCONX_RSP *) smb_buffer_response;
@@ -3207,8 +3350,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3207 return 0; 3350 return 0;
3208 } else if (rc == -ESHUTDOWN) { 3351 } else if (rc == -ESHUTDOWN) {
3209 cFYI(1,("Waking up socket by sending it signal")); 3352 cFYI(1,("Waking up socket by sending it signal"));
3210 if(cifsd_task) 3353 if(cifsd_task) {
3211 send_sig(SIGKILL,cifsd_task,1); 3354 send_sig(SIGKILL,cifsd_task,1);
3355 wait_for_completion(&cifsd_complete);
3356 }
3212 rc = 0; 3357 rc = 0;
3213 } /* else - we have an smb session 3358 } /* else - we have an smb session
3214 left on this socket do not kill cifsd */ 3359 left on this socket do not kill cifsd */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index d335269bd91c..8dfe717a332a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -48,6 +48,7 @@ build_path_from_dentry(struct dentry *direntry)
48 struct dentry *temp; 48 struct dentry *temp;
49 int namelen = 0; 49 int namelen = 0;
50 char *full_path; 50 char *full_path;
51 char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
51 52
52 if(direntry == NULL) 53 if(direntry == NULL)
53 return NULL; /* not much we can do if dentry is freed and 54 return NULL; /* not much we can do if dentry is freed and
@@ -74,7 +75,7 @@ cifs_bp_rename_retry:
74 if (namelen < 0) { 75 if (namelen < 0) {
75 break; 76 break;
76 } else { 77 } else {
77 full_path[namelen] = '\\'; 78 full_path[namelen] = dirsep;
78 strncpy(full_path + namelen + 1, temp->d_name.name, 79 strncpy(full_path + namelen + 1, temp->d_name.name,
79 temp->d_name.len); 80 temp->d_name.len);
80 cFYI(0, (" name: %s ", full_path + namelen)); 81 cFYI(0, (" name: %s ", full_path + namelen));
@@ -183,6 +184,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
183 desiredAccess, CREATE_NOT_DIR, 184 desiredAccess, CREATE_NOT_DIR,
184 &fileHandle, &oplock, buf, cifs_sb->local_nls, 185 &fileHandle, &oplock, buf, cifs_sb->local_nls,
185 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 186 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
187 if(rc == -EIO) {
188 /* old server, retry the open legacy style */
189 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
190 desiredAccess, CREATE_NOT_DIR,
191 &fileHandle, &oplock, buf, cifs_sb->local_nls,
192 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
193 }
186 if (rc) { 194 if (rc) {
187 cFYI(1, ("cifs_create returned 0x%x ", rc)); 195 cFYI(1, ("cifs_create returned 0x%x ", rc));
188 } else { 196 } else {
@@ -208,7 +216,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
208 CIFS_MOUNT_MAP_SPECIAL_CHR); 216 CIFS_MOUNT_MAP_SPECIAL_CHR);
209 } 217 }
210 else { 218 else {
211 /* BB implement via Windows security descriptors */ 219 /* BB implement mode setting via Windows security descriptors */
212 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ 220 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
213 /* could set r/o dos attribute if mode & 0222 == 0 */ 221 /* could set r/o dos attribute if mode & 0222 == 0 */
214 } 222 }
@@ -225,10 +233,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
225 } 233 }
226 234
227 if (rc != 0) { 235 if (rc != 0) {
228 cFYI(1,("Create worked but get_inode_info failed with rc = %d", 236 cFYI(1,
237 ("Create worked but get_inode_info failed rc = %d",
229 rc)); 238 rc));
230 } else { 239 } else {
231 direntry->d_op = &cifs_dentry_ops; 240 if (pTcon->nocase)
241 direntry->d_op = &cifs_ci_dentry_ops;
242 else
243 direntry->d_op = &cifs_dentry_ops;
232 d_instantiate(direntry, newinode); 244 d_instantiate(direntry, newinode);
233 } 245 }
234 if((nd->flags & LOOKUP_OPEN) == FALSE) { 246 if((nd->flags & LOOKUP_OPEN) == FALSE) {
@@ -302,8 +314,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
302 up(&direntry->d_sb->s_vfs_rename_sem); 314 up(&direntry->d_sb->s_vfs_rename_sem);
303 if(full_path == NULL) 315 if(full_path == NULL)
304 rc = -ENOMEM; 316 rc = -ENOMEM;
305 317 else if (pTcon->ses->capabilities & CAP_UNIX) {
306 if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
307 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 318 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
308 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 319 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
309 mode,(__u64)current->euid,(__u64)current->egid, 320 mode,(__u64)current->euid,(__u64)current->egid,
@@ -321,10 +332,49 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
321 if(!rc) { 332 if(!rc) {
322 rc = cifs_get_inode_info_unix(&newinode, full_path, 333 rc = cifs_get_inode_info_unix(&newinode, full_path,
323 inode->i_sb,xid); 334 inode->i_sb,xid);
324 direntry->d_op = &cifs_dentry_ops; 335 if (pTcon->nocase)
336 direntry->d_op = &cifs_ci_dentry_ops;
337 else
338 direntry->d_op = &cifs_dentry_ops;
325 if(rc == 0) 339 if(rc == 0)
326 d_instantiate(direntry, newinode); 340 d_instantiate(direntry, newinode);
327 } 341 }
342 } else {
343 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
344 int oplock = 0;
345 u16 fileHandle;
346 FILE_ALL_INFO * buf;
347
348 cFYI(1,("sfu compat create special file"));
349
350 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
351 if(buf == NULL) {
352 kfree(full_path);
353 FreeXid(xid);
354 return -ENOMEM;
355 }
356
357 rc = CIFSSMBOpen(xid, pTcon, full_path,
358 FILE_CREATE, /* fail if exists */
359 GENERIC_WRITE /* BB would
360 WRITE_OWNER | WRITE_DAC be better? */,
361 /* Create a file and set the
362 file attribute to SYSTEM */
363 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
364 &fileHandle, &oplock, buf,
365 cifs_sb->local_nls,
366 cifs_sb->mnt_cifs_flags &
367 CIFS_MOUNT_MAP_SPECIAL_CHR);
368
369 if(!rc) {
370 /* BB Do not bother to decode buf since no
371 local inode yet to put timestamps in */
372 CIFSSMBClose(xid, pTcon, fileHandle);
373 d_drop(direntry);
374 }
375 kfree(buf);
376 /* add code here to set EAs */
377 }
328 } 378 }
329 379
330 kfree(full_path); 380 kfree(full_path);
@@ -381,7 +431,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
381 parent_dir_inode->i_sb,xid); 431 parent_dir_inode->i_sb,xid);
382 432
383 if ((rc == 0) && (newInode != NULL)) { 433 if ((rc == 0) && (newInode != NULL)) {
384 direntry->d_op = &cifs_dentry_ops; 434 if (pTcon->nocase)
435 direntry->d_op = &cifs_ci_dentry_ops;
436 else
437 direntry->d_op = &cifs_dentry_ops;
385 d_add(direntry, newInode); 438 d_add(direntry, newInode);
386 439
387 /* since paths are not looked up by component - the parent directories are presumed to be good here */ 440 /* since paths are not looked up by component - the parent directories are presumed to be good here */
@@ -440,3 +493,42 @@ struct dentry_operations cifs_dentry_ops = {
440/* d_delete: cifs_d_delete, *//* not needed except for debugging */ 493/* d_delete: cifs_d_delete, *//* not needed except for debugging */
441 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ 494 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
442}; 495};
496
497static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
498{
499 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
500 unsigned long hash;
501 int i;
502
503 hash = init_name_hash();
504 for (i = 0; i < q->len; i++)
505 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
506 hash);
507 q->hash = end_name_hash(hash);
508
509 return 0;
510}
511
512static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
513 struct qstr *b)
514{
515 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
516
517 if ((a->len == b->len) &&
518 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
519 /*
520 * To preserve case, don't let an existing negative dentry's
521 * case take precedence. If a is not a negative dentry, this
522 * should have no side effects
523 */
524 memcpy((unsigned char *)a->name, b->name, a->len);
525 return 0;
526 }
527 return 1;
528}
529
530struct dentry_operations cifs_ci_dentry_ops = {
531 .d_revalidate = cifs_d_revalidate,
532 .d_hash = cifs_ci_hash,
533 .d_compare = cifs_ci_compare,
534};
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 7d2a9202c39a..a7a47bb36bf3 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -78,6 +78,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
78 __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; 78 __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
79 __u16 netfid; 79 __u16 netfid;
80 80
81
82 if(experimEnabled == 0)
83 return 0;
84
81 xid = GetXid(); 85 xid = GetXid();
82 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 86 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
83 pTcon = cifs_sb->tcon; 87 pTcon = cifs_sb->tcon;
@@ -100,8 +104,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
100 } else { 104 } else {
101 filter = convert_to_cifs_notify_flags(arg); 105 filter = convert_to_cifs_notify_flags(arg);
102 if(filter != 0) { 106 if(filter != 0) {
103 rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, 107 rc = CIFSSMBNotify(xid, pTcon,
104 filter, cifs_sb->local_nls); 108 0 /* no subdirs */, netfid,
109 filter, file, arg & DN_MULTISHOT,
110 cifs_sb->local_nls);
105 } else { 111 } else {
106 rc = -EINVAL; 112 rc = -EINVAL;
107 } 113 }
@@ -109,7 +115,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
109 it would close automatically but may be a way 115 it would close automatically but may be a way
110 to do it easily when inode freed or when 116 to do it easily when inode freed or when
111 notify info is cleared/changed */ 117 notify info is cleared/changed */
112 cERROR(1,("notify rc %d",rc)); 118 cFYI(1,("notify rc %d",rc));
113 } 119 }
114 } 120 }
115 121
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 3497125189df..da4f5e10b3cc 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -21,11 +21,15 @@
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/backing-dev.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#include <linux/fcntl.h> 26#include <linux/fcntl.h>
27#include <linux/mpage.h>
26#include <linux/pagemap.h> 28#include <linux/pagemap.h>
27#include <linux/pagevec.h> 29#include <linux/pagevec.h>
28#include <linux/smp_lock.h> 30#include <linux/smp_lock.h>
31#include <linux/writeback.h>
32#include <linux/delay.h>
29#include <asm/div64.h> 33#include <asm/div64.h>
30#include "cifsfs.h" 34#include "cifsfs.h"
31#include "cifspdu.h" 35#include "cifspdu.h"
@@ -47,6 +51,11 @@ static inline struct cifsFileInfo *cifs_init_private(
47 private_data->pInode = inode; 51 private_data->pInode = inode;
48 private_data->invalidHandle = FALSE; 52 private_data->invalidHandle = FALSE;
49 private_data->closePend = FALSE; 53 private_data->closePend = FALSE;
54 /* we have to track num writers to the inode, since writepages
55 does not tell us which handle the write is for so there can
56 be a close (overlapping with write) of the filehandle that
57 cifs_writepages chose to use */
58 atomic_set(&private_data->wrtPending,0);
50 59
51 return private_data; 60 return private_data;
52} 61}
@@ -256,6 +265,13 @@ int cifs_open(struct inode *inode, struct file *file)
256 CREATE_NOT_DIR, &netfid, &oplock, buf, 265 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 266 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258 & CIFS_MOUNT_MAP_SPECIAL_CHR); 267 & CIFS_MOUNT_MAP_SPECIAL_CHR);
268 if (rc == -EIO) {
269 /* Old server, try legacy style OpenX */
270 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
271 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
272 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
273 & CIFS_MOUNT_MAP_SPECIAL_CHR);
274 }
259 if (rc) { 275 if (rc) {
260 cFYI(1, ("cifs_open returned 0x%x ", rc)); 276 cFYI(1, ("cifs_open returned 0x%x ", rc));
261 goto out; 277 goto out;
@@ -463,6 +479,20 @@ int cifs_close(struct inode *inode, struct file *file)
463 /* no sense reconnecting to close a file that is 479 /* no sense reconnecting to close a file that is
464 already closed */ 480 already closed */
465 if (pTcon->tidStatus != CifsNeedReconnect) { 481 if (pTcon->tidStatus != CifsNeedReconnect) {
482 int timeout = 2;
483 while((atomic_read(&pSMBFile->wrtPending) != 0)
484 && (timeout < 1000) ) {
485 /* Give write a better chance to get to
486 server ahead of the close. We do not
487 want to add a wait_q here as it would
488 increase the memory utilization as
489 the struct would be in each open file,
490 but this should give enough time to
491 clear the socket */
492 cERROR(1,("close with pending writes"));
493 msleep(timeout);
494 timeout *= 4;
495 }
466 write_unlock(&file->f_owner.lock); 496 write_unlock(&file->f_owner.lock);
467 rc = CIFSSMBClose(xid, pTcon, 497 rc = CIFSSMBClose(xid, pTcon,
468 pSMBFile->netfid); 498 pSMBFile->netfid);
@@ -744,14 +774,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
744 15 seconds is plenty */ 774 15 seconds is plenty */
745 } 775 }
746 776
747#ifdef CONFIG_CIFS_STATS 777 cifs_stats_bytes_written(pTcon, total_written);
748 if (total_written > 0) {
749 atomic_inc(&pTcon->num_writes);
750 spin_lock(&pTcon->stat_lock);
751 pTcon->bytes_written += total_written;
752 spin_unlock(&pTcon->stat_lock);
753 }
754#endif
755 778
756 /* since the write may have blocked check these pointers again */ 779 /* since the write may have blocked check these pointers again */
757 if (file->f_dentry) { 780 if (file->f_dentry) {
@@ -791,9 +814,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
791 814
792 pTcon = cifs_sb->tcon; 815 pTcon = cifs_sb->tcon;
793 816
794 /* cFYI(1, 817 cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
795 (" write %d bytes to offset %lld of %s", write_size, 818 *poffset, file->f_dentry->d_name.name));
796 *poffset, file->f_dentry->d_name.name)); */
797 819
798 if (file->private_data == NULL) 820 if (file->private_data == NULL)
799 return -EBADF; 821 return -EBADF;
@@ -846,7 +868,26 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
846 if (rc != 0) 868 if (rc != 0)
847 break; 869 break;
848 } 870 }
849 871#ifdef CONFIG_CIFS_EXPERIMENTAL
872 /* BB FIXME We can not sign across two buffers yet */
873 if((experimEnabled) && ((pTcon->ses->server->secMode &
874 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
875 struct kvec iov[2];
876 unsigned int len;
877
878 len = min((size_t)cifs_sb->wsize,
879 write_size - total_written);
880 /* iov[0] is reserved for smb header */
881 iov[1].iov_base = (char *)write_data +
882 total_written;
883 iov[1].iov_len = len;
884 rc = CIFSSMBWrite2(xid, pTcon,
885 open_file->netfid, len,
886 *poffset, &bytes_written,
887 iov, 1, long_op);
888 } else
889 /* BB FIXME fixup indentation of line below */
890#endif
850 rc = CIFSSMBWrite(xid, pTcon, 891 rc = CIFSSMBWrite(xid, pTcon,
851 open_file->netfid, 892 open_file->netfid,
852 min_t(const int, cifs_sb->wsize, 893 min_t(const int, cifs_sb->wsize,
@@ -867,14 +908,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
867 15 seconds is plenty */ 908 15 seconds is plenty */
868 } 909 }
869 910
870#ifdef CONFIG_CIFS_STATS 911 cifs_stats_bytes_written(pTcon, total_written);
871 if (total_written > 0) {
872 atomic_inc(&pTcon->num_writes);
873 spin_lock(&pTcon->stat_lock);
874 pTcon->bytes_written += total_written;
875 spin_unlock(&pTcon->stat_lock);
876 }
877#endif
878 912
879 /* since the write may have blocked check these pointers again */ 913 /* since the write may have blocked check these pointers again */
880 if (file->f_dentry) { 914 if (file->f_dentry) {
@@ -893,6 +927,43 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
893 return total_written; 927 return total_written;
894} 928}
895 929
930struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
931{
932 struct cifsFileInfo *open_file;
933 int rc;
934
935 read_lock(&GlobalSMBSeslock);
936 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
937 if (open_file->closePend)
938 continue;
939 if (open_file->pfile &&
940 ((open_file->pfile->f_flags & O_RDWR) ||
941 (open_file->pfile->f_flags & O_WRONLY))) {
942 atomic_inc(&open_file->wrtPending);
943 read_unlock(&GlobalSMBSeslock);
944 if((open_file->invalidHandle) &&
945 (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
946 rc = cifs_reopen_file(&cifs_inode->vfs_inode,
947 open_file->pfile, FALSE);
948 /* if it fails, try another handle - might be */
949 /* dangerous to hold up writepages with retry */
950 if(rc) {
951 cFYI(1,("failed on reopen file in wp"));
952 read_lock(&GlobalSMBSeslock);
953 /* can not use this handle, no write
954 pending on this one after all */
955 atomic_dec
956 (&open_file->wrtPending);
957 continue;
958 }
959 }
960 return open_file;
961 }
962 }
963 read_unlock(&GlobalSMBSeslock);
964 return NULL;
965}
966
896static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) 967static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
897{ 968{
898 struct address_space *mapping = page->mapping; 969 struct address_space *mapping = page->mapping;
@@ -903,10 +974,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
903 struct cifs_sb_info *cifs_sb; 974 struct cifs_sb_info *cifs_sb;
904 struct cifsTconInfo *pTcon; 975 struct cifsTconInfo *pTcon;
905 struct inode *inode; 976 struct inode *inode;
906 struct cifsInodeInfo *cifsInode; 977 struct cifsFileInfo *open_file;
907 struct cifsFileInfo *open_file = NULL;
908 struct list_head *tmp;
909 struct list_head *tmp1;
910 978
911 if (!mapping || !mapping->host) 979 if (!mapping || !mapping->host)
912 return -EFAULT; 980 return -EFAULT;
@@ -934,49 +1002,20 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
934 if (mapping->host->i_size - offset < (loff_t)to) 1002 if (mapping->host->i_size - offset < (loff_t)to)
935 to = (unsigned)(mapping->host->i_size - offset); 1003 to = (unsigned)(mapping->host->i_size - offset);
936 1004
937 cifsInode = CIFS_I(mapping->host); 1005 open_file = find_writable_file(CIFS_I(mapping->host));
938 read_lock(&GlobalSMBSeslock); 1006 if (open_file) {
939 /* BB we should start at the end */ 1007 bytes_written = cifs_write(open_file->pfile, write_data,
940 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { 1008 to-from, &offset);
941 open_file = list_entry(tmp, struct cifsFileInfo, flist); 1009 atomic_dec(&open_file->wrtPending);
942 if (open_file->closePend)
943 continue;
944 /* We check if file is open for writing first */
945 if ((open_file->pfile) &&
946 ((open_file->pfile->f_flags & O_RDWR) ||
947 (open_file->pfile->f_flags & O_WRONLY))) {
948 read_unlock(&GlobalSMBSeslock);
949 bytes_written = cifs_write(open_file->pfile,
950 write_data, to-from,
951 &offset);
952 read_lock(&GlobalSMBSeslock);
953 /* Does mm or vfs already set times? */ 1010 /* Does mm or vfs already set times? */
954 inode->i_atime = 1011 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
955 inode->i_mtime = current_fs_time(inode->i_sb); 1012 if ((bytes_written > 0) && (offset)) {
956 if ((bytes_written > 0) && (offset)) { 1013 rc = 0;
957 rc = 0; 1014 } else if (bytes_written < 0) {
958 } else if (bytes_written < 0) { 1015 if (rc != -EBADF)
959 if (rc == -EBADF) { 1016 rc = bytes_written;
960 /* have seen a case in which kernel seemed to
961 have closed/freed a file even with writes
962 active so we might as well see if there are
963 other file structs to try for the same
964 inode before giving up */
965 continue;
966 } else
967 rc = bytes_written;
968 }
969 break; /* now that we found a valid file handle and
970 tried to write to it we are done, no sense
971 continuing to loop looking for another */
972 }
973 if (tmp->next == NULL) {
974 cFYI(1, ("File instance %p removed", tmp));
975 break;
976 } 1017 }
977 } 1018 } else {
978 read_unlock(&GlobalSMBSeslock);
979 if (open_file == NULL) {
980 cFYI(1, ("No writeable filehandles for inode")); 1019 cFYI(1, ("No writeable filehandles for inode"));
981 rc = -EIO; 1020 rc = -EIO;
982 } 1021 }
@@ -985,20 +1024,207 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
985 return rc; 1024 return rc;
986} 1025}
987 1026
988#if 0 1027#ifdef CONFIG_CIFS_EXPERIMENTAL
989static int cifs_writepages(struct address_space *mapping, 1028static int cifs_writepages(struct address_space *mapping,
990 struct writeback_control *wbc) 1029 struct writeback_control *wbc)
991{ 1030{
992 int rc = -EFAULT; 1031 struct backing_dev_info *bdi = mapping->backing_dev_info;
1032 unsigned int bytes_to_write;
1033 unsigned int bytes_written;
1034 struct cifs_sb_info *cifs_sb;
1035 int done = 0;
1036 pgoff_t end = -1;
1037 pgoff_t index;
1038 int is_range = 0;
1039 struct kvec iov[32];
1040 int len;
1041 int n_iov = 0;
1042 pgoff_t next;
1043 int nr_pages;
1044 __u64 offset = 0;
1045 struct cifsFileInfo *open_file;
1046 struct page *page;
1047 struct pagevec pvec;
1048 int rc = 0;
1049 int scanned = 0;
993 int xid; 1050 int xid;
994 1051
1052 cifs_sb = CIFS_SB(mapping->host->i_sb);
1053
1054 /*
1055 * If wsize is smaller that the page cache size, default to writing
1056 * one page at a time via cifs_writepage
1057 */
1058 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1059 return generic_writepages(mapping, wbc);
1060
1061 /* BB FIXME we do not have code to sign across multiple buffers yet,
1062 so go to older writepage style write which we can sign if needed */
1063 if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1064 if(cifs_sb->tcon->ses->server->secMode &
1065 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1066 return generic_writepages(mapping, wbc);
1067
1068 /*
1069 * BB: Is this meaningful for a non-block-device file system?
1070 * If it is, we should test it again after we do I/O
1071 */
1072 if (wbc->nonblocking && bdi_write_congested(bdi)) {
1073 wbc->encountered_congestion = 1;
1074 return 0;
1075 }
1076
995 xid = GetXid(); 1077 xid = GetXid();
996 1078
997 /* Find contiguous pages then iterate through repeating 1079 pagevec_init(&pvec, 0);
998 call 16K write then Setpageuptodate or if LARGE_WRITE_X 1080 if (wbc->sync_mode == WB_SYNC_NONE)
999 support then send larger writes via kevec so as to eliminate 1081 index = mapping->writeback_index; /* Start from prev offset */
1000 a memcpy */ 1082 else {
1083 index = 0;
1084 scanned = 1;
1085 }
1086 if (wbc->start || wbc->end) {
1087 index = wbc->start >> PAGE_CACHE_SHIFT;
1088 end = wbc->end >> PAGE_CACHE_SHIFT;
1089 is_range = 1;
1090 scanned = 1;
1091 }
1092retry:
1093 while (!done && (index <= end) &&
1094 (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1095 PAGECACHE_TAG_DIRTY,
1096 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1097 int first;
1098 unsigned int i;
1099
1100 first = -1;
1101 next = 0;
1102 n_iov = 0;
1103 bytes_to_write = 0;
1104
1105 for (i = 0; i < nr_pages; i++) {
1106 page = pvec.pages[i];
1107 /*
1108 * At this point we hold neither mapping->tree_lock nor
1109 * lock on the page itself: the page may be truncated or
1110 * invalidated (changing page->mapping to NULL), or even
1111 * swizzled back from swapper_space to tmpfs file
1112 * mapping
1113 */
1114
1115 if (first < 0)
1116 lock_page(page);
1117 else if (TestSetPageLocked(page))
1118 break;
1119
1120 if (unlikely(page->mapping != mapping)) {
1121 unlock_page(page);
1122 break;
1123 }
1124
1125 if (unlikely(is_range) && (page->index > end)) {
1126 done = 1;
1127 unlock_page(page);
1128 break;
1129 }
1130
1131 if (next && (page->index != next)) {
1132 /* Not next consecutive page */
1133 unlock_page(page);
1134 break;
1135 }
1136
1137 if (wbc->sync_mode != WB_SYNC_NONE)
1138 wait_on_page_writeback(page);
1139
1140 if (PageWriteback(page) ||
1141 !test_clear_page_dirty(page)) {
1142 unlock_page(page);
1143 break;
1144 }
1145
1146 if (page_offset(page) >= mapping->host->i_size) {
1147 done = 1;
1148 unlock_page(page);
1149 break;
1150 }
1151
1152 /*
1153 * BB can we get rid of this? pages are held by pvec
1154 */
1155 page_cache_get(page);
1156
1157 len = min(mapping->host->i_size - page_offset(page),
1158 (loff_t)PAGE_CACHE_SIZE);
1159
1160 /* reserve iov[0] for the smb header */
1161 n_iov++;
1162 iov[n_iov].iov_base = kmap(page);
1163 iov[n_iov].iov_len = len;
1164 bytes_to_write += len;
1165
1166 if (first < 0) {
1167 first = i;
1168 offset = page_offset(page);
1169 }
1170 next = page->index + 1;
1171 if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1172 break;
1173 }
1174 if (n_iov) {
1175 /* Search for a writable handle every time we call
1176 * CIFSSMBWrite2. We can't rely on the last handle
1177 * we used to still be valid
1178 */
1179 open_file = find_writable_file(CIFS_I(mapping->host));
1180 if (!open_file) {
1181 cERROR(1, ("No writable handles for inode"));
1182 rc = -EBADF;
1183 } else {
1184 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1185 open_file->netfid,
1186 bytes_to_write, offset,
1187 &bytes_written, iov, n_iov,
1188 1);
1189 atomic_dec(&open_file->wrtPending);
1190 if (rc || bytes_written < bytes_to_write) {
1191 cERROR(1,("Write2 ret %d, written = %d",
1192 rc, bytes_written));
1193 /* BB what if continued retry is
1194 requested via mount flags? */
1195 set_bit(AS_EIO, &mapping->flags);
1196 SetPageError(page);
1197 } else {
1198 cifs_stats_bytes_written(cifs_sb->tcon,
1199 bytes_written);
1200 }
1201 }
1202 for (i = 0; i < n_iov; i++) {
1203 page = pvec.pages[first + i];
1204 kunmap(page);
1205 unlock_page(page);
1206 page_cache_release(page);
1207 }
1208 if ((wbc->nr_to_write -= n_iov) <= 0)
1209 done = 1;
1210 index = next;
1211 }
1212 pagevec_release(&pvec);
1213 }
1214 if (!scanned && !done) {
1215 /*
1216 * We hit the last page and there is more work to be done: wrap
1217 * back to the start of the file
1218 */
1219 scanned = 1;
1220 index = 0;
1221 goto retry;
1222 }
1223 if (!is_range)
1224 mapping->writeback_index = index;
1225
1001 FreeXid(xid); 1226 FreeXid(xid);
1227
1002 return rc; 1228 return rc;
1003} 1229}
1004#endif 1230#endif
@@ -1207,12 +1433,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1207 if (rc != 0) 1433 if (rc != 0)
1208 break; 1434 break;
1209 } 1435 }
1210
1211 rc = CIFSSMBRead(xid, pTcon, 1436 rc = CIFSSMBRead(xid, pTcon,
1212 open_file->netfid, 1437 open_file->netfid,
1213 current_read_size, *poffset, 1438 current_read_size, *poffset,
1214 &bytes_read, &smb_read_data); 1439 &bytes_read, &smb_read_data);
1215
1216 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1440 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1217 if (copy_to_user(current_offset, 1441 if (copy_to_user(current_offset,
1218 smb_read_data + 4 /* RFC1001 hdr */ 1442 smb_read_data + 4 /* RFC1001 hdr */
@@ -1235,12 +1459,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1235 return rc; 1459 return rc;
1236 } 1460 }
1237 } else { 1461 } else {
1238#ifdef CONFIG_CIFS_STATS 1462 cifs_stats_bytes_read(pTcon, bytes_read);
1239 atomic_inc(&pTcon->num_reads);
1240 spin_lock(&pTcon->stat_lock);
1241 pTcon->bytes_read += total_read;
1242 spin_unlock(&pTcon->stat_lock);
1243#endif
1244 *poffset += bytes_read; 1463 *poffset += bytes_read;
1245 } 1464 }
1246 } 1465 }
@@ -1280,6 +1499,13 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1280 total_read += bytes_read, current_offset += bytes_read) { 1499 total_read += bytes_read, current_offset += bytes_read) {
1281 current_read_size = min_t(const int, read_size - total_read, 1500 current_read_size = min_t(const int, read_size - total_read,
1282 cifs_sb->rsize); 1501 cifs_sb->rsize);
1502 /* For windows me and 9x we do not want to request more
1503 than it negotiated since it will refuse the read then */
1504 if((pTcon->ses) &&
1505 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1506 current_read_size = min_t(const int, current_read_size,
1507 pTcon->ses->server->maxBuf - 128);
1508 }
1283 rc = -EAGAIN; 1509 rc = -EAGAIN;
1284 while (rc == -EAGAIN) { 1510 while (rc == -EAGAIN) {
1285 if ((open_file->invalidHandle) && 1511 if ((open_file->invalidHandle) &&
@@ -1289,11 +1515,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1289 if (rc != 0) 1515 if (rc != 0)
1290 break; 1516 break;
1291 } 1517 }
1292
1293 rc = CIFSSMBRead(xid, pTcon, 1518 rc = CIFSSMBRead(xid, pTcon,
1294 open_file->netfid, 1519 open_file->netfid,
1295 current_read_size, *poffset, 1520 current_read_size, *poffset,
1296 &bytes_read, &current_offset); 1521 &bytes_read, &current_offset);
1297 } 1522 }
1298 if (rc || (bytes_read == 0)) { 1523 if (rc || (bytes_read == 0)) {
1299 if (total_read) { 1524 if (total_read) {
@@ -1303,12 +1528,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1303 return rc; 1528 return rc;
1304 } 1529 }
1305 } else { 1530 } else {
1306#ifdef CONFIG_CIFS_STATS 1531 cifs_stats_bytes_read(pTcon, total_read);
1307 atomic_inc(&pTcon->num_reads);
1308 spin_lock(&pTcon->stat_lock);
1309 pTcon->bytes_read += total_read;
1310 spin_unlock(&pTcon->stat_lock);
1311#endif
1312 *poffset += bytes_read; 1532 *poffset += bytes_read;
1313 } 1533 }
1314 } 1534 }
@@ -1452,10 +1672,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1452 } 1672 }
1453 1673
1454 rc = CIFSSMBRead(xid, pTcon, 1674 rc = CIFSSMBRead(xid, pTcon,
1455 open_file->netfid, 1675 open_file->netfid,
1456 read_size, offset, 1676 read_size, offset,
1457 &bytes_read, &smb_read_data); 1677 &bytes_read, &smb_read_data);
1458 /* BB need to check return code here */ 1678
1679 /* BB more RC checks ? */
1459 if (rc== -EAGAIN) { 1680 if (rc== -EAGAIN) {
1460 if (smb_read_data) { 1681 if (smb_read_data) {
1461 cifs_buf_release(smb_read_data); 1682 cifs_buf_release(smb_read_data);
@@ -1480,12 +1701,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1480 le16_to_cpu(pSMBr->DataOffset), &lru_pvec); 1701 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1481 1702
1482 i += bytes_read >> PAGE_CACHE_SHIFT; 1703 i += bytes_read >> PAGE_CACHE_SHIFT;
1483#ifdef CONFIG_CIFS_STATS 1704 cifs_stats_bytes_read(pTcon, bytes_read);
1484 atomic_inc(&pTcon->num_reads);
1485 spin_lock(&pTcon->stat_lock);
1486 pTcon->bytes_read += bytes_read;
1487 spin_unlock(&pTcon->stat_lock);
1488#endif
1489 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { 1705 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1490 i++; /* account for partial page */ 1706 i++; /* account for partial page */
1491 1707
@@ -1603,40 +1819,21 @@ static int cifs_readpage(struct file *file, struct page *page)
1603 page caching in the current Linux kernel design */ 1819 page caching in the current Linux kernel design */
1604int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) 1820int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1605{ 1821{
1606 struct list_head *tmp;
1607 struct list_head *tmp1;
1608 struct cifsFileInfo *open_file = NULL; 1822 struct cifsFileInfo *open_file = NULL;
1609 int rc = TRUE;
1610 1823
1611 if (cifsInode == NULL) 1824 if (cifsInode)
1612 return rc; 1825 open_file = find_writable_file(cifsInode);
1613 1826
1614 read_lock(&GlobalSMBSeslock); 1827 if(open_file) {
1615 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { 1828 /* there is not actually a write pending so let
1616 open_file = list_entry(tmp, struct cifsFileInfo, flist); 1829 this handle go free and allow it to
1617 if (open_file == NULL) 1830 be closable if needed */
1618 break; 1831 atomic_dec(&open_file->wrtPending);
1619 if (open_file->closePend) 1832 return 0;
1620 continue; 1833 } else
1621 /* We check if file is open for writing, 1834 return 1;
1622 BB we could supplement this with a check to see if file size
1623 changes have been flushed to server - ie inode metadata dirty */
1624 if ((open_file->pfile) &&
1625 ((open_file->pfile->f_flags & O_RDWR) ||
1626 (open_file->pfile->f_flags & O_WRONLY))) {
1627 rc = FALSE;
1628 break;
1629 }
1630 if (tmp->next == NULL) {
1631 cFYI(1, ("File instance %p removed", tmp));
1632 break;
1633 }
1634 }
1635 read_unlock(&GlobalSMBSeslock);
1636 return rc;
1637} 1835}
1638 1836
1639
1640static int cifs_prepare_write(struct file *file, struct page *page, 1837static int cifs_prepare_write(struct file *file, struct page *page,
1641 unsigned from, unsigned to) 1838 unsigned from, unsigned to)
1642{ 1839{
@@ -1676,6 +1873,9 @@ struct address_space_operations cifs_addr_ops = {
1676 .readpage = cifs_readpage, 1873 .readpage = cifs_readpage,
1677 .readpages = cifs_readpages, 1874 .readpages = cifs_readpages,
1678 .writepage = cifs_writepage, 1875 .writepage = cifs_writepage,
1876#ifdef CONFIG_CIFS_EXPERIMENTAL
1877 .writepages = cifs_writepages,
1878#endif
1679 .prepare_write = cifs_prepare_write, 1879 .prepare_write = cifs_prepare_write,
1680 .commit_write = cifs_commit_write, 1880 .commit_write = cifs_commit_write,
1681 .set_page_dirty = __set_page_dirty_nobuffers, 1881 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..912d401600f6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -166,7 +166,13 @@ int cifs_get_inode_info_unix(struct inode **pinode,
166 inode->i_fop = &cifs_file_direct_ops; 166 inode->i_fop = &cifs_file_direct_ops;
167 else 167 else
168 inode->i_fop = &cifs_file_ops; 168 inode->i_fop = &cifs_file_ops;
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
170 inode->i_fop->lock = NULL;
169 inode->i_data.a_ops = &cifs_addr_ops; 171 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL;
170 } else if (S_ISDIR(inode->i_mode)) { 176 } else if (S_ISDIR(inode->i_mode)) {
171 cFYI(1, (" Directory inode")); 177 cFYI(1, (" Directory inode"));
172 inode->i_op = &cifs_dir_inode_ops; 178 inode->i_op = &cifs_dir_inode_ops;
@@ -213,8 +219,18 @@ int cifs_get_inode_info(struct inode **pinode,
213 pfindData = (FILE_ALL_INFO *)buf; 219 pfindData = (FILE_ALL_INFO *)buf;
214 /* could do find first instead but this returns more info */ 220 /* could do find first instead but this returns more info */
215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 221 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 222 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR); 223 CIFS_MOUNT_MAP_SPECIAL_CHR);
224 /* BB optimize code so we do not make the above call
225 when server claims no NT SMB support and the above call
226 failed at least once - set flag in tcon or mount */
227 if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
228 rc = SMBQueryInformation(xid, pTcon, search_path,
229 pfindData, cifs_sb->local_nls,
230 cifs_sb->mnt_cifs_flags &
231 CIFS_MOUNT_MAP_SPECIAL_CHR);
232 }
233
218 } 234 }
219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 235 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
220 if (rc) { 236 if (rc) {
@@ -320,6 +336,16 @@ int cifs_get_inode_info(struct inode **pinode,
320 on dirs */ 336 on dirs */
321 inode->i_mode = cifs_sb->mnt_dir_mode; 337 inode->i_mode = cifs_sb->mnt_dir_mode;
322 inode->i_mode |= S_IFDIR; 338 inode->i_mode |= S_IFDIR;
339 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
340 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
341 /* No need to le64 convert size of zero */
342 (pfindData->EndOfFile == 0)) {
343 inode->i_mode = cifs_sb->mnt_file_mode;
344 inode->i_mode |= S_IFIFO;
345/* BB Finish for SFU style symlinks and devies */
346/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
347 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
348
323 } else { 349 } else {
324 inode->i_mode |= S_IFREG; 350 inode->i_mode |= S_IFREG;
325 /* treat the dos attribute of read-only as read-only 351 /* treat the dos attribute of read-only as read-only
@@ -359,7 +385,12 @@ int cifs_get_inode_info(struct inode **pinode,
359 inode->i_fop = &cifs_file_direct_ops; 385 inode->i_fop = &cifs_file_direct_ops;
360 else 386 else
361 inode->i_fop = &cifs_file_ops; 387 inode->i_fop = &cifs_file_ops;
388 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
389 inode->i_fop->lock = NULL;
362 inode->i_data.a_ops = &cifs_addr_ops; 390 inode->i_data.a_ops = &cifs_addr_ops;
391 if(pTcon->ses->server->maxBuf <
392 4096 + MAX_CIFS_HDR_SIZE)
393 inode->i_data.a_ops->readpages = NULL;
363 } else if (S_ISDIR(inode->i_mode)) { 394 } else if (S_ISDIR(inode->i_mode)) {
364 cFYI(1, (" Directory inode ")); 395 cFYI(1, (" Directory inode "));
365 inode->i_op = &cifs_dir_inode_ops; 396 inode->i_op = &cifs_dir_inode_ops;
@@ -577,7 +608,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 rc = cifs_get_inode_info(&newinode, full_path, NULL, 608 rc = cifs_get_inode_info(&newinode, full_path, NULL,
578 inode->i_sb,xid); 609 inode->i_sb,xid);
579 610
580 direntry->d_op = &cifs_dentry_ops; 611 if (pTcon->nocase)
612 direntry->d_op = &cifs_ci_dentry_ops;
613 else
614 direntry->d_op = &cifs_dentry_ops;
581 d_instantiate(direntry, newinode); 615 d_instantiate(direntry, newinode);
582 if (direntry->d_inode) 616 if (direntry->d_inode)
583 direntry->d_inode->i_nlink = 2; 617 direntry->d_inode->i_nlink = 2;
@@ -928,7 +962,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
928 struct cifsTconInfo *pTcon; 962 struct cifsTconInfo *pTcon;
929 char *full_path = NULL; 963 char *full_path = NULL;
930 int rc = -EACCES; 964 int rc = -EACCES;
931 int found = FALSE;
932 struct cifsFileInfo *open_file = NULL; 965 struct cifsFileInfo *open_file = NULL;
933 FILE_BASIC_INFO time_buf; 966 FILE_BASIC_INFO time_buf;
934 int set_time = FALSE; 967 int set_time = FALSE;
@@ -936,7 +969,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
936 __u64 uid = 0xFFFFFFFFFFFFFFFFULL; 969 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
937 __u64 gid = 0xFFFFFFFFFFFFFFFFULL; 970 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
938 struct cifsInodeInfo *cifsInode; 971 struct cifsInodeInfo *cifsInode;
939 struct list_head *tmp;
940 972
941 xid = GetXid(); 973 xid = GetXid();
942 974
@@ -961,7 +993,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
961 filemap_fdatawait(direntry->d_inode->i_mapping); 993 filemap_fdatawait(direntry->d_inode->i_mapping);
962 994
963 if (attrs->ia_valid & ATTR_SIZE) { 995 if (attrs->ia_valid & ATTR_SIZE) {
964 read_lock(&GlobalSMBSeslock);
965 /* To avoid spurious oplock breaks from server, in the case of 996 /* To avoid spurious oplock breaks from server, in the case of
966 inodes that we already have open, avoid doing path based 997 inodes that we already have open, avoid doing path based
967 setting of file size if we can do it by handle. 998 setting of file size if we can do it by handle.
@@ -969,40 +1000,23 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
969 when the local oplock break takes longer to flush 1000 when the local oplock break takes longer to flush
970 writebehind data than the SMB timeout for the SetPathInfo 1001 writebehind data than the SMB timeout for the SetPathInfo
971 request would allow */ 1002 request would allow */
972 list_for_each(tmp, &cifsInode->openFileList) { 1003 open_file = find_writable_file(cifsInode);
973 open_file = list_entry(tmp, struct cifsFileInfo, 1004 if (open_file) {
974 flist); 1005 __u16 nfid = open_file->netfid;
975 /* We check if file is open for writing first */ 1006 __u32 npid = open_file->pid;
976 if ((open_file->pfile) && 1007 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
977 ((open_file->pfile->f_flags & O_RDWR) || 1008 nfid, npid, FALSE);
978 (open_file->pfile->f_flags & O_WRONLY))) { 1009 atomic_dec(&open_file->wrtPending);
979 if (open_file->invalidHandle == FALSE) { 1010 cFYI(1,("SetFSize for attrs rc = %d", rc));
980 /* we found a valid, writeable network 1011 if(rc == -EINVAL) {
981 file handle to use to try to set the 1012 int bytes_written;
982 file size */ 1013 rc = CIFSSMBWrite(xid, pTcon,
983 __u16 nfid = open_file->netfid; 1014 nfid, 0, attrs->ia_size,
984 __u32 npid = open_file->pid; 1015 &bytes_written, NULL, NULL,
985 read_unlock(&GlobalSMBSeslock); 1016 1 /* 45 seconds */);
986 found = TRUE; 1017 cFYI(1,("Wrt seteof rc %d", rc));
987 rc = CIFSSMBSetFileSize(xid, pTcon,
988 attrs->ia_size, nfid, npid,
989 FALSE);
990 cFYI(1, ("SetFileSize by handle "
991 "(setattrs) rc = %d", rc));
992 /* Do not need reopen and retry on
993 EAGAIN since we will retry by
994 pathname below */
995
996 /* now that we found one valid file
997 handle no sense continuing to loop
998 trying others, so break here */
999 break;
1000 }
1001 } 1018 }
1002 } 1019 }
1003 if (found == FALSE)
1004 read_unlock(&GlobalSMBSeslock);
1005
1006 if (rc != 0) { 1020 if (rc != 0) {
1007 /* Set file size by pathname rather than by handle 1021 /* Set file size by pathname rather than by handle
1008 either because no valid, writeable file handle for 1022 either because no valid, writeable file handle for
@@ -1013,7 +1027,30 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1013 cifs_sb->local_nls, 1027 cifs_sb->local_nls,
1014 cifs_sb->mnt_cifs_flags & 1028 cifs_sb->mnt_cifs_flags &
1015 CIFS_MOUNT_MAP_SPECIAL_CHR); 1029 CIFS_MOUNT_MAP_SPECIAL_CHR);
1016 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); 1030 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1031 if(rc == -EINVAL) {
1032 __u16 netfid;
1033 int oplock = FALSE;
1034
1035 rc = SMBLegacyOpen(xid, pTcon, full_path,
1036 FILE_OPEN,
1037 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1038 CREATE_NOT_DIR, &netfid, &oplock,
1039 NULL, cifs_sb->local_nls,
1040 cifs_sb->mnt_cifs_flags &
1041 CIFS_MOUNT_MAP_SPECIAL_CHR);
1042 if (rc==0) {
1043 int bytes_written;
1044 rc = CIFSSMBWrite(xid, pTcon,
1045 netfid, 0,
1046 attrs->ia_size,
1047 &bytes_written, NULL,
1048 NULL, 1 /* 45 sec */);
1049 cFYI(1,("wrt seteof rc %d",rc));
1050 CIFSSMBClose(xid, pTcon, netfid);
1051 }
1052
1053 }
1017 } 1054 }
1018 1055
1019 /* Server is ok setting allocation size implicitly - no need 1056 /* Server is ok setting allocation size implicitly - no need
@@ -1026,24 +1063,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1026 rc = vmtruncate(direntry->d_inode, attrs->ia_size); 1063 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1027 cifs_truncate_page(direntry->d_inode->i_mapping, 1064 cifs_truncate_page(direntry->d_inode->i_mapping,
1028 direntry->d_inode->i_size); 1065 direntry->d_inode->i_size);
1029 } 1066 } else
1067 goto cifs_setattr_exit;
1030 } 1068 }
1031 if (attrs->ia_valid & ATTR_UID) { 1069 if (attrs->ia_valid & ATTR_UID) {
1032 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid)); 1070 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1033 uid = attrs->ia_uid; 1071 uid = attrs->ia_uid;
1034 /* entry->uid = cpu_to_le16(attr->ia_uid); */
1035 } 1072 }
1036 if (attrs->ia_valid & ATTR_GID) { 1073 if (attrs->ia_valid & ATTR_GID) {
1037 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid)); 1074 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1038 gid = attrs->ia_gid; 1075 gid = attrs->ia_gid;
1039 /* entry->gid = cpu_to_le16(attr->ia_gid); */
1040 } 1076 }
1041 1077
1042 time_buf.Attributes = 0; 1078 time_buf.Attributes = 0;
1043 if (attrs->ia_valid & ATTR_MODE) { 1079 if (attrs->ia_valid & ATTR_MODE) {
1044 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode)); 1080 cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1045 mode = attrs->ia_mode; 1081 mode = attrs->ia_mode;
1046 /* entry->mode = cpu_to_le16(attr->ia_mode); */
1047 } 1082 }
1048 1083
1049 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) 1084 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
@@ -1083,18 +1118,24 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1083 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); 1118 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1084 } else 1119 } else
1085 time_buf.LastWriteTime = 0; 1120 time_buf.LastWriteTime = 0;
1086 1121 /* Do not set ctime explicitly unless other time
1087 if (attrs->ia_valid & ATTR_CTIME) { 1122 stamps are changed explicitly (i.e. by utime()
1123 since we would then have a mix of client and
1124 server times */
1125
1126 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1088 set_time = TRUE; 1127 set_time = TRUE;
1089 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */ 1128 /* Although Samba throws this field away
1129 it may be useful to Windows - but we do
1130 not want to set ctime unless some other
1131 timestamp is changing */
1132 cFYI(1, ("CIFS - CTIME changed "));
1090 time_buf.ChangeTime = 1133 time_buf.ChangeTime =
1091 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1134 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1092 } else 1135 } else
1093 time_buf.ChangeTime = 0; 1136 time_buf.ChangeTime = 0;
1094 1137
1095 if (set_time || time_buf.Attributes) { 1138 if (set_time || time_buf.Attributes) {
1096 /* BB what if setting one attribute fails (such as size) but
1097 time setting works? */
1098 time_buf.CreationTime = 0; /* do not change */ 1139 time_buf.CreationTime = 0; /* do not change */
1099 /* In the future we should experiment - try setting timestamps 1140 /* In the future we should experiment - try setting timestamps
1100 via Handle (SetFileInfo) instead of by path */ 1141 via Handle (SetFileInfo) instead of by path */
@@ -1133,12 +1174,21 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1133 &time_buf, cifs_sb->local_nls); */ 1174 &time_buf, cifs_sb->local_nls); */
1134 } 1175 }
1135 } 1176 }
1177 /* Even if error on time set, no sense failing the call if
1178 the server would set the time to a reasonable value anyway,
1179 and this check ensures that we are not being called from
1180 sys_utimes in which case we ought to fail the call back to
1181 the user when the server rejects the call */
1182 if((rc) && (attrs->ia_valid &&
1183 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1184 rc = 0;
1136 } 1185 }
1137 1186
1138 /* do not need local check to inode_check_ok since the server does 1187 /* do not need local check to inode_check_ok since the server does
1139 that */ 1188 that */
1140 if (!rc) 1189 if (!rc)
1141 rc = inode_setattr(direntry->d_inode, attrs); 1190 rc = inode_setattr(direntry->d_inode, attrs);
1191cifs_setattr_exit:
1142 kfree(full_path); 1192 kfree(full_path);
1143 FreeXid(xid); 1193 FreeXid(xid);
1144 return rc; 1194 return rc;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index ab925ef4f863..b43e071fe110 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -198,7 +198,10 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
198 ("Create symlink worked but get_inode_info failed with rc = %d ", 198 ("Create symlink worked but get_inode_info failed with rc = %d ",
199 rc)); 199 rc));
200 } else { 200 } else {
201 direntry->d_op = &cifs_dentry_ops; 201 if (pTcon->nocase)
202 direntry->d_op = &cifs_ci_dentry_ops;
203 else
204 direntry->d_op = &cifs_dentry_ops;
202 d_instantiate(direntry, newinode); 205 d_instantiate(direntry, newinode);
203 } 206 }
204 } 207 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 20ae4153f791..eba1de917f2a 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -34,8 +34,6 @@ extern mempool_t *cifs_sm_req_poolp;
34extern mempool_t *cifs_req_poolp; 34extern mempool_t *cifs_req_poolp;
35extern struct task_struct * oplockThread; 35extern struct task_struct * oplockThread;
36 36
37static __u16 GlobalMid; /* multiplex id - rotating counter */
38
39/* The xid serves as a useful identifier for each incoming vfs request, 37/* The xid serves as a useful identifier for each incoming vfs request,
40 in a similar way to the mid which is useful to track each sent smb, 38 in a similar way to the mid which is useful to track each sent smb,
41 and CurrentXid can also provide a running counter (although it 39 and CurrentXid can also provide a running counter (although it
@@ -51,6 +49,8 @@ _GetXid(void)
51 GlobalTotalActiveXid++; 49 GlobalTotalActiveXid++;
52 if (GlobalTotalActiveXid > GlobalMaxActiveXid) 50 if (GlobalTotalActiveXid > GlobalMaxActiveXid)
53 GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */ 51 GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
52 if(GlobalTotalActiveXid > 65000)
53 cFYI(1,("warning: more than 65000 requests active"));
54 xid = GlobalCurrentXid++; 54 xid = GlobalCurrentXid++;
55 spin_unlock(&GlobalMid_Lock); 55 spin_unlock(&GlobalMid_Lock);
56 return xid; 56 return xid;
@@ -218,6 +218,76 @@ cifs_small_buf_release(void *buf_to_free)
218 return; 218 return;
219} 219}
220 220
221/*
222 Find a free multiplex id (SMB mid). Otherwise there could be
223 mid collisions which might cause problems, demultiplexing the
224 wrong response to this request. Multiplex ids could collide if
225 one of a series requests takes much longer than the others, or
226 if a very large number of long lived requests (byte range
227 locks or FindNotify requests) are pending. No more than
228 64K-1 requests can be outstanding at one time. If no
229 mids are available, return zero. A future optimization
230 could make the combination of mids and uid the key we use
231 to demultiplex on (rather than mid alone).
232 In addition to the above check, the cifs demultiplex
233 code already used the command code as a secondary
234 check of the frame and if signing is negotiated the
235 response would be discarded if the mid were the same
236 but the signature was wrong. Since the mid is not put in the
237 pending queue until later (when it is about to be dispatched)
238 we do have to limit the number of outstanding requests
239 to somewhat less than 64K-1 although it is hard to imagine
240 so many threads being in the vfs at one time.
241*/
242__u16 GetNextMid(struct TCP_Server_Info *server)
243{
244 __u16 mid = 0;
245 __u16 last_mid;
246 int collision;
247
248 if(server == NULL)
249 return mid;
250
251 spin_lock(&GlobalMid_Lock);
252 last_mid = server->CurrentMid; /* we do not want to loop forever */
253 server->CurrentMid++;
254 /* This nested loop looks more expensive than it is.
255 In practice the list of pending requests is short,
256 fewer than 50, and the mids are likely to be unique
257 on the first pass through the loop unless some request
258 takes longer than the 64 thousand requests before it
259 (and it would also have to have been a request that
260 did not time out) */
261 while(server->CurrentMid != last_mid) {
262 struct list_head *tmp;
263 struct mid_q_entry *mid_entry;
264
265 collision = 0;
266 if(server->CurrentMid == 0)
267 server->CurrentMid++;
268
269 list_for_each(tmp, &server->pending_mid_q) {
270 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
271
272 if ((mid_entry->mid == server->CurrentMid) &&
273 (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
274 /* This mid is in use, try a different one */
275 collision = 1;
276 break;
277 }
278 }
279 if(collision == 0) {
280 mid = server->CurrentMid;
281 break;
282 }
283 server->CurrentMid++;
284 }
285 spin_unlock(&GlobalMid_Lock);
286 return mid;
287}
288
289/* NB: MID can not be set if treeCon not passed in, in that
290 case it is responsbility of caller to set the mid */
221void 291void
222header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , 292header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
223 const struct cifsTconInfo *treeCon, int word_count 293 const struct cifsTconInfo *treeCon, int word_count
@@ -233,7 +303,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
233 (2 * word_count) + sizeof (struct smb_hdr) - 303 (2 * word_count) + sizeof (struct smb_hdr) -
234 4 /* RFC 1001 length field does not count */ + 304 4 /* RFC 1001 length field does not count */ +
235 2 /* for bcc field itself */ ; 305 2 /* for bcc field itself */ ;
236 /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */ 306 /* Note that this is the only network field that has to be converted
307 to big endian and it is done just before we send it */
237 308
238 buffer->Protocol[0] = 0xFF; 309 buffer->Protocol[0] = 0xFF;
239 buffer->Protocol[1] = 'S'; 310 buffer->Protocol[1] = 'S';
@@ -245,8 +316,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
245 buffer->Pid = cpu_to_le16((__u16)current->tgid); 316 buffer->Pid = cpu_to_le16((__u16)current->tgid);
246 buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); 317 buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
247 spin_lock(&GlobalMid_Lock); 318 spin_lock(&GlobalMid_Lock);
248 GlobalMid++;
249 buffer->Mid = GlobalMid;
250 spin_unlock(&GlobalMid_Lock); 319 spin_unlock(&GlobalMid_Lock);
251 if (treeCon) { 320 if (treeCon) {
252 buffer->Tid = treeCon->tid; 321 buffer->Tid = treeCon->tid;
@@ -256,8 +325,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
256 if (treeCon->ses->capabilities & CAP_STATUS32) { 325 if (treeCon->ses->capabilities & CAP_STATUS32) {
257 buffer->Flags2 |= SMBFLG2_ERR_STATUS; 326 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
258 } 327 }
259 328 /* Uid is not converted */
260 buffer->Uid = treeCon->ses->Suid; /* always in LE format */ 329 buffer->Uid = treeCon->ses->Suid;
330 buffer->Mid = GetNextMid(treeCon->ses->server);
261 if(multiuser_mount != 0) { 331 if(multiuser_mount != 0) {
262 /* For the multiuser case, there are few obvious technically */ 332 /* For the multiuser case, there are few obvious technically */
263 /* possible mechanisms to match the local linux user (uid) */ 333 /* possible mechanisms to match the local linux user (uid) */
@@ -305,6 +375,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
305 } 375 }
306 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) 376 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
307 buffer->Flags2 |= SMBFLG2_DFS; 377 buffer->Flags2 |= SMBFLG2_DFS;
378 if (treeCon->nocase)
379 buffer->Flags |= SMBFLG_CASELESS;
308 if((treeCon->ses) && (treeCon->ses->server)) 380 if((treeCon->ses) && (treeCon->ses->server))
309 if(treeCon->ses->server->secMode & 381 if(treeCon->ses->server->secMode &
310 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 382 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
@@ -347,7 +419,8 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
347int 419int
348checkSMB(struct smb_hdr *smb, __u16 mid, int length) 420checkSMB(struct smb_hdr *smb, __u16 mid, int length)
349{ 421{
350 __u32 len = be32_to_cpu(smb->smb_buf_length); 422 __u32 len = smb->smb_buf_length;
423 __u32 clc_len; /* calculated length */
351 cFYI(0, 424 cFYI(0,
352 ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 425 ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
353 length, len)); 426 length, len));
@@ -368,23 +441,29 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
368 cERROR(1, 441 cERROR(1,
369 ("smb_buf_length greater than MaxBufSize")); 442 ("smb_buf_length greater than MaxBufSize"));
370 cERROR(1, 443 cERROR(1,
371 ("bad smb detected. Illegal length. The mid=%d", 444 ("bad smb detected. Illegal length. mid=%d",
372 smb->Mid)); 445 smb->Mid));
373 return 1; 446 return 1;
374 } 447 }
375 448
376 if (checkSMBhdr(smb, mid)) 449 if (checkSMBhdr(smb, mid))
377 return 1; 450 return 1;
378 451 clc_len = smbCalcSize_LE(smb);
379 if ((4 + len != smbCalcSize(smb)) 452 if ((4 + len != clc_len)
380 || (4 + len != (unsigned int)length)) { 453 || (4 + len != (unsigned int)length)) {
381 return 0; 454 cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
382 } else { 455 clc_len, 4 + len));
383 cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); 456 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
384 cERROR(1, 457 /* Windows XP can return a few bytes too much, presumably
385 ("bad smb size detected. The Mid=%d", smb->Mid)); 458 an illegal pad, at the end of byte range lock responses
386 return 1; 459 so we allow for up to eight byte pad, as long as actual
460 received length is as long or longer than calculated length */
461 if((4+len > clc_len) && (len <= clc_len + 3))
462 return 0;
463 else
464 return 1;
387 } 465 }
466 return 0;
388} 467}
389int 468int
390is_valid_oplock_break(struct smb_hdr *buf) 469is_valid_oplock_break(struct smb_hdr *buf)
@@ -448,9 +527,7 @@ is_valid_oplock_break(struct smb_hdr *buf)
448 list_for_each(tmp, &GlobalTreeConnectionList) { 527 list_for_each(tmp, &GlobalTreeConnectionList) {
449 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 528 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
450 if (tcon->tid == buf->Tid) { 529 if (tcon->tid == buf->Tid) {
451#ifdef CONFIG_CIFS_STATS 530 cifs_stats_inc(&tcon->num_oplock_brks);
452 atomic_inc(&tcon->num_oplock_brks);
453#endif
454 list_for_each(tmp1,&tcon->openFileList){ 531 list_for_each(tmp1,&tcon->openFileList){
455 netfile = list_entry(tmp1,struct cifsFileInfo, 532 netfile = list_entry(tmp1,struct cifsFileInfo,
456 tlist); 533 tlist);
@@ -603,6 +680,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
603 int i,j,charlen; 680 int i,j,charlen;
604 int len_remaining = maxlen; 681 int len_remaining = maxlen;
605 char src_char; 682 char src_char;
683 __u16 temp;
606 684
607 if(!mapChars) 685 if(!mapChars)
608 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); 686 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
@@ -639,13 +717,14 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
639 break;*/ 717 break;*/
640 default: 718 default:
641 charlen = cp->char2uni(source+i, 719 charlen = cp->char2uni(source+i,
642 len_remaining, target+j); 720 len_remaining, &temp);
643 /* if no match, use question mark, which 721 /* if no match, use question mark, which
644 at least in some cases servers as wild card */ 722 at least in some cases servers as wild card */
645 if(charlen < 1) { 723 if(charlen < 1) {
646 target[j] = cpu_to_le16(0x003f); 724 target[j] = cpu_to_le16(0x003f);
647 charlen = 1; 725 charlen = 1;
648 } 726 } else
727 target[j] = cpu_to_le16(temp);
649 len_remaining -= charlen; 728 len_remaining -= charlen;
650 /* character may take more than one byte in the 729 /* character may take more than one byte in the
651 the source string, but will take exactly two 730 the source string, but will take exactly two
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index a92af41d4411..f7814689844b 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -133,7 +133,6 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
133int 133int
134cifs_inet_pton(int address_family, char *cp,void *dst) 134cifs_inet_pton(int address_family, char *cp,void *dst)
135{ 135{
136 struct in_addr address;
137 int value; 136 int value;
138 int digit; 137 int digit;
139 int i; 138 int i;
@@ -190,8 +189,7 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
190 if (value > addr_class_max[end - bytes]) 189 if (value > addr_class_max[end - bytes])
191 return 0; 190 return 0;
192 191
193 address.s_addr = *((__be32 *) bytes) | htonl(value); 192 *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
194 *((__be32 *)dst) = address.s_addr;
195 return 1; /* success */ 193 return 1; /* success */
196} 194}
197 195
@@ -815,7 +813,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
815 if (smb->Flags2 & SMBFLG2_ERR_STATUS) { 813 if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
816 /* translate the newer STATUS codes to old style errors and then to POSIX errors */ 814 /* translate the newer STATUS codes to old style errors and then to POSIX errors */
817 __u32 err = le32_to_cpu(smb->Status.CifsError); 815 __u32 err = le32_to_cpu(smb->Status.CifsError);
818 if(cifsFYI) 816 if(cifsFYI & CIFS_RC)
819 cifs_print_status(err); 817 cifs_print_status(err);
820 ntstatus_to_dos(err, &smberrclass, &smberrcode); 818 ntstatus_to_dos(err, &smberrclass, &smberrcode);
821 } else { 819 } else {
@@ -870,7 +868,14 @@ unsigned int
870smbCalcSize(struct smb_hdr *ptr) 868smbCalcSize(struct smb_hdr *ptr)
871{ 869{
872 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + 870 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
873 BCC(ptr)); 871 2 /* size of the bcc field */ + BCC(ptr));
872}
873
874unsigned int
875smbCalcSize_LE(struct smb_hdr *ptr)
876{
877 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
878 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
874} 879}
875 880
876/* The following are taken from fs/ntfs/util.c */ 881/* The following are taken from fs/ntfs/util.c */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 22557716f9af..a86bd1c07602 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -91,7 +91,10 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
91 } 91 }
92 92
93 *ptmp_inode = new_inode(file->f_dentry->d_sb); 93 *ptmp_inode = new_inode(file->f_dentry->d_sb);
94 tmp_dentry->d_op = &cifs_dentry_ops; 94 if (pTcon->nocase)
95 tmp_dentry->d_op = &cifs_ci_dentry_ops;
96 else
97 tmp_dentry->d_op = &cifs_dentry_ops;
95 if(*ptmp_inode == NULL) 98 if(*ptmp_inode == NULL)
96 return rc; 99 return rc;
97 rc = 1; 100 rc = 1;
@@ -148,6 +151,13 @@ static void fill_in_inode(struct inode *tmp_inode,
148 tmp_inode->i_mode = cifs_sb->mnt_dir_mode; 151 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
149 } 152 }
150 tmp_inode->i_mode |= S_IFDIR; 153 tmp_inode->i_mode |= S_IFDIR;
154 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
155 (attr & ATTR_SYSTEM) && (end_of_file == 0)) {
156 *pobject_type = DT_FIFO;
157 tmp_inode->i_mode |= S_IFIFO;
158/* BB Finish for SFU style symlinks and devies */
159/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
160 (attr & ATTR_SYSTEM) && ) { */
151/* we no longer mark these because we could not follow them */ 161/* we no longer mark these because we could not follow them */
152/* } else if (attr & ATTR_REPARSE) { 162/* } else if (attr & ATTR_REPARSE) {
153 *pobject_type = DT_LNK; 163 *pobject_type = DT_LNK;
@@ -187,11 +197,17 @@ static void fill_in_inode(struct inode *tmp_inode,
187 tmp_inode->i_fop = &cifs_file_direct_ops; 197 tmp_inode->i_fop = &cifs_file_direct_ops;
188 else 198 else
189 tmp_inode->i_fop = &cifs_file_ops; 199 tmp_inode->i_fop = &cifs_file_ops;
200 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
201 tmp_inode->i_fop->lock = NULL;
190 tmp_inode->i_data.a_ops = &cifs_addr_ops; 202 tmp_inode->i_data.a_ops = &cifs_addr_ops;
191 203 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
204 (cifs_sb->tcon->ses->server->maxBuf <
205 4096 + MAX_CIFS_HDR_SIZE))
206 tmp_inode->i_data.a_ops->readpages = NULL;
192 if(isNewInode) 207 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we 208 return; /* No sense invalidating pages for new inode
194 have not started caching readahead file data yet */ 209 since have not started caching readahead file
210 data yet */
195 211
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 212 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) { 213 (local_size == tmp_inode->i_size)) {
@@ -290,7 +306,13 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
290 tmp_inode->i_fop = &cifs_file_direct_ops; 306 tmp_inode->i_fop = &cifs_file_direct_ops;
291 else 307 else
292 tmp_inode->i_fop = &cifs_file_ops; 308 tmp_inode->i_fop = &cifs_file_ops;
309 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
310 tmp_inode->i_fop->lock = NULL;
293 tmp_inode->i_data.a_ops = &cifs_addr_ops; 311 tmp_inode->i_data.a_ops = &cifs_addr_ops;
312 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
313 (cifs_sb->tcon->ses->server->maxBuf <
314 4096 + MAX_CIFS_HDR_SIZE))
315 tmp_inode->i_data.a_ops->readpages = NULL;
294 316
295 if(isNewInode) 317 if(isNewInode)
296 return; /* No sense invalidating pages for new inode since we 318 return; /* No sense invalidating pages for new inode since we
@@ -374,7 +396,8 @@ ffirst_retry:
374 396
375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 397 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
376 &cifsFile->netfid, &cifsFile->srch_inf, 398 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 399 cifs_sb->mnt_cifs_flags &
400 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
378 if(rc == 0) 401 if(rc == 0)
379 cifsFile->invalidHandle = FALSE; 402 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) && 403 if((rc == -EOPNOTSUPP) &&
@@ -491,6 +514,30 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
491 return rc; 514 return rc;
492} 515}
493 516
517/* Check if directory that we are searching has changed so we can decide
518 whether we can use the cached search results from the previous search */
519static int is_dir_changed(struct file * file)
520{
521 struct inode * inode;
522 struct cifsInodeInfo *cifsInfo;
523
524 if(file->f_dentry == NULL)
525 return 0;
526
527 inode = file->f_dentry->d_inode;
528
529 if(inode == NULL)
530 return 0;
531
532 cifsInfo = CIFS_I(inode);
533
534 if(cifsInfo->time == 0)
535 return 1; /* directory was changed, perhaps due to unlink */
536 else
537 return 0;
538
539}
540
494/* find the corresponding entry in the search */ 541/* find the corresponding entry in the search */
495/* Note that the SMB server returns search entries for . and .. which 542/* Note that the SMB server returns search entries for . and .. which
496 complicates logic here if we choose to parse for them and we do not 543 complicates logic here if we choose to parse for them and we do not
@@ -507,7 +554,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
507 struct cifsFileInfo * cifsFile = file->private_data; 554 struct cifsFileInfo * cifsFile = file->private_data;
508 /* check if index in the buffer */ 555 /* check if index in the buffer */
509 556
510 if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL)) 557 if((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
558 (num_to_ret == NULL))
511 return -ENOENT; 559 return -ENOENT;
512 560
513 *ppCurrentEntry = NULL; 561 *ppCurrentEntry = NULL;
@@ -515,7 +563,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
515 cifsFile->srch_inf.index_of_last_entry - 563 cifsFile->srch_inf.index_of_last_entry -
516 cifsFile->srch_inf.entries_in_buffer; 564 cifsFile->srch_inf.entries_in_buffer;
517/* dump_cifs_file_struct(file, "In fce ");*/ 565/* dump_cifs_file_struct(file, "In fce ");*/
518 if(index_to_find < first_entry_in_buffer) { 566 if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
567 is_dir_changed(file)) ||
568 (index_to_find < first_entry_in_buffer)) {
519 /* close and restart search */ 569 /* close and restart search */
520 cFYI(1,("search backing up - close and restart search")); 570 cFYI(1,("search backing up - close and restart search"));
521 cifsFile->invalidHandle = TRUE; 571 cifsFile->invalidHandle = TRUE;
@@ -536,7 +586,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
536 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 586 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
537 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ 587 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
538 cFYI(1,("calling findnext2")); 588 cFYI(1,("calling findnext2"));
539 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); 589 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
590 &cifsFile->srch_inf);
540 if(rc) 591 if(rc)
541 return -ENOENT; 592 return -ENOENT;
542 } 593 }
@@ -548,14 +599,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
548 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 599 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
549 smbCalcSize((struct smb_hdr *) 600 smbCalcSize((struct smb_hdr *)
550 cifsFile->srch_inf.ntwrk_buf_start); 601 cifsFile->srch_inf.ntwrk_buf_start);
551/* dump_cifs_file_struct(file,"found entry in fce "); */
552 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry 602 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
553 - cifsFile->srch_inf.entries_in_buffer; 603 - cifsFile->srch_inf.entries_in_buffer;
554 pos_in_buf = index_to_find - first_entry_in_buffer; 604 pos_in_buf = index_to_find - first_entry_in_buffer;
555 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 605 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
556 current_entry = cifsFile->srch_inf.srch_entries_start; 606 current_entry = cifsFile->srch_inf.srch_entries_start;
557 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 607 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
558 /* go entry to next entry figuring out which we need to start with */ 608 /* go entry by entry figuring out which is first */
559 /* if( . or ..) 609 /* if( . or ..)
560 skip */ 610 skip */
561 rc = cifs_entry_is_dot(current_entry,cifsFile); 611 rc = cifs_entry_is_dot(current_entry,cifsFile);
@@ -582,11 +632,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
582 } 632 }
583 633
584 if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { 634 if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
585 cFYI(1,("can not return entries when pos_in_buf beyond last entry")); 635 cFYI(1,("can not return entries pos_in_buf beyond last entry"));
586 *num_to_ret = 0; 636 *num_to_ret = 0;
587 } else 637 } else
588 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; 638 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
589/* dump_cifs_file_struct(file, "end fce ");*/
590 639
591 return rc; 640 return rc;
592} 641}
@@ -721,7 +770,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 770 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
722 } 771 }
723 772
724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 773 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
774 tmp_inode->i_ino,obj_type);
725 if(rc) { 775 if(rc) {
726 cFYI(1,("filldir rc = %d",rc)); 776 cFYI(1,("filldir rc = %d",rc));
727 } 777 }
@@ -805,15 +855,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
805 FreeXid(xid); 855 FreeXid(xid);
806 return -EIO; 856 return -EIO;
807 } 857 }
808/* dump_cifs_file_struct(file, "Begin rdir "); */
809 858
810 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 859 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
811 pTcon = cifs_sb->tcon; 860 pTcon = cifs_sb->tcon;
812 if(pTcon == NULL) 861 if(pTcon == NULL)
813 return -EINVAL; 862 return -EINVAL;
814 863
815/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
816
817 switch ((int) file->f_pos) { 864 switch ((int) file->f_pos) {
818 case 0: 865 case 0:
819 /*if (filldir(direntry, ".", 1, file->f_pos, 866 /*if (filldir(direntry, ".", 1, file->f_pos,
@@ -866,7 +913,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
866 cifsFile->search_resume_name = NULL; */ 913 cifsFile->search_resume_name = NULL; */
867 914
868 /* BB account for . and .. in f_pos as special case */ 915 /* BB account for . and .. in f_pos as special case */
869 /* dump_cifs_file_struct(file, "rdir after default ");*/
870 916
871 rc = find_cifs_entry(xid,pTcon, file, 917 rc = find_cifs_entry(xid,pTcon, file,
872 &current_entry,&num_to_fill); 918 &current_entry,&num_to_fill);
@@ -906,14 +952,14 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
906 cifs_save_resume_key(current_entry,cifsFile); 952 cifs_save_resume_key(current_entry,cifsFile);
907 break; 953 break;
908 } else 954 } else
909 current_entry = nxt_dir_entry(current_entry,end_of_smb); 955 current_entry = nxt_dir_entry(current_entry,
956 end_of_smb);
910 } 957 }
911 kfree(tmp_buf); 958 kfree(tmp_buf);
912 break; 959 break;
913 } /* end switch */ 960 } /* end switch */
914 961
915rddir2_exit: 962rddir2_exit:
916 /* dump_cifs_file_struct(file, "end rdir "); */
917 FreeXid(xid); 963 FreeXid(xid);
918 return rc; 964 return rc;
919} 965}
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0046c219833d..981ea0d8b9cd 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
49 return NULL; 49 return NULL;
50 } 50 }
51 51
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS); 52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
53 SLAB_KERNEL | SLAB_NOFS);
53 if (temp == NULL) 54 if (temp == NULL)
54 return temp; 55 return temp;
55 else { 56 else {
@@ -58,7 +59,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
58 temp->pid = current->pid; 59 temp->pid = current->pid;
59 temp->command = smb_buffer->Command; 60 temp->command = smb_buffer->Command;
60 cFYI(1, ("For smb_command %d", temp->command)); 61 cFYI(1, ("For smb_command %d", temp->command));
61 do_gettimeofday(&temp->when_sent); 62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies;
62 temp->ses = ses; 65 temp->ses = ses;
63 temp->tsk = current; 66 temp->tsk = current;
64 } 67 }
@@ -74,6 +77,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
74static void 77static void
75DeleteMidQEntry(struct mid_q_entry *midEntry) 78DeleteMidQEntry(struct mid_q_entry *midEntry)
76{ 79{
80#ifdef CONFIG_CIFS_STATS2
81 unsigned long now;
82#endif
77 spin_lock(&GlobalMid_Lock); 83 spin_lock(&GlobalMid_Lock);
78 midEntry->midState = MID_FREE; 84 midEntry->midState = MID_FREE;
79 list_del(&midEntry->qhead); 85 list_del(&midEntry->qhead);
@@ -83,6 +89,22 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
83 cifs_buf_release(midEntry->resp_buf); 89 cifs_buf_release(midEntry->resp_buf);
84 else 90 else
85 cifs_small_buf_release(midEntry->resp_buf); 91 cifs_small_buf_release(midEntry->resp_buf);
92#ifdef CONFIG_CIFS_STATS2
93 now = jiffies;
94 /* commands taking longer than one second are indications that
95 something is wrong, unless it is quite a slow link or server */
96 if((now - midEntry->when_alloc) > HZ) {
97 if((cifsFYI & CIFS_TIMER) &&
98 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
99 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
100 midEntry->command, midEntry->mid);
101 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
102 now - midEntry->when_alloc,
103 now - midEntry->when_sent,
104 now - midEntry->when_received);
105 }
106 }
107#endif
86 mempool_free(midEntry, cifs_mid_poolp); 108 mempool_free(midEntry, cifs_mid_poolp);
87} 109}
88 110
@@ -146,32 +168,37 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
146 Flags2 is converted in SendReceive */ 168 Flags2 is converted in SendReceive */
147 169
148 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 170 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
149 cFYI(1, ("Sending smb of length %d ", smb_buf_length)); 171 cFYI(1, ("Sending smb of length %d", smb_buf_length));
150 dump_smb(smb_buffer, len); 172 dump_smb(smb_buffer, len);
151 173
152 while (len > 0) { 174 while (len > 0) {
153 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len); 175 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
154 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 176 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
155 i++; 177 i++;
156 if(i > 60) { 178 /* smaller timeout here than send2 since smaller size */
179 /* Although it may not be required, this also is smaller
180 oplock break time */
181 if(i > 12) {
157 cERROR(1, 182 cERROR(1,
158 ("sends on sock %p stuck for 30 seconds", 183 ("sends on sock %p stuck for 7 seconds",
159 ssocket)); 184 ssocket));
160 rc = -EAGAIN; 185 rc = -EAGAIN;
161 break; 186 break;
162 } 187 }
163 msleep(500); 188 msleep(1 << i);
164 continue; 189 continue;
165 } 190 }
166 if (rc < 0) 191 if (rc < 0)
167 break; 192 break;
193 else
194 i = 0; /* reset i after each successful send */
168 iov.iov_base += rc; 195 iov.iov_base += rc;
169 iov.iov_len -= rc; 196 iov.iov_len -= rc;
170 len -= rc; 197 len -= rc;
171 } 198 }
172 199
173 if (rc < 0) { 200 if (rc < 0) {
174 cERROR(1,("Error %d sending data on socket to server.", rc)); 201 cERROR(1,("Error %d sending data on socket to server", rc));
175 } else { 202 } else {
176 rc = 0; 203 rc = 0;
177 } 204 }
@@ -179,26 +206,21 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
179 return rc; 206 return rc;
180} 207}
181 208
182#ifdef CIFS_EXPERIMENTAL 209#ifdef CONFIG_CIFS_EXPERIMENTAL
183/* BB finish off this function, adding support for writing set of pages as iovec */ 210static int
184/* and also adding support for operations that need to parse the response smb */ 211smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
185 212 struct sockaddr *sin)
186int
187smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
188 unsigned int smb_buf_length, struct kvec * write_vector
189 /* page list */, struct sockaddr *sin)
190{ 213{
191 int rc = 0; 214 int rc = 0;
192 int i = 0; 215 int i = 0;
193 struct msghdr smb_msg; 216 struct msghdr smb_msg;
194 number_of_pages += 1; /* account for SMB header */ 217 struct smb_hdr *smb_buffer = iov[0].iov_base;
195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 218 unsigned int len = iov[0].iov_len;
196 unsigned len = smb_buf_length + 4; 219 unsigned int total_len;
197 220 int first_vec = 0;
221
198 if(ssocket == NULL) 222 if(ssocket == NULL)
199 return -ENOTSOCK; /* BB eventually add reconnect code here */ 223 return -ENOTSOCK; /* BB eventually add reconnect code here */
200 iov.iov_base = smb_buffer;
201 iov.iov_len = len;
202 224
203 smb_msg.msg_name = sin; 225 smb_msg.msg_name = sin;
204 smb_msg.msg_namelen = sizeof (struct sockaddr); 226 smb_msg.msg_namelen = sizeof (struct sockaddr);
@@ -211,49 +233,80 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
211 cifssmb.c and RFC1001 len is converted to bigendian in smb_send 233 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
212 Flags2 is converted in SendReceive */ 234 Flags2 is converted in SendReceive */
213 235
236
237 total_len = 0;
238 for (i = 0; i < n_vec; i++)
239 total_len += iov[i].iov_len;
240
214 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 241 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
215 cFYI(1, ("Sending smb of length %d ", smb_buf_length)); 242 cFYI(1, ("Sending smb: total_len %d", total_len));
216 dump_smb(smb_buffer, len); 243 dump_smb(smb_buffer, len);
217 244
218 while (len > 0) { 245 while (total_len) {
219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 246 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
220 len); 247 n_vec - first_vec, total_len);
221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 248 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
222 i++; 249 i++;
223 if(i > 60) { 250 if(i >= 14) {
224 cERROR(1, 251 cERROR(1,
225 ("sends on sock %p stuck for 30 seconds", 252 ("sends on sock %p stuck for 15 seconds",
226 ssocket)); 253 ssocket));
227 rc = -EAGAIN; 254 rc = -EAGAIN;
228 break; 255 break;
229 } 256 }
230 msleep(500); 257 msleep(1 << i);
231 continue; 258 continue;
232 } 259 }
233 if (rc < 0) 260 if (rc < 0)
234 break; 261 break;
235 iov.iov_base += rc; 262
236 iov.iov_len -= rc; 263 if (rc >= total_len) {
237 len -= rc; 264 WARN_ON(rc > total_len);
265 break;
266 }
267 if(rc == 0) {
268 /* should never happen, letting socket clear before
269 retrying is our only obvious option here */
270 cERROR(1,("tcp sent no data"));
271 msleep(500);
272 continue;
273 }
274 total_len -= rc;
275 /* the line below resets i */
276 for (i = first_vec; i < n_vec; i++) {
277 if (iov[i].iov_len) {
278 if (rc > iov[i].iov_len) {
279 rc -= iov[i].iov_len;
280 iov[i].iov_len = 0;
281 } else {
282 iov[i].iov_base += rc;
283 iov[i].iov_len -= rc;
284 first_vec = i;
285 break;
286 }
287 }
288 }
289 i = 0; /* in case we get ENOSPC on the next send */
238 } 290 }
239 291
240 if (rc < 0) { 292 if (rc < 0) {
241 cERROR(1,("Error %d sending data on socket to server.", rc)); 293 cERROR(1,("Error %d sending data on socket to server", rc));
242 } else { 294 } else
243 rc = 0; 295 rc = 0;
244 }
245 296
246 return rc; 297 return rc;
247} 298}
248 299
249
250int 300int
251CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, 301SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
252 struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op) 302 struct kvec *iov, int n_vec, int *pbytes_returned,
303 const int long_op)
253{ 304{
254 int rc = 0; 305 int rc = 0;
255 unsigned long timeout = 15 * HZ; 306 unsigned int receive_len;
256 struct mid_q_entry *midQ = NULL; 307 unsigned long timeout;
308 struct mid_q_entry *midQ;
309 struct smb_hdr *in_buf = iov[0].iov_base;
257 310
258 if (ses == NULL) { 311 if (ses == NULL) {
259 cERROR(1,("Null smb session")); 312 cERROR(1,("Null smb session"));
@@ -263,14 +316,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
263 cERROR(1,("Null tcp session")); 316 cERROR(1,("Null tcp session"));
264 return -EIO; 317 return -EIO;
265 } 318 }
266 if(pbytes_returned == NULL)
267 return -EIO;
268 else
269 *pbytes_returned = 0;
270 319
271 320 if(ses->server->tcpStatus == CifsExiting)
272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT; 321 return -ENOENT;
275 322
276 /* Ensure that we do not send more than 50 overlapping requests 323 /* Ensure that we do not send more than 50 overlapping requests
@@ -282,11 +329,18 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
282 } else { 329 } else {
283 spin_lock(&GlobalMid_Lock); 330 spin_lock(&GlobalMid_Lock);
284 while(1) { 331 while(1) {
285 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 332 if(atomic_read(&ses->server->inFlight) >=
333 cifs_max_pending){
286 spin_unlock(&GlobalMid_Lock); 334 spin_unlock(&GlobalMid_Lock);
335#ifdef CONFIG_CIFS_STATS2
336 atomic_inc(&ses->server->num_waiters);
337#endif
287 wait_event(ses->server->request_q, 338 wait_event(ses->server->request_q,
288 atomic_read(&ses->server->inFlight) 339 atomic_read(&ses->server->inFlight)
289 < cifs_max_pending); 340 < cifs_max_pending);
341#ifdef CONFIG_CIFS_STATS2
342 atomic_dec(&ses->server->num_waiters);
343#endif
290 spin_lock(&GlobalMid_Lock); 344 spin_lock(&GlobalMid_Lock);
291 } else { 345 } else {
292 if(ses->server->tcpStatus == CifsExiting) { 346 if(ses->server->tcpStatus == CifsExiting) {
@@ -314,17 +368,17 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
314 368
315 if (ses->server->tcpStatus == CifsExiting) { 369 if (ses->server->tcpStatus == CifsExiting) {
316 rc = -ENOENT; 370 rc = -ENOENT;
317 goto cifs_out_label; 371 goto out_unlock2;
318 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 372 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
319 cFYI(1,("tcp session dead - return to caller to retry")); 373 cFYI(1,("tcp session dead - return to caller to retry"));
320 rc = -EAGAIN; 374 rc = -EAGAIN;
321 goto cifs_out_label; 375 goto out_unlock2;
322 } else if (ses->status != CifsGood) { 376 } else if (ses->status != CifsGood) {
323 /* check if SMB session is bad because we are setting it up */ 377 /* check if SMB session is bad because we are setting it up */
324 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 378 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
325 (in_buf->Command != SMB_COM_NEGOTIATE)) { 379 (in_buf->Command != SMB_COM_NEGOTIATE)) {
326 rc = -EAGAIN; 380 rc = -EAGAIN;
327 goto cifs_out_label; 381 goto out_unlock2;
328 } /* else ok - we are setting up session */ 382 } /* else ok - we are setting up session */
329 } 383 }
330 midQ = AllocMidQEntry(in_buf, ses); 384 midQ = AllocMidQEntry(in_buf, ses);
@@ -338,51 +392,162 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
338 return -ENOMEM; 392 return -ENOMEM;
339 } 393 }
340 394
341 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 395/* BB FIXME */
342 up(&ses->server->tcpSem); 396/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
343 cERROR(1, 397
344 ("Illegal length, greater than maximum frame, %d ", 398 midQ->midState = MID_REQUEST_SUBMITTED;
345 in_buf->smb_buf_length)); 399#ifdef CONFIG_CIFS_STATS2
400 atomic_inc(&ses->server->inSend);
401#endif
402 rc = smb_send2(ses->server->ssocket, iov, n_vec,
403 (struct sockaddr *) &(ses->server->addr.sockAddr));
404#ifdef CONFIG_CIFS_STATS2
405 atomic_dec(&ses->server->inSend);
406 midQ->when_sent = jiffies;
407#endif
408 if(rc < 0) {
346 DeleteMidQEntry(midQ); 409 DeleteMidQEntry(midQ);
410 up(&ses->server->tcpSem);
347 /* If not lock req, update # of requests on wire to server */ 411 /* If not lock req, update # of requests on wire to server */
348 if(long_op < 3) { 412 if(long_op < 3) {
349 atomic_dec(&ses->server->inFlight); 413 atomic_dec(&ses->server->inFlight);
350 wake_up(&ses->server->request_q); 414 wake_up(&ses->server->request_q);
351 } 415 }
352 return -EIO; 416 return rc;
417 } else
418 up(&ses->server->tcpSem);
419 if (long_op == -1)
420 goto cifs_no_response_exit2;
421 else if (long_op == 2) /* writes past end of file can take loong time */
422 timeout = 180 * HZ;
423 else if (long_op == 1)
424 timeout = 45 * HZ; /* should be greater than
425 servers oplock break timeout (about 43 seconds) */
426 else if (long_op > 2) {
427 timeout = MAX_SCHEDULE_TIMEOUT;
428 } else
429 timeout = 15 * HZ;
430 /* wait for 15 seconds or until woken up due to response arriving or
431 due to last connection to this server being unmounted */
432 if (signal_pending(current)) {
433 /* if signal pending do not hold up user for full smb timeout
434 but we still give response a change to complete */
435 timeout = 2 * HZ;
436 }
437
438 /* No user interrupts in wait - wreaks havoc with performance */
439 if(timeout != MAX_SCHEDULE_TIMEOUT) {
440 timeout += jiffies;
441 wait_event(ses->server->response_q,
442 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
443 time_after(jiffies, timeout) ||
444 ((ses->server->tcpStatus != CifsGood) &&
445 (ses->server->tcpStatus != CifsNew)));
446 } else {
447 wait_event(ses->server->response_q,
448 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
449 ((ses->server->tcpStatus != CifsGood) &&
450 (ses->server->tcpStatus != CifsNew)));
353 } 451 }
354 452
355 /* BB can we sign efficiently in this path? */ 453 spin_lock(&GlobalMid_Lock);
356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 454 if (midQ->resp_buf) {
455 spin_unlock(&GlobalMid_Lock);
456 receive_len = midQ->resp_buf->smb_buf_length;
457 } else {
458 cERROR(1,("No response to cmd %d mid %d",
459 midQ->command, midQ->mid));
460 if(midQ->midState == MID_REQUEST_SUBMITTED) {
461 if(ses->server->tcpStatus == CifsExiting)
462 rc = -EHOSTDOWN;
463 else {
464 ses->server->tcpStatus = CifsNeedReconnect;
465 midQ->midState = MID_RETRY_NEEDED;
466 }
467 }
357 468
358 midQ->midState = MID_REQUEST_SUBMITTED; 469 if (rc != -EHOSTDOWN) {
359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 470 if(midQ->midState == MID_RETRY_NEEDED) {
360 piovec, 471 rc = -EAGAIN;
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/ 472 cFYI(1,("marking request for retry"));
362 if(rc < 0) { 473 } else {
474 rc = -EIO;
475 }
476 }
477 spin_unlock(&GlobalMid_Lock);
363 DeleteMidQEntry(midQ); 478 DeleteMidQEntry(midQ);
364 up(&ses->server->tcpSem);
365 /* If not lock req, update # of requests on wire to server */ 479 /* If not lock req, update # of requests on wire to server */
366 if(long_op < 3) { 480 if(long_op < 3) {
367 atomic_dec(&ses->server->inFlight); 481 atomic_dec(&ses->server->inFlight);
368 wake_up(&ses->server->request_q); 482 wake_up(&ses->server->request_q);
369 } 483 }
370 return rc; 484 return rc;
371 } else 485 }
372 up(&ses->server->tcpSem); 486
373cifs_out_label: 487 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
374 if(midQ) 488 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
375 DeleteMidQEntry(midQ); 489 receive_len, xid));
376 490 rc = -EIO;
491 } else { /* rcvd frame is ok */
492
493 if (midQ->resp_buf &&
494 (midQ->midState == MID_RESPONSE_RECEIVED)) {
495 in_buf->smb_buf_length = receive_len;
496 /* BB verify that length would not overrun small buf */
497 memcpy((char *)in_buf + 4,
498 (char *)midQ->resp_buf + 4,
499 receive_len);
500
501 dump_smb(in_buf, 80);
502 /* convert the length into a more usable form */
503 if((receive_len > 24) &&
504 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
505 SECMODE_SIGN_ENABLED))) {
506 rc = cifs_verify_signature(in_buf,
507 ses->server->mac_signing_key,
508 midQ->sequence_number+1);
509 if(rc) {
510 cERROR(1,("Unexpected SMB signature"));
511 /* BB FIXME add code to kill session */
512 }
513 }
514
515 *pbytes_returned = in_buf->smb_buf_length;
516
517 /* BB special case reconnect tid and uid here? */
518 rc = map_smb_to_linux_error(in_buf);
519
520 /* convert ByteCount if necessary */
521 if (receive_len >=
522 sizeof (struct smb_hdr) -
523 4 /* do not count RFC1001 header */ +
524 (2 * in_buf->WordCount) + 2 /* bcc */ )
525 BCC(in_buf) = le16_to_cpu(BCC(in_buf));
526 } else {
527 rc = -EIO;
528 cFYI(1,("Bad MID state?"));
529 }
530 }
531cifs_no_response_exit2:
532 DeleteMidQEntry(midQ);
533
377 if(long_op < 3) { 534 if(long_op < 3) {
378 atomic_dec(&ses->server->inFlight); 535 atomic_dec(&ses->server->inFlight);
379 wake_up(&ses->server->request_q); 536 wake_up(&ses->server->request_q);
380 } 537 }
381 538
382 return rc; 539 return rc;
383}
384 540
541out_unlock2:
542 up(&ses->server->tcpSem);
543 /* If not lock req, update # of requests on wire to server */
544 if(long_op < 3) {
545 atomic_dec(&ses->server->inFlight);
546 wake_up(&ses->server->request_q);
547 }
385 548
549 return rc;
550}
386#endif /* CIFS_EXPERIMENTAL */ 551#endif /* CIFS_EXPERIMENTAL */
387 552
388int 553int
@@ -419,9 +584,15 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
419 if(atomic_read(&ses->server->inFlight) >= 584 if(atomic_read(&ses->server->inFlight) >=
420 cifs_max_pending){ 585 cifs_max_pending){
421 spin_unlock(&GlobalMid_Lock); 586 spin_unlock(&GlobalMid_Lock);
587#ifdef CONFIG_CIFS_STATS2
588 atomic_inc(&ses->server->num_waiters);
589#endif
422 wait_event(ses->server->request_q, 590 wait_event(ses->server->request_q,
423 atomic_read(&ses->server->inFlight) 591 atomic_read(&ses->server->inFlight)
424 < cifs_max_pending); 592 < cifs_max_pending);
593#ifdef CONFIG_CIFS_STATS2
594 atomic_dec(&ses->server->num_waiters);
595#endif
425 spin_lock(&GlobalMid_Lock); 596 spin_lock(&GlobalMid_Lock);
426 } else { 597 } else {
427 if(ses->server->tcpStatus == CifsExiting) { 598 if(ses->server->tcpStatus == CifsExiting) {
@@ -490,8 +661,15 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
490 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 661 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
491 662
492 midQ->midState = MID_REQUEST_SUBMITTED; 663 midQ->midState = MID_REQUEST_SUBMITTED;
664#ifdef CONFIG_CIFS_STATS2
665 atomic_inc(&ses->server->inSend);
666#endif
493 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 667 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
494 (struct sockaddr *) &(ses->server->addr.sockAddr)); 668 (struct sockaddr *) &(ses->server->addr.sockAddr));
669#ifdef CONFIG_CIFS_STATS2
670 atomic_dec(&ses->server->inSend);
671 midQ->when_sent = jiffies;
672#endif
495 if(rc < 0) { 673 if(rc < 0) {
496 DeleteMidQEntry(midQ); 674 DeleteMidQEntry(midQ);
497 up(&ses->server->tcpSem); 675 up(&ses->server->tcpSem);
@@ -506,7 +684,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
506 if (long_op == -1) 684 if (long_op == -1)
507 goto cifs_no_response_exit; 685 goto cifs_no_response_exit;
508 else if (long_op == 2) /* writes past end of file can take loong time */ 686 else if (long_op == 2) /* writes past end of file can take loong time */
509 timeout = 300 * HZ; 687 timeout = 180 * HZ;
510 else if (long_op == 1) 688 else if (long_op == 1)
511 timeout = 45 * HZ; /* should be greater than 689 timeout = 45 * HZ; /* should be greater than
512 servers oplock break timeout (about 43 seconds) */ 690 servers oplock break timeout (about 43 seconds) */
@@ -540,9 +718,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
540 spin_lock(&GlobalMid_Lock); 718 spin_lock(&GlobalMid_Lock);
541 if (midQ->resp_buf) { 719 if (midQ->resp_buf) {
542 spin_unlock(&GlobalMid_Lock); 720 spin_unlock(&GlobalMid_Lock);
543 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf); 721 receive_len = midQ->resp_buf->smb_buf_length;
544 } else { 722 } else {
545 cERROR(1,("No response buffer")); 723 cERROR(1,("No response for cmd %d mid %d",
724 midQ->command, midQ->mid));
546 if(midQ->midState == MID_REQUEST_SUBMITTED) { 725 if(midQ->midState == MID_REQUEST_SUBMITTED) {
547 if(ses->server->tcpStatus == CifsExiting) 726 if(ses->server->tcpStatus == CifsExiting)
548 rc = -EHOSTDOWN; 727 rc = -EHOSTDOWN;
@@ -610,7 +789,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
610 BCC(out_buf) = le16_to_cpu(BCC(out_buf)); 789 BCC(out_buf) = le16_to_cpu(BCC(out_buf));
611 } else { 790 } else {
612 rc = -EIO; 791 rc = -EIO;
613 cFYI(1,("Bad MID state? ")); 792 cERROR(1,("Bad MID state? "));
614 } 793 }
615 } 794 }
616cifs_no_response_exit: 795cifs_no_response_exit: