aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-11-02 00:28:53 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-02 00:28:53 -0500
commitfca324e79fa30d4e64ac15554601a86392999ae6 (patch)
treec55ecac090b2ad245fd94d993c99ef00a1e10a89
parent1d373741976985bc665e75aeb2b3bf7a524e36cc (diff)
parent7f28570185f98bfa83f775756ced79e9f22b6d93 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
-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.h499
-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/ntlmssp.h12
-rw-r--r--fs/cifs/readdir.c84
-rw-r--r--fs/cifs/rfc1002pdu.h13
-rw-r--r--fs/cifs/transport.c331
-rw-r--r--mm/swap.c3
27 files changed, 2442 insertions, 722 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..48a05b9df7eb 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
@@ -76,7 +80,7 @@
76#define NT_TRANSACT_GET_USER_QUOTA 0x07 80#define NT_TRANSACT_GET_USER_QUOTA 0x07
77#define NT_TRANSACT_SET_USER_QUOTA 0x08 81#define NT_TRANSACT_SET_USER_QUOTA 0x08
78 82
79#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */ 83#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */
80 84
81/* internal cifs vfs structures */ 85/* internal cifs vfs structures */
82/***************************************************************** 86/*****************************************************************
@@ -129,10 +133,11 @@
129/* 133/*
130 * SMB flag definitions 134 * SMB flag definitions
131 */ 135 */
132#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */ 136#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
133#define SMBFLG_RCV_POSTED 0x02 /* obsolete */ 137#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
134#define SMBFLG_RSVD 0x04 138#define SMBFLG_RSVD 0x04
135#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */ 139#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off
140 implies case sensitive file handling request) */
136#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */ 141#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
137#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */ 142#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
138#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */ 143#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
@@ -141,7 +146,8 @@
141/* 146/*
142 * SMB flag2 definitions 147 * SMB flag2 definitions
143 */ 148 */
144#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) path names in response */ 149#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
150 path names in response */
145#define SMBFLG2_KNOWS_EAS cpu_to_le16(2) 151#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
146#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4) 152#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
147#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40) 153#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
@@ -160,32 +166,32 @@
160 * file and can have any suitable combination of the following values: 166 * file and can have any suitable combination of the following values:
161 */ 167 */
162 168
163#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */ 169#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
164#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */ 170#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
165#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */ 171#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
166#define FILE_READ_EA 0x00000008 /* Extended attributes associated */ 172#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
167 /* with the file can be read */ 173 /* with the file can be read */
168#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */ 174#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
169 /* with the file can be written */ 175 /* with the file can be written */
170#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */ 176#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
171 /* the file using system paging I/O */ 177 /* the file using system paging I/O */
172#define FILE_DELETE_CHILD 0x00000040 178#define FILE_DELETE_CHILD 0x00000040
173#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */ 179#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
174 /* file can be read */ 180 /* file can be read */
175#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */ 181#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
176 /* file can be written */ 182 /* file can be written */
177#define DELETE 0x00010000 /* The file can be deleted */ 183#define DELETE 0x00010000 /* The file can be deleted */
178#define READ_CONTROL 0x00020000 /* The access control list and */ 184#define READ_CONTROL 0x00020000 /* The access control list and */
179 /* ownership associated with the */ 185 /* ownership associated with the */
180 /* file can be read */ 186 /* file can be read */
181#define WRITE_DAC 0x00040000 /* The access control list and */ 187#define WRITE_DAC 0x00040000 /* The access control list and */
182 /* ownership associated with the */ 188 /* ownership associated with the */
183 /* file can be written. */ 189 /* file can be written. */
184#define WRITE_OWNER 0x00080000 /* Ownership information associated */ 190#define WRITE_OWNER 0x00080000 /* Ownership information associated */
185 /* with the file can be written */ 191 /* with the file can be written */
186#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */ 192#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
187 /* synchronize with the completion */ 193 /* synchronize with the completion */
188 /* of an input/output request */ 194 /* of an input/output request */
189#define GENERIC_ALL 0x10000000 195#define GENERIC_ALL 0x10000000
190#define GENERIC_EXECUTE 0x20000000 196#define GENERIC_EXECUTE 0x20000000
191#define GENERIC_WRITE 0x40000000 197#define GENERIC_WRITE 0x40000000
@@ -193,7 +199,7 @@
193 /* In summary - Relevant file */ 199 /* In summary - Relevant file */
194 /* access flags from CIFS are */ 200 /* access flags from CIFS are */
195 /* file_read_data, file_write_data */ 201 /* file_read_data, file_write_data */
196 /* file_execute, file_read_attributes */ 202 /* file_execute, file_read_attributes*/
197 /* write_dac, and delete. */ 203 /* write_dac, and delete. */
198 204
199/* 205/*
@@ -238,7 +244,8 @@
238#define ATTR_SPARSE 0x0200 244#define ATTR_SPARSE 0x0200
239#define ATTR_REPARSE 0x0400 245#define ATTR_REPARSE 0x0400
240#define ATTR_COMPRESSED 0x0800 246#define ATTR_COMPRESSED 0x0800
241#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */ 247#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
248 on offline storage */
242#define ATTR_NOT_CONTENT_INDEXED 0x2000 249#define ATTR_NOT_CONTENT_INDEXED 0x2000
243#define ATTR_ENCRYPTED 0x4000 250#define ATTR_ENCRYPTED 0x4000
244#define ATTR_POSIX_SEMANTICS 0x01000000 251#define ATTR_POSIX_SEMANTICS 0x01000000
@@ -267,10 +274,18 @@
267/* CreateOptions */ 274/* CreateOptions */
268#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ 275#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
269#define CREATE_WRITE_THROUGH 0x00000002 276#define CREATE_WRITE_THROUGH 0x00000002
270#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ 277#define CREATE_SEQUENTIAL 0x00000004
278#define CREATE_SYNC_ALERT 0x00000010
279#define CREATE_ASYNC_ALERT 0x00000020
280#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
281#define CREATE_NO_EA_KNOWLEDGE 0x00000200
282#define CREATE_EIGHT_DOT_THREE 0x00000400
271#define CREATE_RANDOM_ACCESS 0x00000800 283#define CREATE_RANDOM_ACCESS 0x00000800
272#define CREATE_DELETE_ON_CLOSE 0x00001000 284#define CREATE_DELETE_ON_CLOSE 0x00001000
285#define CREATE_OPEN_BY_ID 0x00002000
273#define OPEN_REPARSE_POINT 0x00200000 286#define OPEN_REPARSE_POINT 0x00200000
287#define CREATE_OPTIONS_MASK 0x007FFFFF
288#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
274 289
275/* ImpersonationLevel flags */ 290/* ImpersonationLevel flags */
276#define SECURITY_ANONYMOUS 0 291#define SECURITY_ANONYMOUS 0
@@ -297,10 +312,10 @@
297#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */ 312#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
298#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ 313#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
299 314
300#pragma pack(1)
301
302struct smb_hdr { 315struct smb_hdr {
303 __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */ 316 __u32 smb_buf_length; /* big endian on wire *//* BB length is only two
317 or three bytes - with one or two byte type preceding it that are
318 zero - we could mask the type byte off just in case BB */
304 __u8 Protocol[4]; 319 __u8 Protocol[4];
305 __u8 Command; 320 __u8 Command;
306 union { 321 union {
@@ -308,9 +323,9 @@ struct smb_hdr {
308 __u8 ErrorClass; 323 __u8 ErrorClass;
309 __u8 Reserved; 324 __u8 Reserved;
310 __le16 Error; 325 __le16 Error;
311 } DosError; 326 } __attribute__((packed)) DosError;
312 __le32 CifsError; 327 __le32 CifsError;
313 } Status; 328 } __attribute__((packed)) Status;
314 __u8 Flags; 329 __u8 Flags;
315 __le16 Flags2; /* note: le */ 330 __le16 Flags2; /* note: le */
316 __le16 PidHigh; 331 __le16 PidHigh;
@@ -318,16 +333,16 @@ struct smb_hdr {
318 struct { 333 struct {
319 __le32 SequenceNumber; /* le */ 334 __le32 SequenceNumber; /* le */
320 __u32 Reserved; /* zero */ 335 __u32 Reserved; /* zero */
321 } Sequence; 336 } __attribute__((packed)) Sequence;
322 __u8 SecuritySignature[8]; /* le */ 337 __u8 SecuritySignature[8]; /* le */
323 } Signature; 338 } __attribute__((packed)) Signature;
324 __u8 pad[2]; 339 __u8 pad[2];
325 __u16 Tid; 340 __u16 Tid;
326 __le16 Pid; 341 __le16 Pid;
327 __u16 Uid; 342 __u16 Uid;
328 __u16 Mid; 343 __u16 Mid;
329 __u8 WordCount; 344 __u8 WordCount;
330}; 345} __attribute__((packed));
331/* given a pointer to an smb_hdr retrieve the value of byte count */ 346/* given a pointer to an smb_hdr retrieve the value of byte count */
332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 347#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
333#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 348#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
@@ -379,7 +394,7 @@ typedef struct negotiate_req {
379 struct smb_hdr hdr; /* wct = 0 */ 394 struct smb_hdr hdr; /* wct = 0 */
380 __le16 ByteCount; 395 __le16 ByteCount;
381 unsigned char DialectsArray[1]; 396 unsigned char DialectsArray[1];
382} NEGOTIATE_REQ; 397} __attribute__((packed)) NEGOTIATE_REQ;
383 398
384typedef struct negotiate_rsp { 399typedef struct negotiate_rsp {
385 struct smb_hdr hdr; /* wct = 17 */ 400 struct smb_hdr hdr; /* wct = 17 */
@@ -397,16 +412,16 @@ typedef struct negotiate_rsp {
397 __u8 EncryptionKeyLength; 412 __u8 EncryptionKeyLength;
398 __u16 ByteCount; 413 __u16 ByteCount;
399 union { 414 union {
400 unsigned char EncryptionKey[1]; /* if cap extended security is off */ 415 unsigned char EncryptionKey[1]; /* cap extended security off */
401 /* followed by Domain name - if extended security is off */ 416 /* followed by Domain name - if extended security is off */
402 /* followed by 16 bytes of server GUID */ 417 /* followed by 16 bytes of server GUID */
403 /* followed by security blob if cap_extended_security negotiated */ 418 /* then security blob if cap_extended_security negotiated */
404 struct { 419 struct {
405 unsigned char GUID[16]; 420 unsigned char GUID[16];
406 unsigned char SecurityBlob[1]; 421 unsigned char SecurityBlob[1];
407 } extended_response; 422 } __attribute__((packed)) extended_response;
408 } u; 423 } __attribute__((packed)) u;
409} NEGOTIATE_RSP; 424} __attribute__((packed)) NEGOTIATE_RSP;
410 425
411/* SecurityMode bits */ 426/* SecurityMode bits */
412#define SECMODE_USER 0x01 /* off indicates share level security */ 427#define SECMODE_USER 0x01 /* off indicates share level security */
@@ -452,7 +467,8 @@ typedef union smb_com_session_setup_andx {
452 unsigned char SecurityBlob[1]; /* followed by */ 467 unsigned char SecurityBlob[1]; /* followed by */
453 /* STRING NativeOS */ 468 /* STRING NativeOS */
454 /* STRING NativeLanMan */ 469 /* STRING NativeLanMan */
455 } req; /* NTLM request format (with extended security */ 470 } __attribute__((packed)) req; /* NTLM request format (with
471 extended security */
456 472
457 struct { /* request format */ 473 struct { /* request format */
458 struct smb_hdr hdr; /* wct = 13 */ 474 struct smb_hdr hdr; /* wct = 13 */
@@ -463,18 +479,19 @@ typedef union smb_com_session_setup_andx {
463 __le16 MaxMpxCount; 479 __le16 MaxMpxCount;
464 __le16 VcNumber; 480 __le16 VcNumber;
465 __u32 SessionKey; 481 __u32 SessionKey;
466 __le16 CaseInsensitivePasswordLength; /* ASCII password length */ 482 __le16 CaseInsensitivePasswordLength; /* ASCII password len */
467 __le16 CaseSensitivePasswordLength; /* Unicode password length */ 483 __le16 CaseSensitivePasswordLength; /* Unicode password length*/
468 __u32 Reserved; /* see below */ 484 __u32 Reserved; /* see below */
469 __le32 Capabilities; 485 __le32 Capabilities;
470 __le16 ByteCount; 486 __le16 ByteCount;
471 unsigned char CaseInsensitivePassword[1]; /* followed by: */ 487 unsigned char CaseInsensitivePassword[1]; /* followed by: */
472 /* unsigned char * CaseSensitivePassword; */ 488 /* unsigned char * CaseSensitivePassword; */
473 /* STRING AccountName */ 489 /* STRING AccountName */
474 /* STRING PrimaryDomain */ 490 /* STRING PrimaryDomain */
475 /* STRING NativeOS */ 491 /* STRING NativeOS */
476 /* STRING NativeLanMan */ 492 /* STRING NativeLanMan */
477 } req_no_secext; /* NTLM request format (without extended security */ 493 } __attribute__((packed)) req_no_secext; /* NTLM request format (without
494 extended security */
478 495
479 struct { /* default (NTLM) response format */ 496 struct { /* default (NTLM) response format */
480 struct smb_hdr hdr; /* wct = 4 */ 497 struct smb_hdr hdr; /* wct = 4 */
@@ -488,7 +505,7 @@ typedef union smb_com_session_setup_andx {
488/* unsigned char * NativeOS; */ 505/* unsigned char * NativeOS; */
489/* unsigned char * NativeLanMan; */ 506/* unsigned char * NativeLanMan; */
490/* unsigned char * PrimaryDomain; */ 507/* unsigned char * PrimaryDomain; */
491 } resp; /* NTLM response format (with or without extended security */ 508 } __attribute__((packed)) resp; /* NTLM response format (with or without extended security */
492 509
493 struct { /* request format */ 510 struct { /* request format */
494 struct smb_hdr hdr; /* wct = 10 */ 511 struct smb_hdr hdr; /* wct = 10 */
@@ -507,7 +524,7 @@ typedef union smb_com_session_setup_andx {
507 /* STRING PrimaryDomain */ 524 /* STRING PrimaryDomain */
508 /* STRING NativeOS */ 525 /* STRING NativeOS */
509 /* STRING NativeLanMan */ 526 /* STRING NativeLanMan */
510 } old_req; /* pre-NTLM (LANMAN2.1) request format */ 527 } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */
511 528
512 struct { /* default (NTLM) response format */ 529 struct { /* default (NTLM) response format */
513 struct smb_hdr hdr; /* wct = 3 */ 530 struct smb_hdr hdr; /* wct = 3 */
@@ -519,8 +536,8 @@ typedef union smb_com_session_setup_andx {
519 unsigned char NativeOS[1]; /* followed by */ 536 unsigned char NativeOS[1]; /* followed by */
520/* unsigned char * NativeLanMan; */ 537/* unsigned char * NativeLanMan; */
521/* unsigned char * PrimaryDomain; */ 538/* unsigned char * PrimaryDomain; */
522 } old_resp; /* pre-NTLM (LANMAN2.1) response format */ 539 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */
523} SESSION_SETUP_ANDX; 540} __attribute__((packed)) SESSION_SETUP_ANDX;
524 541
525#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" 542#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
526 543
@@ -530,7 +547,8 @@ typedef union smb_com_session_setup_andx {
530#define CAP_NT_SMBS 0x00000010 547#define CAP_NT_SMBS 0x00000010
531#define CAP_STATUS32 0x00000040 548#define CAP_STATUS32 0x00000040
532#define CAP_LEVEL_II_OPLOCKS 0x00000080 549#define CAP_LEVEL_II_OPLOCKS 0x00000080
533#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */ 550#define CAP_NT_FIND 0x00000200 /* reserved should be zero
551 (because NT_SMBs implies the same thing?) */
534#define CAP_BULK_TRANSFER 0x20000000 552#define CAP_BULK_TRANSFER 0x20000000
535#define CAP_EXTENDED_SECURITY 0x80000000 553#define CAP_EXTENDED_SECURITY 0x80000000
536 554
@@ -548,7 +566,7 @@ typedef struct smb_com_tconx_req {
548 unsigned char Password[1]; /* followed by */ 566 unsigned char Password[1]; /* followed by */
549/* STRING Path *//* \\server\share name */ 567/* STRING Path *//* \\server\share name */
550 /* STRING Service */ 568 /* STRING Service */
551} TCONX_REQ; 569} __attribute__((packed)) TCONX_REQ;
552 570
553typedef struct smb_com_tconx_rsp { 571typedef struct smb_com_tconx_rsp {
554 struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */ 572 struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
@@ -559,13 +577,14 @@ typedef struct smb_com_tconx_rsp {
559 __u16 ByteCount; 577 __u16 ByteCount;
560 unsigned char Service[1]; /* always ASCII, not Unicode */ 578 unsigned char Service[1]; /* always ASCII, not Unicode */
561 /* STRING NativeFileSystem */ 579 /* STRING NativeFileSystem */
562} TCONX_RSP; 580} __attribute__((packed)) TCONX_RSP;
563 581
564/* tree connect Flags */ 582/* tree connect Flags */
565#define DISCONNECT_TID 0x0001 583#define DISCONNECT_TID 0x0001
566#define TCON_EXTENDED_SECINFO 0x0008 584#define TCON_EXTENDED_SECINFO 0x0008
567/* OptionalSupport bits */ 585/* OptionalSupport bits */
568#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */ 586#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
587 (exclusive searches supported) */
569#define SMB_SHARE_IS_IN_DFS 0x0002 588#define SMB_SHARE_IS_IN_DFS 0x0002
570 589
571typedef struct smb_com_logoff_andx_req { 590typedef struct smb_com_logoff_andx_req {
@@ -574,7 +593,7 @@ typedef struct smb_com_logoff_andx_req {
574 __u8 AndXReserved; 593 __u8 AndXReserved;
575 __u16 AndXOffset; 594 __u16 AndXOffset;
576 __u16 ByteCount; 595 __u16 ByteCount;
577} LOGOFF_ANDX_REQ; 596} __attribute__((packed)) LOGOFF_ANDX_REQ;
578 597
579typedef struct smb_com_logoff_andx_rsp { 598typedef struct smb_com_logoff_andx_rsp {
580 struct smb_hdr hdr; /* wct = 2 */ 599 struct smb_hdr hdr; /* wct = 2 */
@@ -582,38 +601,39 @@ typedef struct smb_com_logoff_andx_rsp {
582 __u8 AndXReserved; 601 __u8 AndXReserved;
583 __u16 AndXOffset; 602 __u16 AndXOffset;
584 __u16 ByteCount; 603 __u16 ByteCount;
585} LOGOFF_ANDX_RSP; 604} __attribute__((packed)) LOGOFF_ANDX_RSP;
586 605
587typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */ 606typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
588 struct { 607 struct {
589 struct smb_hdr hdr; /* wct = 0 */ 608 struct smb_hdr hdr; /* wct = 0 */
590 __u16 ByteCount; /* bcc = 0 */ 609 __u16 ByteCount; /* bcc = 0 */
591 } req; 610 } __attribute__((packed)) req;
592 struct { 611 struct {
593 struct smb_hdr hdr; /* wct = 0 */ 612 struct smb_hdr hdr; /* wct = 0 */
594 __u16 ByteCount; /* bcc = 0 */ 613 __u16 ByteCount; /* bcc = 0 */
595 } resp; 614 } __attribute__((packed)) resp;
596} TREE_DISCONNECT; 615} __attribute__((packed)) TREE_DISCONNECT;
597 616
598typedef struct smb_com_close_req { 617typedef struct smb_com_close_req {
599 struct smb_hdr hdr; /* wct = 3 */ 618 struct smb_hdr hdr; /* wct = 3 */
600 __u16 FileID; 619 __u16 FileID;
601 __u32 LastWriteTime; /* should be zero */ 620 __u32 LastWriteTime; /* should be zero */
602 __u16 ByteCount; /* 0 */ 621 __u16 ByteCount; /* 0 */
603} CLOSE_REQ; 622} __attribute__((packed)) CLOSE_REQ;
604 623
605typedef struct smb_com_close_rsp { 624typedef struct smb_com_close_rsp {
606 struct smb_hdr hdr; /* wct = 0 */ 625 struct smb_hdr hdr; /* wct = 0 */
607 __u16 ByteCount; /* bct = 0 */ 626 __u16 ByteCount; /* bct = 0 */
608} CLOSE_RSP; 627} __attribute__((packed)) CLOSE_RSP;
609 628
610typedef struct smb_com_findclose_req { 629typedef struct smb_com_findclose_req {
611 struct smb_hdr hdr; /* wct = 1 */ 630 struct smb_hdr hdr; /* wct = 1 */
612 __u16 FileID; 631 __u16 FileID;
613 __u16 ByteCount; /* 0 */ 632 __u16 ByteCount; /* 0 */
614} FINDCLOSE_REQ; 633} __attribute__((packed)) FINDCLOSE_REQ;
615 634
616/* OpenFlags */ 635/* OpenFlags */
636#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
617#define REQ_OPLOCK 0x00000002 637#define REQ_OPLOCK 0x00000002
618#define REQ_BATCHOPLOCK 0x00000004 638#define REQ_BATCHOPLOCK 0x00000004
619#define REQ_OPENDIRONLY 0x00000008 639#define REQ_OPENDIRONLY 0x00000008
@@ -637,7 +657,7 @@ typedef struct smb_com_open_req { /* also handles create */
637 __u8 SecurityFlags; 657 __u8 SecurityFlags;
638 __le16 ByteCount; 658 __le16 ByteCount;
639 char fileName[1]; 659 char fileName[1];
640} OPEN_REQ; 660} __attribute__((packed)) OPEN_REQ;
641 661
642/* open response: oplock levels */ 662/* open response: oplock levels */
643#define OPLOCK_NONE 0 663#define OPLOCK_NONE 0
@@ -667,7 +687,63 @@ typedef struct smb_com_open_rsp {
667 __le16 DeviceState; 687 __le16 DeviceState;
668 __u8 DirectoryFlag; 688 __u8 DirectoryFlag;
669 __u16 ByteCount; /* bct = 0 */ 689 __u16 ByteCount; /* bct = 0 */
670} OPEN_RSP; 690} __attribute__((packed)) OPEN_RSP;
691
692/* format of legacy open request */
693typedef struct smb_com_openx_req {
694 struct smb_hdr hdr; /* wct = 15 */
695 __u8 AndXCommand;
696 __u8 AndXReserved;
697 __le16 AndXOffset;
698 __le16 OpenFlags;
699 __le16 Mode;
700 __le16 Sattr; /* search attributes */
701 __le16 FileAttributes; /* dos attrs */
702 __le32 CreateTime; /* os2 format */
703 __le16 OpenFunction;
704 __le32 EndOfFile;
705 __le32 Timeout;
706 __le32 Reserved;
707 __le16 ByteCount; /* file name follows */
708 char fileName[1];
709} __attribute__((packed)) OPENX_REQ;
710
711typedef struct smb_com_openx_rsp {
712 struct smb_hdr hdr; /* wct = 15 */
713 __u8 AndXCommand;
714 __u8 AndXReserved;
715 __le16 AndXOffset;
716 __u16 Fid;
717 __le16 FileAttributes;
718 __le32 LastWriteTime; /* os2 format */
719 __le32 EndOfFile;
720 __le16 Access;
721 __le16 FileType;
722 __le16 IPCState;
723 __le16 Action;
724 __u32 FileId;
725 __u16 Reserved;
726 __u16 ByteCount;
727} __attribute__((packed)) OPENX_RSP;
728
729/* Legacy write request for older servers */
730typedef struct smb_com_writex_req {
731 struct smb_hdr hdr; /* wct = 12 */
732 __u8 AndXCommand;
733 __u8 AndXReserved;
734 __le16 AndXOffset;
735 __u16 Fid;
736 __le32 OffsetLow;
737 __u32 Reserved; /* Timeout */
738 __le16 WriteMode; /* 1 = write through */
739 __le16 Remaining;
740 __le16 Reserved2;
741 __le16 DataLengthLow;
742 __le16 DataOffset;
743 __le16 ByteCount;
744 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
745 char Data[0];
746} __attribute__((packed)) WRITEX_REQ;
671 747
672typedef struct smb_com_write_req { 748typedef struct smb_com_write_req {
673 struct smb_hdr hdr; /* wct = 14 */ 749 struct smb_hdr hdr; /* wct = 14 */
@@ -686,7 +762,7 @@ typedef struct smb_com_write_req {
686 __le16 ByteCount; 762 __le16 ByteCount;
687 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ 763 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
688 char Data[0]; 764 char Data[0];
689} WRITE_REQ; 765} __attribute__((packed)) WRITE_REQ;
690 766
691typedef struct smb_com_write_rsp { 767typedef struct smb_com_write_rsp {
692 struct smb_hdr hdr; /* wct = 6 */ 768 struct smb_hdr hdr; /* wct = 6 */
@@ -698,7 +774,22 @@ typedef struct smb_com_write_rsp {
698 __le16 CountHigh; 774 __le16 CountHigh;
699 __u16 Reserved; 775 __u16 Reserved;
700 __u16 ByteCount; 776 __u16 ByteCount;
701} WRITE_RSP; 777} __attribute__((packed)) WRITE_RSP;
778
779/* legacy read request for older servers */
780typedef struct smb_com_readx_req {
781 struct smb_hdr hdr; /* wct = 10 */
782 __u8 AndXCommand;
783 __u8 AndXReserved;
784 __le16 AndXOffset;
785 __u16 Fid;
786 __le32 OffsetLow;
787 __le16 MaxCount;
788 __le16 MinCount; /* obsolete */
789 __le32 Reserved;
790 __le16 Remaining;
791 __le16 ByteCount;
792} __attribute__((packed)) READX_REQ;
702 793
703typedef struct smb_com_read_req { 794typedef struct smb_com_read_req {
704 struct smb_hdr hdr; /* wct = 12 */ 795 struct smb_hdr hdr; /* wct = 12 */
@@ -713,7 +804,7 @@ typedef struct smb_com_read_req {
713 __le16 Remaining; 804 __le16 Remaining;
714 __le32 OffsetHigh; 805 __le32 OffsetHigh;
715 __le16 ByteCount; 806 __le16 ByteCount;
716} READ_REQ; 807} __attribute__((packed)) READ_REQ;
717 808
718typedef struct smb_com_read_rsp { 809typedef struct smb_com_read_rsp {
719 struct smb_hdr hdr; /* wct = 12 */ 810 struct smb_hdr hdr; /* wct = 12 */
@@ -730,7 +821,7 @@ typedef struct smb_com_read_rsp {
730 __u16 ByteCount; 821 __u16 ByteCount;
731 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ 822 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
732 char Data[1]; 823 char Data[1];
733} READ_RSP; 824} __attribute__((packed)) READ_RSP;
734 825
735typedef struct locking_andx_range { 826typedef struct locking_andx_range {
736 __le16 Pid; 827 __le16 Pid;
@@ -739,7 +830,7 @@ typedef struct locking_andx_range {
739 __le32 OffsetLow; 830 __le32 OffsetLow;
740 __le32 LengthHigh; 831 __le32 LengthHigh;
741 __le32 LengthLow; 832 __le32 LengthLow;
742} LOCKING_ANDX_RANGE; 833} __attribute__((packed)) LOCKING_ANDX_RANGE;
743 834
744#define LOCKING_ANDX_SHARED_LOCK 0x01 835#define LOCKING_ANDX_SHARED_LOCK 0x01
745#define LOCKING_ANDX_OPLOCK_RELEASE 0x02 836#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
@@ -760,7 +851,7 @@ typedef struct smb_com_lock_req {
760 __le16 NumberOfLocks; 851 __le16 NumberOfLocks;
761 __le16 ByteCount; 852 __le16 ByteCount;
762 LOCKING_ANDX_RANGE Locks[1]; 853 LOCKING_ANDX_RANGE Locks[1];
763} LOCK_REQ; 854} __attribute__((packed)) LOCK_REQ;
764 855
765 856
766typedef struct cifs_posix_lock { 857typedef struct cifs_posix_lock {
@@ -770,7 +861,7 @@ typedef struct cifs_posix_lock {
770 __le64 start; 861 __le64 start;
771 __le64 length; 862 __le64 length;
772 /* BB what about additional owner info to identify network client */ 863 /* BB what about additional owner info to identify network client */
773} CIFS_POSIX_LOCK; 864} __attribute__((packed)) CIFS_POSIX_LOCK;
774 865
775typedef struct smb_com_lock_rsp { 866typedef struct smb_com_lock_rsp {
776 struct smb_hdr hdr; /* wct = 2 */ 867 struct smb_hdr hdr; /* wct = 2 */
@@ -778,7 +869,7 @@ typedef struct smb_com_lock_rsp {
778 __u8 AndXReserved; 869 __u8 AndXReserved;
779 __le16 AndXOffset; 870 __le16 AndXOffset;
780 __u16 ByteCount; 871 __u16 ByteCount;
781} LOCK_RSP; 872} __attribute__((packed)) LOCK_RSP;
782 873
783typedef struct smb_com_rename_req { 874typedef struct smb_com_rename_req {
784 struct smb_hdr hdr; /* wct = 1 */ 875 struct smb_hdr hdr; /* wct = 1 */
@@ -788,7 +879,7 @@ typedef struct smb_com_rename_req {
788 unsigned char OldFileName[1]; 879 unsigned char OldFileName[1];
789 /* followed by __u8 BufferFormat2 */ 880 /* followed by __u8 BufferFormat2 */
790 /* followed by NewFileName */ 881 /* followed by NewFileName */
791} RENAME_REQ; 882} __attribute__((packed)) RENAME_REQ;
792 883
793 /* copy request flags */ 884 /* copy request flags */
794#define COPY_MUST_BE_FILE 0x0001 885#define COPY_MUST_BE_FILE 0x0001
@@ -808,7 +899,7 @@ typedef struct smb_com_copy_req {
808 unsigned char OldFileName[1]; 899 unsigned char OldFileName[1];
809 /* followed by __u8 BufferFormat2 */ 900 /* followed by __u8 BufferFormat2 */
810 /* followed by NewFileName string */ 901 /* followed by NewFileName string */
811} COPY_REQ; 902} __attribute__((packed)) COPY_REQ;
812 903
813typedef struct smb_com_copy_rsp { 904typedef struct smb_com_copy_rsp {
814 struct smb_hdr hdr; /* wct = 1 */ 905 struct smb_hdr hdr; /* wct = 1 */
@@ -816,7 +907,7 @@ typedef struct smb_com_copy_rsp {
816 __u16 ByteCount; /* may be zero */ 907 __u16 ByteCount; /* may be zero */
817 __u8 BufferFormat; /* 0x04 - only present if errored file follows */ 908 __u8 BufferFormat; /* 0x04 - only present if errored file follows */
818 unsigned char ErrorFileName[1]; /* only present if error in copy */ 909 unsigned char ErrorFileName[1]; /* only present if error in copy */
819} COPY_RSP; 910} __attribute__((packed)) COPY_RSP;
820 911
821#define CREATE_HARD_LINK 0x103 912#define CREATE_HARD_LINK 0x103
822#define MOVEFILE_COPY_ALLOWED 0x0002 913#define MOVEFILE_COPY_ALLOWED 0x0002
@@ -832,12 +923,12 @@ typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
832 unsigned char OldFileName[1]; 923 unsigned char OldFileName[1];
833 /* followed by __u8 BufferFormat2 */ 924 /* followed by __u8 BufferFormat2 */
834 /* followed by NewFileName */ 925 /* followed by NewFileName */
835} NT_RENAME_REQ; 926} __attribute__((packed)) NT_RENAME_REQ;
836 927
837typedef struct smb_com_rename_rsp { 928typedef struct smb_com_rename_rsp {
838 struct smb_hdr hdr; /* wct = 0 */ 929 struct smb_hdr hdr; /* wct = 0 */
839 __u16 ByteCount; /* bct = 0 */ 930 __u16 ByteCount; /* bct = 0 */
840} RENAME_RSP; 931} __attribute__((packed)) RENAME_RSP;
841 932
842typedef struct smb_com_delete_file_req { 933typedef struct smb_com_delete_file_req {
843 struct smb_hdr hdr; /* wct = 1 */ 934 struct smb_hdr hdr; /* wct = 1 */
@@ -845,36 +936,52 @@ typedef struct smb_com_delete_file_req {
845 __le16 ByteCount; 936 __le16 ByteCount;
846 __u8 BufferFormat; /* 4 = ASCII */ 937 __u8 BufferFormat; /* 4 = ASCII */
847 unsigned char fileName[1]; 938 unsigned char fileName[1];
848} DELETE_FILE_REQ; 939} __attribute__((packed)) DELETE_FILE_REQ;
849 940
850typedef struct smb_com_delete_file_rsp { 941typedef struct smb_com_delete_file_rsp {
851 struct smb_hdr hdr; /* wct = 0 */ 942 struct smb_hdr hdr; /* wct = 0 */
852 __u16 ByteCount; /* bct = 0 */ 943 __u16 ByteCount; /* bct = 0 */
853} DELETE_FILE_RSP; 944} __attribute__((packed)) DELETE_FILE_RSP;
854 945
855typedef struct smb_com_delete_directory_req { 946typedef struct smb_com_delete_directory_req {
856 struct smb_hdr hdr; /* wct = 0 */ 947 struct smb_hdr hdr; /* wct = 0 */
857 __le16 ByteCount; 948 __le16 ByteCount;
858 __u8 BufferFormat; /* 4 = ASCII */ 949 __u8 BufferFormat; /* 4 = ASCII */
859 unsigned char DirName[1]; 950 unsigned char DirName[1];
860} DELETE_DIRECTORY_REQ; 951} __attribute__((packed)) DELETE_DIRECTORY_REQ;
861 952
862typedef struct smb_com_delete_directory_rsp { 953typedef struct smb_com_delete_directory_rsp {
863 struct smb_hdr hdr; /* wct = 0 */ 954 struct smb_hdr hdr; /* wct = 0 */
864 __u16 ByteCount; /* bct = 0 */ 955 __u16 ByteCount; /* bct = 0 */
865} DELETE_DIRECTORY_RSP; 956} __attribute__((packed)) DELETE_DIRECTORY_RSP;
866 957
867typedef struct smb_com_create_directory_req { 958typedef struct smb_com_create_directory_req {
868 struct smb_hdr hdr; /* wct = 0 */ 959 struct smb_hdr hdr; /* wct = 0 */
869 __le16 ByteCount; 960 __le16 ByteCount;
870 __u8 BufferFormat; /* 4 = ASCII */ 961 __u8 BufferFormat; /* 4 = ASCII */
871 unsigned char DirName[1]; 962 unsigned char DirName[1];
872} CREATE_DIRECTORY_REQ; 963} __attribute__((packed)) CREATE_DIRECTORY_REQ;
873 964
874typedef struct smb_com_create_directory_rsp { 965typedef struct smb_com_create_directory_rsp {
875 struct smb_hdr hdr; /* wct = 0 */ 966 struct smb_hdr hdr; /* wct = 0 */
876 __u16 ByteCount; /* bct = 0 */ 967 __u16 ByteCount; /* bct = 0 */
877} CREATE_DIRECTORY_RSP; 968} __attribute__((packed)) CREATE_DIRECTORY_RSP;
969
970typedef struct smb_com_query_information_req {
971 struct smb_hdr hdr; /* wct = 0 */
972 __le16 ByteCount; /* 1 + namelen + 1 */
973 __u8 BufferFormat; /* 4 = ASCII */
974 unsigned char FileName[1];
975} __attribute__((packed)) QUERY_INFORMATION_REQ;
976
977typedef struct smb_com_query_information_rsp {
978 struct smb_hdr hdr; /* wct = 10 */
979 __le16 attr;
980 __le32 last_write_time;
981 __le32 size;
982 __u16 reserved[5];
983 __le16 ByteCount; /* bcc = 0 */
984} __attribute__((packed)) QUERY_INFORMATION_RSP;
878 985
879typedef struct smb_com_setattr_req { 986typedef struct smb_com_setattr_req {
880 struct smb_hdr hdr; /* wct = 8 */ 987 struct smb_hdr hdr; /* wct = 8 */
@@ -885,12 +992,12 @@ typedef struct smb_com_setattr_req {
885 __u16 ByteCount; 992 __u16 ByteCount;
886 __u8 BufferFormat; /* 4 = ASCII */ 993 __u8 BufferFormat; /* 4 = ASCII */
887 unsigned char fileName[1]; 994 unsigned char fileName[1];
888} SETATTR_REQ; 995} __attribute__((packed)) SETATTR_REQ;
889 996
890typedef struct smb_com_setattr_rsp { 997typedef struct smb_com_setattr_rsp {
891 struct smb_hdr hdr; /* wct = 0 */ 998 struct smb_hdr hdr; /* wct = 0 */
892 __u16 ByteCount; /* bct = 0 */ 999 __u16 ByteCount; /* bct = 0 */
893} SETATTR_RSP; 1000} __attribute__((packed)) SETATTR_RSP;
894 1001
895/* empty wct response to setattr */ 1002/* empty wct response to setattr */
896 1003
@@ -920,7 +1027,7 @@ typedef struct smb_com_transaction_ioctl_req {
920 __le16 ByteCount; 1027 __le16 ByteCount;
921 __u8 Pad[3]; 1028 __u8 Pad[3];
922 __u8 Data[1]; 1029 __u8 Data[1];
923} TRANSACT_IOCTL_REQ; 1030} __attribute__((packed)) TRANSACT_IOCTL_REQ;
924 1031
925typedef struct smb_com_transaction_ioctl_rsp { 1032typedef struct smb_com_transaction_ioctl_rsp {
926 struct smb_hdr hdr; /* wct = 19 */ 1033 struct smb_hdr hdr; /* wct = 19 */
@@ -937,7 +1044,7 @@ typedef struct smb_com_transaction_ioctl_rsp {
937 __le16 ReturnedDataLen; 1044 __le16 ReturnedDataLen;
938 __u16 ByteCount; 1045 __u16 ByteCount;
939 __u8 Pad[3]; 1046 __u8 Pad[3];
940} TRANSACT_IOCTL_RSP; 1047} __attribute__((packed)) TRANSACT_IOCTL_RSP;
941 1048
942typedef struct smb_com_transaction_change_notify_req { 1049typedef struct smb_com_transaction_change_notify_req {
943 struct smb_hdr hdr; /* wct = 23 */ 1050 struct smb_hdr hdr; /* wct = 23 */
@@ -961,7 +1068,7 @@ typedef struct smb_com_transaction_change_notify_req {
961 __le16 ByteCount; 1068 __le16 ByteCount;
962/* __u8 Pad[3];*/ 1069/* __u8 Pad[3];*/
963/* __u8 Data[1];*/ 1070/* __u8 Data[1];*/
964} TRANSACT_CHANGE_NOTIFY_REQ; 1071} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
965 1072
966typedef struct smb_com_transaction_change_notify_rsp { 1073typedef struct smb_com_transaction_change_notify_rsp {
967 struct smb_hdr hdr; /* wct = 18 */ 1074 struct smb_hdr hdr; /* wct = 18 */
@@ -977,7 +1084,7 @@ typedef struct smb_com_transaction_change_notify_rsp {
977 __u8 SetupCount; /* 0 */ 1084 __u8 SetupCount; /* 0 */
978 __u16 ByteCount; 1085 __u16 ByteCount;
979 /* __u8 Pad[3]; */ 1086 /* __u8 Pad[3]; */
980} TRANSACT_CHANGE_NOTIFY_RSP; 1087} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_RSP;
981/* Completion Filter flags for Notify */ 1088/* Completion Filter flags for Notify */
982#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 1089#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
983#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 1090#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
@@ -1008,7 +1115,7 @@ struct file_notify_information {
1008 __le32 Action; 1115 __le32 Action;
1009 __le32 FileNameLength; 1116 __le32 FileNameLength;
1010 __u8 FileName[0]; 1117 __u8 FileName[0];
1011}; 1118} __attribute__((packed));
1012 1119
1013struct reparse_data { 1120struct reparse_data {
1014 __u32 ReparseTag; 1121 __u32 ReparseTag;
@@ -1019,7 +1126,7 @@ struct reparse_data {
1019 __u16 TargetNameOffset; 1126 __u16 TargetNameOffset;
1020 __u16 TargetNameLen; 1127 __u16 TargetNameLen;
1021 char LinkNamesBuf[1]; 1128 char LinkNamesBuf[1];
1022}; 1129} __attribute__((packed));
1023 1130
1024struct cifs_quota_data { 1131struct cifs_quota_data {
1025 __u32 rsrvd1; /* 0 */ 1132 __u32 rsrvd1; /* 0 */
@@ -1029,7 +1136,7 @@ struct cifs_quota_data {
1029 __u64 soft_limit; 1136 __u64 soft_limit;
1030 __u64 hard_limit; 1137 __u64 hard_limit;
1031 char sid[1]; /* variable size? */ 1138 char sid[1]; /* variable size? */
1032}; 1139} __attribute__((packed));
1033 1140
1034/* quota sub commands */ 1141/* quota sub commands */
1035#define QUOTA_LIST_CONTINUE 0 1142#define QUOTA_LIST_CONTINUE 0
@@ -1055,12 +1162,12 @@ struct trans2_req {
1055 __u8 Reserved3; 1162 __u8 Reserved3;
1056 __le16 SubCommand; /* 1st setup word - SetupCount words follow */ 1163 __le16 SubCommand; /* 1st setup word - SetupCount words follow */
1057 __le16 ByteCount; 1164 __le16 ByteCount;
1058}; 1165} __attribute__((packed));
1059 1166
1060struct smb_t2_req { 1167struct smb_t2_req {
1061 struct smb_hdr hdr; 1168 struct smb_hdr hdr;
1062 struct trans2_req t2_req; 1169 struct trans2_req t2_req;
1063}; 1170} __attribute__((packed));
1064 1171
1065struct trans2_resp { 1172struct trans2_resp {
1066 /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */ 1173 /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
@@ -1079,12 +1186,12 @@ struct trans2_resp {
1079 __u16 ByteCount; 1186 __u16 ByteCount;
1080 __u16 Reserved2;*/ 1187 __u16 Reserved2;*/
1081 /* data area follows */ 1188 /* data area follows */
1082}; 1189} __attribute__((packed));
1083 1190
1084struct smb_t2_rsp { 1191struct smb_t2_rsp {
1085 struct smb_hdr hdr; 1192 struct smb_hdr hdr;
1086 struct trans2_resp t2_rsp; 1193 struct trans2_resp t2_rsp;
1087}; 1194} __attribute__((packed));
1088 1195
1089/* PathInfo/FileInfo infolevels */ 1196/* PathInfo/FileInfo infolevels */
1090#define SMB_INFO_STANDARD 1 1197#define SMB_INFO_STANDARD 1
@@ -1171,14 +1278,14 @@ typedef struct smb_com_transaction2_qpi_req {
1171 __le16 InformationLevel; 1278 __le16 InformationLevel;
1172 __u32 Reserved4; 1279 __u32 Reserved4;
1173 char FileName[1]; 1280 char FileName[1];
1174} TRANSACTION2_QPI_REQ; 1281} __attribute__((packed)) TRANSACTION2_QPI_REQ;
1175 1282
1176typedef struct smb_com_transaction2_qpi_rsp { 1283typedef struct smb_com_transaction2_qpi_rsp {
1177 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1284 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1178 struct trans2_resp t2; 1285 struct trans2_resp t2;
1179 __u16 ByteCount; 1286 __u16 ByteCount;
1180 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1287 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
1181} TRANSACTION2_QPI_RSP; 1288} __attribute__((packed)) TRANSACTION2_QPI_RSP;
1182 1289
1183typedef struct smb_com_transaction2_spi_req { 1290typedef struct smb_com_transaction2_spi_req {
1184 struct smb_hdr hdr; /* wct = 15 */ 1291 struct smb_hdr hdr; /* wct = 15 */
@@ -1204,21 +1311,21 @@ typedef struct smb_com_transaction2_spi_req {
1204 __le16 InformationLevel; 1311 __le16 InformationLevel;
1205 __u32 Reserved4; 1312 __u32 Reserved4;
1206 char FileName[1]; 1313 char FileName[1];
1207} TRANSACTION2_SPI_REQ; 1314} __attribute__((packed)) TRANSACTION2_SPI_REQ;
1208 1315
1209typedef struct smb_com_transaction2_spi_rsp { 1316typedef struct smb_com_transaction2_spi_rsp {
1210 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1317 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1211 struct trans2_resp t2; 1318 struct trans2_resp t2;
1212 __u16 ByteCount; 1319 __u16 ByteCount;
1213 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1320 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
1214} TRANSACTION2_SPI_RSP; 1321} __attribute__((packed)) TRANSACTION2_SPI_RSP;
1215 1322
1216struct set_file_rename { 1323struct set_file_rename {
1217 __le32 overwrite; /* 1 = overwrite dest */ 1324 __le32 overwrite; /* 1 = overwrite dest */
1218 __u32 root_fid; /* zero */ 1325 __u32 root_fid; /* zero */
1219 __le32 target_name_len; 1326 __le32 target_name_len;
1220 char target_name[0]; /* Must be unicode */ 1327 char target_name[0]; /* Must be unicode */
1221}; 1328} __attribute__((packed));
1222 1329
1223struct smb_com_transaction2_sfi_req { 1330struct smb_com_transaction2_sfi_req {
1224 struct smb_hdr hdr; /* wct = 15 */ 1331 struct smb_hdr hdr; /* wct = 15 */
@@ -1244,7 +1351,7 @@ struct smb_com_transaction2_sfi_req {
1244 __u16 Fid; 1351 __u16 Fid;
1245 __le16 InformationLevel; 1352 __le16 InformationLevel;
1246 __u16 Reserved4; 1353 __u16 Reserved4;
1247}; 1354} __attribute__((packed));
1248 1355
1249struct smb_com_transaction2_sfi_rsp { 1356struct smb_com_transaction2_sfi_rsp {
1250 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1357 struct smb_hdr hdr; /* wct = 10 + SetupCount */
@@ -1252,7 +1359,7 @@ struct smb_com_transaction2_sfi_rsp {
1252 __u16 ByteCount; 1359 __u16 ByteCount;
1253 __u16 Reserved2; /* parameter word reserved - 1360 __u16 Reserved2; /* parameter word reserved -
1254 present for infolevels > 100 */ 1361 present for infolevels > 100 */
1255}; 1362} __attribute__((packed));
1256 1363
1257struct smb_t2_qfi_req { 1364struct smb_t2_qfi_req {
1258 struct smb_hdr hdr; 1365 struct smb_hdr hdr;
@@ -1260,7 +1367,7 @@ struct smb_t2_qfi_req {
1260 __u8 Pad; 1367 __u8 Pad;
1261 __u16 Fid; 1368 __u16 Fid;
1262 __le16 InformationLevel; 1369 __le16 InformationLevel;
1263}; 1370} __attribute__((packed));
1264 1371
1265struct smb_t2_qfi_rsp { 1372struct smb_t2_qfi_rsp {
1266 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1373 struct smb_hdr hdr; /* wct = 10 + SetupCount */
@@ -1268,7 +1375,7 @@ struct smb_t2_qfi_rsp {
1268 __u16 ByteCount; 1375 __u16 ByteCount;
1269 __u16 Reserved2; /* parameter word reserved - 1376 __u16 Reserved2; /* parameter word reserved -
1270 present for infolevels > 100 */ 1377 present for infolevels > 100 */
1271}; 1378} __attribute__((packed));
1272 1379
1273/* 1380/*
1274 * Flags on T2 FINDFIRST and FINDNEXT 1381 * Flags on T2 FINDFIRST and FINDNEXT
@@ -1310,13 +1417,13 @@ typedef struct smb_com_transaction2_ffirst_req {
1310 __le16 InformationLevel; 1417 __le16 InformationLevel;
1311 __le32 SearchStorageType; 1418 __le32 SearchStorageType;
1312 char FileName[1]; 1419 char FileName[1];
1313} TRANSACTION2_FFIRST_REQ; 1420} __attribute__((packed)) TRANSACTION2_FFIRST_REQ;
1314 1421
1315typedef struct smb_com_transaction2_ffirst_rsp { 1422typedef struct smb_com_transaction2_ffirst_rsp {
1316 struct smb_hdr hdr; /* wct = 10 */ 1423 struct smb_hdr hdr; /* wct = 10 */
1317 struct trans2_resp t2; 1424 struct trans2_resp t2;
1318 __u16 ByteCount; 1425 __u16 ByteCount;
1319} TRANSACTION2_FFIRST_RSP; 1426} __attribute__((packed)) TRANSACTION2_FFIRST_RSP;
1320 1427
1321typedef struct smb_com_transaction2_ffirst_rsp_parms { 1428typedef struct smb_com_transaction2_ffirst_rsp_parms {
1322 __u16 SearchHandle; 1429 __u16 SearchHandle;
@@ -1324,7 +1431,7 @@ typedef struct smb_com_transaction2_ffirst_rsp_parms {
1324 __le16 EndofSearch; 1431 __le16 EndofSearch;
1325 __le16 EAErrorOffset; 1432 __le16 EAErrorOffset;
1326 __le16 LastNameOffset; 1433 __le16 LastNameOffset;
1327} T2_FFIRST_RSP_PARMS; 1434} __attribute__((packed)) T2_FFIRST_RSP_PARMS;
1328 1435
1329typedef struct smb_com_transaction2_fnext_req { 1436typedef struct smb_com_transaction2_fnext_req {
1330 struct smb_hdr hdr; /* wct = 15 */ 1437 struct smb_hdr hdr; /* wct = 15 */
@@ -1352,20 +1459,20 @@ typedef struct smb_com_transaction2_fnext_req {
1352 __u32 ResumeKey; 1459 __u32 ResumeKey;
1353 __le16 SearchFlags; 1460 __le16 SearchFlags;
1354 char ResumeFileName[1]; 1461 char ResumeFileName[1];
1355} TRANSACTION2_FNEXT_REQ; 1462} __attribute__((packed)) TRANSACTION2_FNEXT_REQ;
1356 1463
1357typedef struct smb_com_transaction2_fnext_rsp { 1464typedef struct smb_com_transaction2_fnext_rsp {
1358 struct smb_hdr hdr; /* wct = 10 */ 1465 struct smb_hdr hdr; /* wct = 10 */
1359 struct trans2_resp t2; 1466 struct trans2_resp t2;
1360 __u16 ByteCount; 1467 __u16 ByteCount;
1361} TRANSACTION2_FNEXT_RSP; 1468} __attribute__((packed)) TRANSACTION2_FNEXT_RSP;
1362 1469
1363typedef struct smb_com_transaction2_fnext_rsp_parms { 1470typedef struct smb_com_transaction2_fnext_rsp_parms {
1364 __le16 SearchCount; 1471 __le16 SearchCount;
1365 __le16 EndofSearch; 1472 __le16 EndofSearch;
1366 __le16 EAErrorOffset; 1473 __le16 EAErrorOffset;
1367 __le16 LastNameOffset; 1474 __le16 LastNameOffset;
1368} T2_FNEXT_RSP_PARMS; 1475} __attribute__((packed)) T2_FNEXT_RSP_PARMS;
1369 1476
1370/* QFSInfo Levels */ 1477/* QFSInfo Levels */
1371#define SMB_INFO_ALLOCATION 1 1478#define SMB_INFO_ALLOCATION 1
@@ -1402,14 +1509,51 @@ typedef struct smb_com_transaction2_qfsi_req {
1402 __le16 ByteCount; 1509 __le16 ByteCount;
1403 __u8 Pad; 1510 __u8 Pad;
1404 __le16 InformationLevel; 1511 __le16 InformationLevel;
1405} TRANSACTION2_QFSI_REQ; 1512} __attribute__((packed)) TRANSACTION2_QFSI_REQ;
1406 1513
1407typedef struct smb_com_transaction_qfsi_rsp { 1514typedef struct smb_com_transaction_qfsi_rsp {
1408 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1515 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1409 struct trans2_resp t2; 1516 struct trans2_resp t2;
1410 __u16 ByteCount; 1517 __u16 ByteCount;
1411 __u8 Pad; /* may be three bytes *//* followed by data area */ 1518 __u8 Pad; /* may be three bytes *//* followed by data area */
1412} TRANSACTION2_QFSI_RSP; 1519} __attribute__((packed)) TRANSACTION2_QFSI_RSP;
1520
1521
1522/* SETFSInfo Levels */
1523#define SMB_SET_CIFS_UNIX_INFO 0x200
1524typedef struct smb_com_transaction2_setfsi_req {
1525 struct smb_hdr hdr; /* wct = 15 */
1526 __le16 TotalParameterCount;
1527 __le16 TotalDataCount;
1528 __le16 MaxParameterCount;
1529 __le16 MaxDataCount;
1530 __u8 MaxSetupCount;
1531 __u8 Reserved;
1532 __le16 Flags;
1533 __le32 Timeout;
1534 __u16 Reserved2;
1535 __le16 ParameterCount; /* 4 */
1536 __le16 ParameterOffset;
1537 __le16 DataCount; /* 12 */
1538 __le16 DataOffset;
1539 __u8 SetupCount; /* one */
1540 __u8 Reserved3;
1541 __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
1542 __le16 ByteCount;
1543 __u8 Pad;
1544 __u16 FileNum; /* Parameters start. */
1545 __le16 InformationLevel;/* Parameters end. */
1546 __le16 ClientUnixMajor; /* Data start. */
1547 __le16 ClientUnixMinor;
1548 __le64 ClientUnixCap; /* Data end */
1549} __attribute__((packed)) TRANSACTION2_SETFSI_REQ;
1550
1551typedef struct smb_com_transaction2_setfsi_rsp {
1552 struct smb_hdr hdr; /* wct = 10 */
1553 struct trans2_resp t2;
1554 __u16 ByteCount;
1555} __attribute__((packed)) TRANSACTION2_SETFSI_RSP;
1556
1413 1557
1414typedef struct smb_com_transaction2_get_dfs_refer_req { 1558typedef struct smb_com_transaction2_get_dfs_refer_req {
1415 struct smb_hdr hdr; /* wct = 15 */ 1559 struct smb_hdr hdr; /* wct = 15 */
@@ -1433,7 +1577,7 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
1433 __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */ 1577 __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
1434 __le16 MaxReferralLevel; 1578 __le16 MaxReferralLevel;
1435 char RequestFileName[1]; 1579 char RequestFileName[1];
1436} TRANSACTION2_GET_DFS_REFER_REQ; 1580} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
1437 1581
1438typedef struct dfs_referral_level_3 { 1582typedef struct dfs_referral_level_3 {
1439 __le16 VersionNumber; 1583 __le16 VersionNumber;
@@ -1445,7 +1589,7 @@ typedef struct dfs_referral_level_3 {
1445 __le16 DfsPathOffset; 1589 __le16 DfsPathOffset;
1446 __le16 DfsAlternatePathOffset; 1590 __le16 DfsAlternatePathOffset;
1447 __le16 NetworkAddressOffset; 1591 __le16 NetworkAddressOffset;
1448} REFERRAL3; 1592} __attribute__((packed)) REFERRAL3;
1449 1593
1450typedef struct smb_com_transaction_get_dfs_refer_rsp { 1594typedef struct smb_com_transaction_get_dfs_refer_rsp {
1451 struct smb_hdr hdr; /* wct = 10 */ 1595 struct smb_hdr hdr; /* wct = 10 */
@@ -1458,7 +1602,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
1458 __u16 Pad2; 1602 __u16 Pad2;
1459 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ 1603 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
1460 /* followed by the strings pointed to by the referral structures */ 1604 /* followed by the strings pointed to by the referral structures */
1461} TRANSACTION2_GET_DFS_REFER_RSP; 1605} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP;
1462 1606
1463/* DFS Flags */ 1607/* DFS Flags */
1464#define DFSREF_REFERRAL_SERVER 0x0001 1608#define DFSREF_REFERRAL_SERVER 0x0001
@@ -1512,7 +1656,7 @@ struct serverInfo {
1512 unsigned char versionMinor; 1656 unsigned char versionMinor;
1513 unsigned long type; 1657 unsigned long type;
1514 unsigned int commentOffset; 1658 unsigned int commentOffset;
1515}; 1659} __attribute__((packed));
1516 1660
1517/* 1661/*
1518 * The following structure is the format of the data returned on a NetShareEnum 1662 * The following structure is the format of the data returned on a NetShareEnum
@@ -1524,39 +1668,55 @@ struct shareInfo {
1524 char pad; 1668 char pad;
1525 unsigned short type; 1669 unsigned short type;
1526 unsigned int commentOffset; 1670 unsigned int commentOffset;
1527}; 1671} __attribute__((packed));
1528 1672
1529struct aliasInfo { 1673struct aliasInfo {
1530 char aliasName[9]; 1674 char aliasName[9];
1531 char pad; 1675 char pad;
1532 unsigned int commentOffset; 1676 unsigned int commentOffset;
1533 unsigned char type[2]; 1677 unsigned char type[2];
1534}; 1678} __attribute__((packed));
1535 1679
1536struct aliasInfo92 { 1680struct aliasInfo92 {
1537 int aliasNameOffset; 1681 int aliasNameOffset;
1538 int serverNameOffset; 1682 int serverNameOffset;
1539 int shareNameOffset; 1683 int shareNameOffset;
1540}; 1684} __attribute__((packed));
1541 1685
1542typedef struct { 1686typedef struct {
1543 __le64 TotalAllocationUnits; 1687 __le64 TotalAllocationUnits;
1544 __le64 FreeAllocationUnits; 1688 __le64 FreeAllocationUnits;
1545 __le32 SectorsPerAllocationUnit; 1689 __le32 SectorsPerAllocationUnit;
1546 __le32 BytesPerSector; 1690 __le32 BytesPerSector;
1547} FILE_SYSTEM_INFO; /* size info, level 0x103 */ 1691} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
1692
1693typedef struct {
1694 __le32 fsid;
1695 __le32 SectorsPerAllocationUnit;
1696 __le32 TotalAllocationUnits;
1697 __le32 FreeAllocationUnits;
1698 __le16 BytesPerSector;
1699} __attribute__((packed)) FILE_SYSTEM_ALLOC_INFO;
1548 1700
1549typedef struct { 1701typedef struct {
1550 __le16 MajorVersionNumber; 1702 __le16 MajorVersionNumber;
1551 __le16 MinorVersionNumber; 1703 __le16 MinorVersionNumber;
1552 __le64 Capability; 1704 __le64 Capability;
1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1705} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1706
1707/* Version numbers for CIFS UNIX major and minor. */
1708#define CIFS_UNIX_MAJOR_VERSION 1
1709#define CIFS_UNIX_MINOR_VERSION 0
1710
1554/* Linux/Unix extensions capability flags */ 1711/* Linux/Unix extensions capability flags */
1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1712#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1713#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1714#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1715#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1716#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
1717
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1718#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1719
1560typedef struct { 1720typedef struct {
1561 /* For undefined recommended transfer size return -1 in that field */ 1721 /* For undefined recommended transfer size return -1 in that field */
1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1722 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
@@ -1577,7 +1737,7 @@ typedef struct {
1577 __le64 FileSysIdentifier; /* fsid */ 1737 __le64 FileSysIdentifier; /* fsid */
1578 /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */ 1738 /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
1579 /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */ 1739 /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
1580} FILE_SYSTEM_POSIX_INFO; 1740} __attribute__((packed)) FILE_SYSTEM_POSIX_INFO;
1581 1741
1582/* DeviceType Flags */ 1742/* DeviceType Flags */
1583#define FILE_DEVICE_CD_ROM 0x00000002 1743#define FILE_DEVICE_CD_ROM 0x00000002
@@ -1602,14 +1762,14 @@ typedef struct {
1602typedef struct { 1762typedef struct {
1603 __le32 DeviceType; 1763 __le32 DeviceType;
1604 __le32 DeviceCharacteristics; 1764 __le32 DeviceCharacteristics;
1605} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */ 1765} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
1606 1766
1607typedef struct { 1767typedef struct {
1608 __le32 Attributes; 1768 __le32 Attributes;
1609 __le32 MaxPathNameComponentLength; 1769 __le32 MaxPathNameComponentLength;
1610 __le32 FileSystemNameLen; 1770 __le32 FileSystemNameLen;
1611 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ 1771 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
1612} FILE_SYSTEM_ATTRIBUTE_INFO; 1772} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
1613 1773
1614/******************************************************************************/ 1774/******************************************************************************/
1615/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */ 1775/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
@@ -1636,7 +1796,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */
1636 __le32 AlignmentRequirement; 1796 __le32 AlignmentRequirement;
1637 __le32 FileNameLength; 1797 __le32 FileNameLength;
1638 char FileName[1]; 1798 char FileName[1];
1639} FILE_ALL_INFO; /* level 0x107 QPathInfo */ 1799} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
1640 1800
1641/* defines for enumerating possible values of the Unix type field below */ 1801/* defines for enumerating possible values of the Unix type field below */
1642#define UNIX_FILE 0 1802#define UNIX_FILE 0
@@ -1660,11 +1820,11 @@ typedef struct {
1660 __u64 UniqueId; 1820 __u64 UniqueId;
1661 __le64 Permissions; 1821 __le64 Permissions;
1662 __le64 Nlinks; 1822 __le64 Nlinks;
1663} FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ 1823} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
1664 1824
1665typedef struct { 1825typedef struct {
1666 char LinkDest[1]; 1826 char LinkDest[1];
1667} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ 1827} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
1668 1828
1669/* The following three structures are needed only for 1829/* The following three structures are needed only for
1670 setting time to NT4 and some older servers via 1830 setting time to NT4 and some older servers via
@@ -1673,13 +1833,13 @@ typedef struct {
1673 __u16 Day:5; 1833 __u16 Day:5;
1674 __u16 Month:4; 1834 __u16 Month:4;
1675 __u16 Year:7; 1835 __u16 Year:7;
1676} SMB_DATE; 1836} __attribute__((packed)) SMB_DATE;
1677 1837
1678typedef struct { 1838typedef struct {
1679 __u16 TwoSeconds:5; 1839 __u16 TwoSeconds:5;
1680 __u16 Minutes:6; 1840 __u16 Minutes:6;
1681 __u16 Hours:5; 1841 __u16 Hours:5;
1682} SMB_TIME; 1842} __attribute__((packed)) SMB_TIME;
1683 1843
1684typedef struct { 1844typedef struct {
1685 __le16 CreationDate; /* SMB Date see above */ 1845 __le16 CreationDate; /* SMB Date see above */
@@ -1692,7 +1852,7 @@ typedef struct {
1692 __le32 AllocationSize; 1852 __le32 AllocationSize;
1693 __le16 Attributes; /* verify not u32 */ 1853 __le16 Attributes; /* verify not u32 */
1694 __le32 EASize; 1854 __le32 EASize;
1695} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ 1855} __attribute__((packed)) FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
1696 1856
1697typedef struct { 1857typedef struct {
1698 __le64 CreationTime; 1858 __le64 CreationTime;
@@ -1701,19 +1861,19 @@ typedef struct {
1701 __le64 ChangeTime; 1861 __le64 ChangeTime;
1702 __le32 Attributes; 1862 __le32 Attributes;
1703 __u32 Pad; 1863 __u32 Pad;
1704} FILE_BASIC_INFO; /* size info, level 0x101 */ 1864} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
1705 1865
1706struct file_allocation_info { 1866struct file_allocation_info {
1707 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ 1867 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
1708}; /* size used on disk, level 0x103 for set, 0x105 for query */ 1868} __attribute__((packed)); /* size used on disk, level 0x103 for set, 0x105 for query */
1709 1869
1710struct file_end_of_file_info { 1870struct file_end_of_file_info {
1711 __le64 FileSize; /* offset to end of file */ 1871 __le64 FileSize; /* offset to end of file */
1712}; /* size info, level 0x104 for set, 0x106 for query */ 1872} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
1713 1873
1714struct file_alt_name_info { 1874struct file_alt_name_info {
1715 __u8 alt_name[1]; 1875 __u8 alt_name[1];
1716}; /* level 0x0108 */ 1876} __attribute__((packed)); /* level 0x0108 */
1717 1877
1718struct file_stream_info { 1878struct file_stream_info {
1719 __le32 number_of_streams; /* BB check sizes and verify location */ 1879 __le32 number_of_streams; /* BB check sizes and verify location */
@@ -1730,7 +1890,7 @@ struct file_compression_info {
1730 __u8 ch_shift; 1890 __u8 ch_shift;
1731 __u8 cl_shift; 1891 __u8 cl_shift;
1732 __u8 pad[3]; 1892 __u8 pad[3];
1733}; /* level 0x10b */ 1893} __attribute__((packed)); /* level 0x10b */
1734 1894
1735/* POSIX ACL set/query path info structures */ 1895/* POSIX ACL set/query path info structures */
1736#define CIFS_ACL_VERSION 1 1896#define CIFS_ACL_VERSION 1
@@ -1738,7 +1898,7 @@ struct cifs_posix_ace { /* access control entry (ACE) */
1738 __u8 cifs_e_tag; 1898 __u8 cifs_e_tag;
1739 __u8 cifs_e_perm; 1899 __u8 cifs_e_perm;
1740 __le64 cifs_uid; /* or gid */ 1900 __le64 cifs_uid; /* or gid */
1741}; 1901} __attribute__((packed));
1742 1902
1743struct cifs_posix_acl { /* access conrol list (ACL) */ 1903struct cifs_posix_acl { /* access conrol list (ACL) */
1744 __le16 version; 1904 __le16 version;
@@ -1747,7 +1907,7 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
1747 struct cifs_posix_ace ace_array[0]; 1907 struct cifs_posix_ace ace_array[0];
1748 /* followed by 1908 /* followed by
1749 struct cifs_posix_ace default_ace_arraay[] */ 1909 struct cifs_posix_ace default_ace_arraay[] */
1750}; /* level 0x204 */ 1910} __attribute__((packed)); /* level 0x204 */
1751 1911
1752/* types of access control entries already defined in posix_acl.h */ 1912/* types of access control entries already defined in posix_acl.h */
1753/* #define CIFS_POSIX_ACL_USER_OBJ 0x01 1913/* #define CIFS_POSIX_ACL_USER_OBJ 0x01
@@ -1766,15 +1926,15 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
1766 1926
1767struct file_internal_info { 1927struct file_internal_info {
1768 __u64 UniqueId; /* inode number */ 1928 __u64 UniqueId; /* inode number */
1769}; /* level 0x3ee */ 1929} __attribute__((packed)); /* level 0x3ee */
1770struct file_mode_info { 1930struct file_mode_info {
1771 __le32 Mode; 1931 __le32 Mode;
1772}; /* level 0x3f8 */ 1932} __attribute__((packed)); /* level 0x3f8 */
1773 1933
1774struct file_attrib_tag { 1934struct file_attrib_tag {
1775 __le32 Attribute; 1935 __le32 Attribute;
1776 __le32 ReparseTag; 1936 __le32 ReparseTag;
1777}; /* level 0x40b */ 1937} __attribute__((packed)); /* level 0x40b */
1778 1938
1779 1939
1780/********************************************************/ 1940/********************************************************/
@@ -1798,7 +1958,7 @@ typedef struct {
1798 __le64 Permissions; 1958 __le64 Permissions;
1799 __le64 Nlinks; 1959 __le64 Nlinks;
1800 char FileName[1]; 1960 char FileName[1];
1801} FILE_UNIX_INFO; /* level 0x202 */ 1961} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */
1802 1962
1803typedef struct { 1963typedef struct {
1804 __le32 NextEntryOffset; 1964 __le32 NextEntryOffset;
@@ -1812,7 +1972,7 @@ typedef struct {
1812 __le32 ExtFileAttributes; 1972 __le32 ExtFileAttributes;
1813 __le32 FileNameLength; 1973 __le32 FileNameLength;
1814 char FileName[1]; 1974 char FileName[1];
1815} FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */ 1975} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */
1816 1976
1817typedef struct { 1977typedef struct {
1818 __le32 NextEntryOffset; 1978 __le32 NextEntryOffset;
@@ -1827,7 +1987,7 @@ typedef struct {
1827 __le32 FileNameLength; 1987 __le32 FileNameLength;
1828 __le32 EaSize; /* length of the xattrs */ 1988 __le32 EaSize; /* length of the xattrs */
1829 char FileName[1]; 1989 char FileName[1];
1830} FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */ 1990} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */
1831 1991
1832typedef struct { 1992typedef struct {
1833 __le32 NextEntryOffset; 1993 __le32 NextEntryOffset;
@@ -1844,7 +2004,7 @@ typedef struct {
1844 __le32 Reserved; 2004 __le32 Reserved;
1845 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ 2005 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
1846 char FileName[1]; 2006 char FileName[1];
1847} SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */ 2007} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */
1848 2008
1849typedef struct { 2009typedef struct {
1850 __le32 NextEntryOffset; 2010 __le32 NextEntryOffset;
@@ -1862,18 +2022,18 @@ typedef struct {
1862 __u8 Reserved; 2022 __u8 Reserved;
1863 __u8 ShortName[12]; 2023 __u8 ShortName[12];
1864 char FileName[1]; 2024 char FileName[1];
1865} FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ 2025} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
1866 2026
1867 2027
1868struct gea { 2028struct gea {
1869 unsigned char name_len; 2029 unsigned char name_len;
1870 char name[1]; 2030 char name[1];
1871}; 2031} __attribute__((packed));
1872 2032
1873struct gealist { 2033struct gealist {
1874 unsigned long list_len; 2034 unsigned long list_len;
1875 struct gea list[1]; 2035 struct gea list[1];
1876}; 2036} __attribute__((packed));
1877 2037
1878struct fea { 2038struct fea {
1879 unsigned char EA_flags; 2039 unsigned char EA_flags;
@@ -1881,21 +2041,21 @@ struct fea {
1881 __le16 value_len; 2041 __le16 value_len;
1882 char name[1]; 2042 char name[1];
1883 /* optionally followed by value */ 2043 /* optionally followed by value */
1884}; 2044} __attribute__((packed));
1885/* flags for _FEA.fEA */ 2045/* flags for _FEA.fEA */
1886#define FEA_NEEDEA 0x80 /* need EA bit */ 2046#define FEA_NEEDEA 0x80 /* need EA bit */
1887 2047
1888struct fealist { 2048struct fealist {
1889 __le32 list_len; 2049 __le32 list_len;
1890 struct fea list[1]; 2050 struct fea list[1];
1891}; 2051} __attribute__((packed));
1892 2052
1893/* used to hold an arbitrary blob of data */ 2053/* used to hold an arbitrary blob of data */
1894struct data_blob { 2054struct data_blob {
1895 __u8 *data; 2055 __u8 *data;
1896 size_t length; 2056 size_t length;
1897 void (*free) (struct data_blob * data_blob); 2057 void (*free) (struct data_blob * data_blob);
1898}; 2058} __attribute__((packed));
1899 2059
1900 2060
1901#ifdef CONFIG_CIFS_POSIX 2061#ifdef CONFIG_CIFS_POSIX
@@ -1907,18 +2067,17 @@ struct data_blob {
1907 perhaps add a CreateDevice - to create Pipes and other special .inodes 2067 perhaps add a CreateDevice - to create Pipes and other special .inodes
1908 Also note POSIX open flags 2068 Also note POSIX open flags
1909 2) Close - to return the last write time to do cache across close more safely 2069 2) Close - to return the last write time to do cache across close more safely
1910 3) PosixQFSInfo - to return statfs info 2070 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) 2071 forms short (matches readdir) and full (enough info to cache inodes)
1912 5) Mkdir - set mode 2072 4) Mkdir - set mode
1913 2073
1914 And under consideration: 2074 And under consideration:
1915 6) FindClose2 (return nanosecond timestamp ??) 2075 5) FindClose2 (return nanosecond timestamp ??)
1916 7) Use nanosecond timestamps throughout all time fields if 2076 6) Use nanosecond timestamps throughout all time fields if
1917 corresponding attribute flag is set 2077 corresponding attribute flag is set
1918 8) sendfile - handle based copy 2078 7) sendfile - handle based copy
1919 9) Direct i/o 2079 8) Direct i/o
1920 10) "POSIX ACL" support 2080 9) Misc fcntls?
1921 11) Misc fcntls?
1922 2081
1923 what about fixing 64 bit alignment 2082 what about fixing 64 bit alignment
1924 2083
@@ -1974,7 +2133,7 @@ struct data_blob {
1974 2133
1975 */ 2134 */
1976 2135
1977/* xsymlink is a symlink format that can be used 2136/* xsymlink is a symlink format (used by MacOS) that can be used
1978 to save symlink info in a regular file when 2137 to save symlink info in a regular file when
1979 mounted to operating systems that do not 2138 mounted to operating systems that do not
1980 support the cifs Unix extensions or EAs (for xattr 2139 support the cifs Unix extensions or EAs (for xattr
@@ -1999,7 +2158,7 @@ struct xsymlink {
1999 char cr2; /* \n */ 2158 char cr2; /* \n */
2000/* if room left, then end with \n then 0x20s by convention but not required */ 2159/* if room left, then end with \n then 0x20s by convention but not required */
2001 char path[1024]; 2160 char path[1024];
2002}; 2161} __attribute__((packed));
2003 2162
2004typedef struct file_xattr_info { 2163typedef struct file_xattr_info {
2005 /* BB do we need another field for flags? BB */ 2164 /* BB do we need another field for flags? BB */
@@ -2007,7 +2166,7 @@ typedef struct file_xattr_info {
2007 __u32 xattr_value_len; 2166 __u32 xattr_value_len;
2008 char xattr_name[0]; 2167 char xattr_name[0];
2009 /* followed by xattr_value[xattr_value_len], no pad */ 2168 /* followed by xattr_value[xattr_value_len], no pad */
2010} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ 2169} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
2011 2170
2012 2171
2013/* flags for chattr command */ 2172/* flags for chattr command */
@@ -2033,10 +2192,8 @@ typedef struct file_xattr_info {
2033typedef struct file_chattr_info { 2192typedef struct file_chattr_info {
2034 __le64 mask; /* list of all possible attribute bits */ 2193 __le64 mask; /* list of all possible attribute bits */
2035 __le64 mode; /* list of actual attribute bits on this inode */ 2194 __le64 mode; /* list of actual attribute bits on this inode */
2036} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */ 2195} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
2037 2196
2038#endif 2197#endif
2039 2198
2040#pragma pack() /* resume default structure packing */
2041
2042#endif /* _CIFSPDU_H */ 2199#endif /* _CIFSPDU_H */
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/ntlmssp.h b/fs/cifs/ntlmssp.h
index 6facb41117a3..803389b64a2c 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -19,8 +19,6 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#pragma pack(1)
23
24#define NTLMSSP_SIGNATURE "NTLMSSP" 22#define NTLMSSP_SIGNATURE "NTLMSSP"
25/* Message Types */ 23/* Message Types */
26#define NtLmNegotiate cpu_to_le32(1) 24#define NtLmNegotiate cpu_to_le32(1)
@@ -63,7 +61,7 @@ typedef struct _SECURITY_BUFFER {
63 __le16 Length; 61 __le16 Length;
64 __le16 MaximumLength; 62 __le16 MaximumLength;
65 __le32 Buffer; /* offset to buffer */ 63 __le32 Buffer; /* offset to buffer */
66} SECURITY_BUFFER; 64} __attribute__((packed)) SECURITY_BUFFER;
67 65
68typedef struct _NEGOTIATE_MESSAGE { 66typedef struct _NEGOTIATE_MESSAGE {
69 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 67 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
@@ -73,7 +71,7 @@ typedef struct _NEGOTIATE_MESSAGE {
73 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ 71 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
74 char DomainString[0]; 72 char DomainString[0];
75 /* followed by WorkstationString */ 73 /* followed by WorkstationString */
76} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; 74} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
77 75
78typedef struct _CHALLENGE_MESSAGE { 76typedef struct _CHALLENGE_MESSAGE {
79 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 77 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
@@ -83,7 +81,7 @@ typedef struct _CHALLENGE_MESSAGE {
83 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; 81 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
84 __u8 Reserved[8]; 82 __u8 Reserved[8];
85 SECURITY_BUFFER TargetInfoArray; 83 SECURITY_BUFFER TargetInfoArray;
86} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; 84} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
87 85
88typedef struct _AUTHENTICATE_MESSAGE { 86typedef struct _AUTHENTICATE_MESSAGE {
89 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 87 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
@@ -96,6 +94,4 @@ typedef struct _AUTHENTICATE_MESSAGE {
96 SECURITY_BUFFER SessionKey; 94 SECURITY_BUFFER SessionKey;
97 __le32 NegotiateFlags; 95 __le32 NegotiateFlags;
98 char UserString[0]; 96 char UserString[0];
99} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; 97} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
100
101#pragma pack() /* resume default structure packing */
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/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index 806c0ed06da9..9222033cad8e 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -21,8 +21,6 @@
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 23
24#pragma pack(1)
25
26/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ 24/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
27 25
28 /* RFC 1002 session packet types */ 26 /* RFC 1002 session packet types */
@@ -48,17 +46,17 @@ struct rfc1002_session_packet {
48 __u8 calling_len; 46 __u8 calling_len;
49 __u8 calling_name[32]; 47 __u8 calling_name[32];
50 __u8 scope2; /* null */ 48 __u8 scope2; /* null */
51 } session_req; 49 } __attribute__((packed)) session_req;
52 struct { 50 struct {
53 __u32 retarget_ip_addr; 51 __u32 retarget_ip_addr;
54 __u16 port; 52 __u16 port;
55 } retarget_resp; 53 } __attribute__((packed)) retarget_resp;
56 __u8 neg_ses_resp_error_code; 54 __u8 neg_ses_resp_error_code;
57 /* POSITIVE_SESSION_RESPONSE packet does not include trailer. 55 /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
58 SESSION_KEEP_ALIVE packet also does not include a trailer. 56 SESSION_KEEP_ALIVE packet also does not include a trailer.
59 Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */ 57 Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
60 } trailer; 58 } __attribute__((packed)) trailer;
61}; 59} __attribute__((packed));
62 60
63/* Negative Session Response error codes */ 61/* Negative Session Response error codes */
64#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */ 62#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
@@ -74,6 +72,3 @@ server netbios name). Currently server names are resolved only via DNS
74(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/ 72(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
75 73
76#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER " 74#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
77
78#pragma pack() /* resume default structure packing */
79
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:
diff --git a/mm/swap.c b/mm/swap.c
index 96387e20184a..154ae13d8b7e 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -259,6 +259,8 @@ void __pagevec_release(struct pagevec *pvec)
259 pagevec_reinit(pvec); 259 pagevec_reinit(pvec);
260} 260}
261 261
262EXPORT_SYMBOL(__pagevec_release);
263
262/* 264/*
263 * pagevec_release() for pages which are known to not be on the LRU 265 * pagevec_release() for pages which are known to not be on the LRU
264 * 266 *
@@ -387,6 +389,7 @@ unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping,
387 return pagevec_count(pvec); 389 return pagevec_count(pvec);
388} 390}
389 391
392EXPORT_SYMBOL(pagevec_lookup_tag);
390 393
391#ifdef CONFIG_SMP 394#ifdef CONFIG_SMP
392/* 395/*