aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/AUTHORS4
-rw-r--r--fs/cifs/CHANGES32
-rw-r--r--fs/cifs/README7
-rw-r--r--fs/cifs/cifs_debug.c38
-rw-r--r--fs/cifs/cifs_fs_sb.h3
-rw-r--r--fs/cifs/cifsfs.c38
-rw-r--r--fs/cifs/cifsfs.h3
-rw-r--r--fs/cifs/cifsglob.h85
-rw-r--r--fs/cifs/cifspdu.h166
-rw-r--r--fs/cifs/cifsproto.h29
-rw-r--r--fs/cifs/cifssmb.c505
-rw-r--r--fs/cifs/connect.c143
-rw-r--r--fs/cifs/dir.c108
-rw-r--r--fs/cifs/fcntl.c8
-rw-r--r--fs/cifs/file.c90
-rw-r--r--fs/cifs/inode.c38
-rw-r--r--fs/cifs/link.c5
-rw-r--r--fs/cifs/misc.c90
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/readdir.c49
-rw-r--r--fs/cifs/transport.c227
21 files changed, 1378 insertions, 294 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..6c73f020ef40 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,24 @@
1Version 1.36
2------------
3Add support for mounting to older pre-CIFS servers such as Windows9x and ME.
4For these older servers, add option for passing netbios name of server in
5on mount (servernetbiosname). Add suspend support for power management, to
6avoid cifsd thread preventing software suspend from working.
7Add mount option for disabling the default behavior of sending byte range lock
8requests to the server (necessary for certain applications which break with
9mandatory lock behavior such as Evolution), and also mount option for
10requesting case insensitive matching for path based requests (requesting
11case sensitive is the default).
12
1Version 1.35 13Version 1.35
2------------ 14------------
3Add writepage performance improvements. Fix path name conversions 15Add writepage performance improvements. Fix path name conversions
4for long filenames on mounts which were done with "mapchars" mount option 16for long filenames on mounts which were done with "mapchars" mount option
5specified. 17specified. Ensure multiplex ids do not collide. Fix case in which
18rmmod can oops if done soon after last unmount. Fix truncated
19search (readdir) output when resume filename was a long filename.
20Fix filename conversion when mapchars mount option was specified and
21filename was a long filename.
6 22
7Version 1.34 23Version 1.34
8------------ 24------------
@@ -11,7 +27,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 27kills the cifsd thread (NB: killing the cifs kernel threads is not
12recommended, unmount and rmmod cifs will kill them when they are 28recommended, unmount and rmmod cifs will kill them when they are
13no longer needed). Fix readdir to ASCII servers (ie older servers 29no longer needed). Fix readdir to ASCII servers (ie older servers
14which do not support Unicode) and also require asterik. 30which do not support Unicode) and also require asterisk.
15Fix out of memory case in which data could be written one page 31Fix out of memory case in which data could be written one page
16off in the page cache. 32off in the page cache.
17 33
@@ -101,7 +117,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call.
101 117
102Version 1.25 118Version 1.25
103------------ 119------------
104Fix internationlization problem in cifs readdir with filenames that map to 120Fix internationalization problem in cifs readdir with filenames that map to
105longer UTF8 strings than the string on the wire was in Unicode. Add workaround 121longer 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 122for readdir to netapp servers. Fix search rewind (seek into readdir to return
107non-consecutive entries). Do not do readdir when server negotiates 123non-consecutive entries). Do not do readdir when server negotiates
@@ -276,7 +292,7 @@ Fix caching problem when files opened by multiple clients in which
276page cache could contain stale data, and write through did 292page cache could contain stale data, and write through did
277not occur often enough while file was still open when read ahead 293not occur often enough while file was still open when read ahead
278(read oplock) not allowed. Treat "sep=" when first mount option 294(read oplock) not allowed. Treat "sep=" when first mount option
279as an overrride of comma as the default separator between mount 295as an override of comma as the default separator between mount
280options. 296options.
281 297
282Version 1.01 298Version 1.01
@@ -286,7 +302,7 @@ Allow passwords longer than 16 bytes. Allow null password string.
286Version 1.00 302Version 1.00
287------------ 303------------
288Gracefully clean up failed mounts when attempting to mount to servers such as 304Gracefully clean up failed mounts when attempting to mount to servers such as
289Windows 98 that terminate tcp sessions during prototocol negotiation. Handle 305Windows 98 that terminate tcp sessions during protocol negotiation. Handle
290embedded commas in mount parsing of passwords. 306embedded commas in mount parsing of passwords.
291 307
292Version 0.99 308Version 0.99
@@ -295,7 +311,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 311instance is closed so that the client does not continue using stale local
296copy rather than later modified server copy of file. Do not reconnect 312copy rather than later modified server copy of file. Do not reconnect
297when server drops the tcp session prematurely before negotiate 313when server drops the tcp session prematurely before negotiate
298protocol response. Fix oops in roepen_file when dentry freed. Allow 314protocol response. Fix oops in reopen_file when dentry freed. Allow
299the support for CIFS Unix Extensions to be disabled via proc interface. 315the support for CIFS Unix Extensions to be disabled via proc interface.
300 316
301Version 0.98 317Version 0.98
@@ -637,7 +653,7 @@ versions of 2.4 kernel (now builds and works again on kernels at least as early
637Version 0.41 653Version 0.41
638------------ 654------------
639Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked 655Various 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. 656files now return the correct number of links on fstat as they are repeatedly linked and unlinked.
641 657
642Version 0.40 658Version 0.40
643------------ 659------------
@@ -704,7 +720,7 @@ session)
704and cleaned them up and made them more consistent with other cifs functions. 720and cleaned them up and made them more consistent with other cifs functions.
705 721
7067) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways 7227) 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, 723(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 724nor is the symlink support using the Unix extensions
709 725
7108) Started adding the readlink and follow_link code 7268) Started adding the readlink and follow_link code
diff --git a/fs/cifs/README b/fs/cifs/README
index 34b0cf7111f3..3b610d08dc1e 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -407,6 +407,13 @@ A partial list of the supported mount options follows:
407 This has no effect if the server does not support 407 This has no effect if the server does not support
408 Unicode on the wire. 408 Unicode on the wire.
409 nomapchars Do not translate any of these seven characters (default). 409 nomapchars Do not translate any of these seven characters (default).
410 nocase Request case insensitive path name matching (case
411 sensitive is the default if the server suports it).
412 nobrl Do not send byte range lock requests to the server.
413 This is necessary for certain applications that break
414 with cifs style mandatory byte range locks (and most
415 cifs servers do not yet support requesting advisory
416 byte range locks).
410 remount remount the share (often used to change from ro to rw mounts 417 remount remount the share (often used to change from ro to rw mounts
411 or vice versa) 418 or vice versa)
412 419
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 4061e43471c1..f4c6544468ab 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -254,35 +254,51 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
254 buf += sprintf(buf, "\tDISCONNECTED "); 254 buf += sprintf(buf, "\tDISCONNECTED ");
255 length += 14; 255 length += 14;
256 } 256 }
257 item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d", 257 item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
258 atomic_read(&tcon->num_smbs_sent), 258 atomic_read(&tcon->num_smbs_sent),
259 atomic_read(&tcon->num_oplock_brks)); 259 atomic_read(&tcon->num_oplock_brks));
260 buf += item_length; 260 buf += item_length;
261 length += item_length; 261 length += item_length;
262 item_length = sprintf(buf,"\nReads: %d Bytes %lld", 262 item_length = sprintf(buf, "\nReads: %d Bytes %lld",
263 atomic_read(&tcon->num_reads), 263 atomic_read(&tcon->num_reads),
264 (long long)(tcon->bytes_read)); 264 (long long)(tcon->bytes_read));
265 buf += item_length; 265 buf += item_length;
266 length += item_length; 266 length += item_length;
267 item_length = sprintf(buf,"\nWrites: %d Bytes: %lld", 267 item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
268 atomic_read(&tcon->num_writes), 268 atomic_read(&tcon->num_writes),
269 (long long)(tcon->bytes_written)); 269 (long long)(tcon->bytes_written));
270 buf += item_length;
271 length += item_length;
272 item_length = sprintf(buf,
273 "\nLocks: %d HardLinks: %d Symlinks: %d",
274 atomic_read(&tcon->num_locks),
275 atomic_read(&tcon->num_hardlinks),
276 atomic_read(&tcon->num_symlinks));
277 buf += item_length;
278 length += item_length;
279
280 item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
281 atomic_read(&tcon->num_opens),
282 atomic_read(&tcon->num_closes),
283 atomic_read(&tcon->num_deletes));
270 buf += item_length; 284 buf += item_length;
271 length += item_length; 285 length += item_length;
272 item_length = sprintf(buf, 286 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), 287 atomic_read(&tcon->num_mkdirs),
277 atomic_read(&tcon->num_rmdirs)); 288 atomic_read(&tcon->num_rmdirs));
278 buf += item_length; 289 buf += item_length;
279 length += item_length; 290 length += item_length;
280 item_length = sprintf(buf, 291 item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
281 "\nRenames: %d T2 Renames %d",
282 atomic_read(&tcon->num_renames), 292 atomic_read(&tcon->num_renames),
283 atomic_read(&tcon->num_t2renames)); 293 atomic_read(&tcon->num_t2renames));
284 buf += item_length; 294 buf += item_length;
285 length += item_length; 295 length += item_length;
296 item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
297 atomic_read(&tcon->num_ffirst),
298 atomic_read(&tcon->num_fnext),
299 atomic_read(&tcon->num_fclose));
300 buf += item_length;
301 length += item_length;
286 } 302 }
287 read_unlock(&GlobalSMBSeslock); 303 read_unlock(&GlobalSMBSeslock);
288 304
@@ -360,7 +376,7 @@ cifs_proc_init(void)
360 if (pde) 376 if (pde)
361 pde->write_proc = oplockEnabled_write; 377 pde->write_proc = oplockEnabled_write;
362 378
363 pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs, 379 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
364 quotaEnabled_read, NULL); 380 quotaEnabled_read, NULL);
365 if (pde) 381 if (pde)
366 pde->write_proc = quotaEnabled_write; 382 pde->write_proc = quotaEnabled_write;
@@ -419,7 +435,7 @@ cifs_proc_clean(void)
419 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 435 remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
420 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); 436 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
421 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); 437 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
422 remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs); 438 remove_proc_entry("Experimental",proc_fs_cifs);
423 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); 439 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
424 remove_proc_entry("cifs", proc_root_fs); 440 remove_proc_entry("cifs", proc_root_fs);
425} 441}
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 8cc23e7d0d5d..43fb2aafa528 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;
@@ -781,6 +784,8 @@ static int cifs_oplock_thread(void * dummyarg)
781 784
782 oplockThread = current; 785 oplockThread = current;
783 do { 786 do {
787 if(try_to_freeze())
788 continue;
784 set_current_state(TASK_INTERRUPTIBLE); 789 set_current_state(TASK_INTERRUPTIBLE);
785 790
786 schedule_timeout(1*HZ); 791 schedule_timeout(1*HZ);
@@ -834,8 +839,23 @@ static int cifs_oplock_thread(void * dummyarg)
834 spin_unlock(&GlobalMid_Lock); 839 spin_unlock(&GlobalMid_Lock);
835 } 840 }
836 } while(!signal_pending(current)); 841 } while(!signal_pending(current));
837 complete_and_exit (&cifs_oplock_exited, 0);
838 oplockThread = NULL; 842 oplockThread = NULL;
843 complete_and_exit (&cifs_oplock_exited, 0);
844}
845
846static int cifs_dnotify_thread(void * dummyarg)
847{
848 daemonize("cifsdnotifyd");
849 allow_signal(SIGTERM);
850
851 dnotifyThread = current;
852 do {
853 if(try_to_freeze())
854 continue;
855 set_current_state(TASK_INTERRUPTIBLE);
856 schedule_timeout(39*HZ);
857 } while(!signal_pending(current));
858 complete_and_exit (&cifs_dnotify_exited, 0);
839} 859}
840 860
841static int __init 861static int __init
@@ -884,10 +904,16 @@ init_cifs(void)
884 if (!rc) { 904 if (!rc) {
885 rc = (int)kernel_thread(cifs_oplock_thread, NULL, 905 rc = (int)kernel_thread(cifs_oplock_thread, NULL,
886 CLONE_FS | CLONE_FILES | CLONE_VM); 906 CLONE_FS | CLONE_FILES | CLONE_VM);
887 if(rc > 0) 907 if(rc > 0) {
888 return 0; 908 rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
889 else 909 CLONE_FS | CLONE_FILES | CLONE_VM);
910 if(rc > 0)
911 return 0;
912 else
913 cERROR(1,("error %d create dnotify thread", rc));
914 } else {
890 cERROR(1,("error %d create oplock thread",rc)); 915 cERROR(1,("error %d create oplock thread",rc));
916 }
891 } 917 }
892 cifs_destroy_request_bufs(); 918 cifs_destroy_request_bufs();
893 } 919 }
@@ -916,6 +942,10 @@ exit_cifs(void)
916 send_sig(SIGTERM, oplockThread, 1); 942 send_sig(SIGTERM, oplockThread, 1);
917 wait_for_completion(&cifs_oplock_exited); 943 wait_for_completion(&cifs_oplock_exited);
918 } 944 }
945 if(dnotifyThread) {
946 send_sig(SIGTERM, dnotifyThread, 1);
947 wait_for_completion(&cifs_dnotify_exited);
948 }
919} 949}
920 950
921MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); 951MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 1fd21f66f243..bb3404a99e5f 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.36"
100#endif /* _CIFSFS_H */ 101#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 81babab265e1..a9c791edede5 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;
@@ -147,8 +148,10 @@ struct TCP_Server_Info {
147 /* (returned on Negotiate */ 148 /* (returned on Negotiate */
148 int capabilities; /* allow selective disabling of caps by smb sess */ 149 int capabilities; /* allow selective disabling of caps by smb sess */
149 __u16 timeZone; 150 __u16 timeZone;
151 __u16 CurrentMid; /* multiplex id - rotating counter */
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 152 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */ 153 /* 16th byte of RFC1001 workstation name is always null */
154 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
152 __u32 sequence_number; /* needed for CIFS PDU signature */ 155 __u32 sequence_number; /* needed for CIFS PDU signature */
153 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 156 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
154}; 157};
@@ -214,19 +217,41 @@ struct cifsTconInfo {
214 atomic_t num_reads; 217 atomic_t num_reads;
215 atomic_t num_oplock_brks; 218 atomic_t num_oplock_brks;
216 atomic_t num_opens; 219 atomic_t num_opens;
220 atomic_t num_closes;
217 atomic_t num_deletes; 221 atomic_t num_deletes;
218 atomic_t num_mkdirs; 222 atomic_t num_mkdirs;
219 atomic_t num_rmdirs; 223 atomic_t num_rmdirs;
220 atomic_t num_renames; 224 atomic_t num_renames;
221 atomic_t num_t2renames; 225 atomic_t num_t2renames;
226 atomic_t num_ffirst;
227 atomic_t num_fnext;
228 atomic_t num_fclose;
229 atomic_t num_hardlinks;
230 atomic_t num_symlinks;
231 atomic_t num_locks;
232#ifdef CONFIG_CIFS_STATS2
233 unsigned long long time_writes;
234 unsigned long long time_reads;
235 unsigned long long time_opens;
236 unsigned long long time_deletes;
237 unsigned long long time_closes;
238 unsigned long long time_mkdirs;
239 unsigned long long time_rmdirs;
240 unsigned long long time_renames;
241 unsigned long long time_t2renames;
242 unsigned long long time_ffirst;
243 unsigned long long time_fnext;
244 unsigned long long time_fclose;
245#endif /* CONFIG_CIFS_STATS2 */
222 __u64 bytes_read; 246 __u64 bytes_read;
223 __u64 bytes_written; 247 __u64 bytes_written;
224 spinlock_t stat_lock; 248 spinlock_t stat_lock;
225#endif 249#endif /* CONFIG_CIFS_STATS */
226 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 250 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
227 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ 251 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
228 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 252 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
229 unsigned retry:1; 253 unsigned retry:1;
254 unsigned nocase:1;
230 /* BB add field for back pointer to sb struct? */ 255 /* BB add field for back pointer to sb struct? */
231}; 256};
232 257
@@ -306,6 +331,41 @@ CIFS_SB(struct super_block *sb)
306 return sb->s_fs_info; 331 return sb->s_fs_info;
307} 332}
308 333
334static inline const char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
335{
336 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
337 return '/';
338 else
339 return '\\';
340}
341
342#ifdef CONFIG_CIFS_STATS
343#define cifs_stats_inc atomic_inc
344
345static inline void cifs_stats_bytes_written(struct cifsTconInfo *tcon,
346 unsigned int bytes)
347{
348 if (bytes) {
349 spin_lock(&tcon->stat_lock);
350 tcon->bytes_written += bytes;
351 spin_unlock(&tcon->stat_lock);
352 }
353}
354
355static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
356 unsigned int bytes)
357{
358 spin_lock(&tcon->stat_lock);
359 tcon->bytes_read += bytes;
360 spin_unlock(&tcon->stat_lock);
361}
362#else
363
364#define cifs_stats_inc(field) do {} while(0)
365#define cifs_stats_bytes_written(tcon, bytes) do {} while(0)
366#define cifs_stats_bytes_read(tcon, bytes) do {} while(0)
367
368#endif
309 369
310/* one of these for every pending CIFS request to the server */ 370/* one of these for every pending CIFS request to the server */
311struct mid_q_entry { 371struct mid_q_entry {
@@ -331,6 +391,20 @@ struct oplock_q_entry {
331 __u16 netfid; 391 __u16 netfid;
332}; 392};
333 393
394/* for pending dnotify requests */
395struct dir_notify_req {
396 struct list_head lhead;
397 __le16 Pid;
398 __le16 PidHigh;
399 __u16 Mid;
400 __u16 Tid;
401 __u16 Uid;
402 __u16 netfid;
403 __u32 filter; /* CompletionFilter (for multishot) */
404 int multishot;
405 struct file * pfile;
406};
407
334#define MID_FREE 0 408#define MID_FREE 0
335#define MID_REQUEST_ALLOCATED 1 409#define MID_REQUEST_ALLOCATED 1
336#define MID_REQUEST_SUBMITTED 2 410#define MID_REQUEST_SUBMITTED 2
@@ -399,6 +473,9 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
399 473
400GLOBAL_EXTERN struct list_head GlobalOplock_Q; 474GLOBAL_EXTERN struct list_head GlobalOplock_Q;
401 475
476GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
477GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */
478
402/* 479/*
403 * Global transaction id (XID) information 480 * Global transaction id (XID) information
404 */ 481 */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index aede6a813167..cf466595b0d4 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -36,9 +36,11 @@
36#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ 36#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
37#define SMB_COM_DELETE 0x06 /* trivial response */ 37#define SMB_COM_DELETE 0x06 /* trivial response */
38#define SMB_COM_RENAME 0x07 /* trivial response */ 38#define SMB_COM_RENAME 0x07 /* trivial response */
39#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
39#define SMB_COM_SETATTR 0x09 /* trivial response */ 40#define SMB_COM_SETATTR 0x09 /* trivial response */
40#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ 41#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
41#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ 42#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
43#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
42#define SMB_COM_READ_ANDX 0x2E 44#define SMB_COM_READ_ANDX 0x2E
43#define SMB_COM_WRITE_ANDX 0x2F 45#define SMB_COM_WRITE_ANDX 0x2F
44#define SMB_COM_TRANSACTION2 0x32 46#define SMB_COM_TRANSACTION2 0x32
@@ -52,6 +54,7 @@
52#define SMB_COM_NT_TRANSACT 0xA0 54#define SMB_COM_NT_TRANSACT 0xA0
53#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 55#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
54#define SMB_COM_NT_CREATE_ANDX 0xA2 56#define SMB_COM_NT_CREATE_ANDX 0xA2
57#define SMB_COM_NT_CANCEL 0xA4 /* no response */
55#define SMB_COM_NT_RENAME 0xA5 /* trivial response */ 58#define SMB_COM_NT_RENAME 0xA5 /* trivial response */
56 59
57/* Transact2 subcommand codes */ 60/* Transact2 subcommand codes */
@@ -59,6 +62,7 @@
59#define TRANS2_FIND_FIRST 0x01 62#define TRANS2_FIND_FIRST 0x01
60#define TRANS2_FIND_NEXT 0x02 63#define TRANS2_FIND_NEXT 0x02
61#define TRANS2_QUERY_FS_INFORMATION 0x03 64#define TRANS2_QUERY_FS_INFORMATION 0x03
65#define TRANS2_SET_FS_INFORMATION 0x04
62#define TRANS2_QUERY_PATH_INFORMATION 0x05 66#define TRANS2_QUERY_PATH_INFORMATION 0x05
63#define TRANS2_SET_PATH_INFORMATION 0x06 67#define TRANS2_SET_PATH_INFORMATION 0x06
64#define TRANS2_QUERY_FILE_INFORMATION 0x07 68#define TRANS2_QUERY_FILE_INFORMATION 0x07
@@ -267,10 +271,18 @@
267/* CreateOptions */ 271/* CreateOptions */
268#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ 272#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
269#define CREATE_WRITE_THROUGH 0x00000002 273#define CREATE_WRITE_THROUGH 0x00000002
270#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ 274#define CREATE_SEQUENTIAL 0x00000004
275#define CREATE_SYNC_ALERT 0x00000010
276#define CREATE_ASYNC_ALERT 0x00000020
277#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
278#define CREATE_NO_EA_KNOWLEDGE 0x00000200
279#define CREATE_EIGHT_DOT_THREE 0x00000400
271#define CREATE_RANDOM_ACCESS 0x00000800 280#define CREATE_RANDOM_ACCESS 0x00000800
272#define CREATE_DELETE_ON_CLOSE 0x00001000 281#define CREATE_DELETE_ON_CLOSE 0x00001000
282#define CREATE_OPEN_BY_ID 0x00002000
273#define OPEN_REPARSE_POINT 0x00200000 283#define OPEN_REPARSE_POINT 0x00200000
284#define CREATE_OPTIONS_MASK 0x007FFFFF
285#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
274 286
275/* ImpersonationLevel flags */ 287/* ImpersonationLevel flags */
276#define SECURITY_ANONYMOUS 0 288#define SECURITY_ANONYMOUS 0
@@ -614,6 +626,7 @@ typedef struct smb_com_findclose_req {
614} FINDCLOSE_REQ; 626} FINDCLOSE_REQ;
615 627
616/* OpenFlags */ 628/* OpenFlags */
629#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
617#define REQ_OPLOCK 0x00000002 630#define REQ_OPLOCK 0x00000002
618#define REQ_BATCHOPLOCK 0x00000004 631#define REQ_BATCHOPLOCK 0x00000004
619#define REQ_OPENDIRONLY 0x00000008 632#define REQ_OPENDIRONLY 0x00000008
@@ -669,6 +682,62 @@ typedef struct smb_com_open_rsp {
669 __u16 ByteCount; /* bct = 0 */ 682 __u16 ByteCount; /* bct = 0 */
670} OPEN_RSP; 683} OPEN_RSP;
671 684
685/* format of legacy open request */
686typedef struct smb_com_openx_req {
687 struct smb_hdr hdr; /* wct = 15 */
688 __u8 AndXCommand;
689 __u8 AndXReserved;
690 __le16 AndXOffset;
691 __le16 OpenFlags;
692 __le16 Mode;
693 __le16 Sattr; /* search attributes */
694 __le16 FileAttributes; /* dos attrs */
695 __le32 CreateTime; /* os2 format */
696 __le16 OpenFunction;
697 __le32 EndOfFile;
698 __le32 Timeout;
699 __le32 Reserved;
700 __u16 ByteCount; /* file name follows */
701 char fileName[1];
702} OPENX_REQ;
703
704typedef struct smb_com_openx_rsp {
705 struct smb_hdr hdr; /* wct = 15 */
706 __u8 AndXCommand;
707 __u8 AndXReserved;
708 __le16 AndXOffset;
709 __u16 Fid;
710 __le16 FileAttributes;
711 __le32 LastWriteTime; /* os2 format */
712 __le32 EndOfFile;
713 __le16 Access;
714 __le16 FileType;
715 __le16 IPCState;
716 __le16 Action;
717 __u32 FileId;
718 __u16 Reserved;
719 __u16 ByteCount;
720} OPENX_RSP;
721
722/* Legacy write request for older servers */
723typedef struct smb_com_writex_req {
724 struct smb_hdr hdr; /* wct = 12 */
725 __u8 AndXCommand;
726 __u8 AndXReserved;
727 __le16 AndXOffset;
728 __u16 Fid;
729 __le32 OffsetLow;
730 __u32 Reserved; /* Timeout */
731 __le16 WriteMode; /* 1 = write through */
732 __le16 Remaining;
733 __le16 Reserved2;
734 __le16 DataLengthLow;
735 __le16 DataOffset;
736 __le16 ByteCount;
737 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
738 char Data[0];
739} WRITEX_REQ;
740
672typedef struct smb_com_write_req { 741typedef struct smb_com_write_req {
673 struct smb_hdr hdr; /* wct = 14 */ 742 struct smb_hdr hdr; /* wct = 14 */
674 __u8 AndXCommand; 743 __u8 AndXCommand;
@@ -700,6 +769,21 @@ typedef struct smb_com_write_rsp {
700 __u16 ByteCount; 769 __u16 ByteCount;
701} WRITE_RSP; 770} WRITE_RSP;
702 771
772/* legacy read request for older servers */
773typedef struct smb_com_readx_req {
774 struct smb_hdr hdr; /* wct = 10 */
775 __u8 AndXCommand;
776 __u8 AndXReserved;
777 __le16 AndXOffset;
778 __u16 Fid;
779 __le32 OffsetLow;
780 __le16 MaxCount;
781 __le16 MinCount; /* obsolete */
782 __le32 Reserved;
783 __le16 Remaining;
784 __le16 ByteCount;
785} READX_REQ;
786
703typedef struct smb_com_read_req { 787typedef struct smb_com_read_req {
704 struct smb_hdr hdr; /* wct = 12 */ 788 struct smb_hdr hdr; /* wct = 12 */
705 __u8 AndXCommand; 789 __u8 AndXCommand;
@@ -876,6 +960,22 @@ typedef struct smb_com_create_directory_rsp {
876 __u16 ByteCount; /* bct = 0 */ 960 __u16 ByteCount; /* bct = 0 */
877} CREATE_DIRECTORY_RSP; 961} CREATE_DIRECTORY_RSP;
878 962
963typedef struct smb_com_query_information_req {
964 struct smb_hdr hdr; /* wct = 0 */
965 __le16 ByteCount; /* 1 + namelen + 1 */
966 __u8 BufferFormat; /* 4 = ASCII */
967 unsigned char FileName[1];
968} QUERY_INFORMATION_REQ;
969
970typedef struct smb_com_query_information_rsp {
971 struct smb_hdr hdr; /* wct = 10 */
972 __le16 attr;
973 __le32 last_write_time;
974 __le32 size;
975 __u16 reserved[5];
976 __le16 ByteCount; /* bcc = 0 */
977} QUERY_INFORMATION_RSP;
978
879typedef struct smb_com_setattr_req { 979typedef struct smb_com_setattr_req {
880 struct smb_hdr hdr; /* wct = 8 */ 980 struct smb_hdr hdr; /* wct = 8 */
881 __le16 attr; 981 __le16 attr;
@@ -1411,6 +1511,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
1411 __u8 Pad; /* may be three bytes *//* followed by data area */ 1511 __u8 Pad; /* may be three bytes *//* followed by data area */
1412} TRANSACTION2_QFSI_RSP; 1512} TRANSACTION2_QFSI_RSP;
1413 1513
1514
1515/* SETFSInfo Levels */
1516#define SMB_SET_CIFS_UNIX_INFO 0x200
1517typedef struct smb_com_transaction2_setfsi_req {
1518 struct smb_hdr hdr; /* wct = 15 */
1519 __le16 TotalParameterCount;
1520 __le16 TotalDataCount;
1521 __le16 MaxParameterCount;
1522 __le16 MaxDataCount;
1523 __u8 MaxSetupCount;
1524 __u8 Reserved;
1525 __le16 Flags;
1526 __le32 Timeout;
1527 __u16 Reserved2;
1528 __le16 ParameterCount; /* 4 */
1529 __le16 ParameterOffset;
1530 __le16 DataCount; /* 12 */
1531 __le16 DataOffset;
1532 __u8 SetupCount; /* one */
1533 __u8 Reserved3;
1534 __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
1535 __le16 ByteCount;
1536 __u8 Pad;
1537 __u16 FileNum; /* Parameters start. */
1538 __le16 InformationLevel;/* Parameters end. */
1539 __le16 ClientUnixMajor; /* Data start. */
1540 __le16 ClientUnixMinor;
1541 __le64 ClientUnixCap; /* Data end */
1542} TRANSACTION2_SETFSI_REQ;
1543
1544typedef struct smb_com_transaction2_setfsi_rsp {
1545 struct smb_hdr hdr; /* wct = 10 */
1546 struct trans2_resp t2;
1547 __u16 ByteCount;
1548} TRANSACTION2_SETFSI_RSP;
1549
1550
1414typedef struct smb_com_transaction2_get_dfs_refer_req { 1551typedef struct smb_com_transaction2_get_dfs_refer_req {
1415 struct smb_hdr hdr; /* wct = 15 */ 1552 struct smb_hdr hdr; /* wct = 15 */
1416 __le16 TotalParameterCount; 1553 __le16 TotalParameterCount;
@@ -1551,12 +1688,20 @@ typedef struct {
1551 __le16 MinorVersionNumber; 1688 __le16 MinorVersionNumber;
1552 __le64 Capability; 1689 __le64 Capability;
1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1690} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1691
1692/* Version numbers for CIFS UNIX major and minor. */
1693#define CIFS_UNIX_MAJOR_VERSION 1
1694#define CIFS_UNIX_MINOR_VERSION 0
1695
1554/* Linux/Unix extensions capability flags */ 1696/* Linux/Unix extensions capability flags */
1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1697#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1698#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1699#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1700#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1701#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
1702
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1703#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1704
1560typedef struct { 1705typedef struct {
1561 /* For undefined recommended transfer size return -1 in that field */ 1706 /* For undefined recommended transfer size return -1 in that field */
1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1707 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
@@ -1907,18 +2052,17 @@ struct data_blob {
1907 perhaps add a CreateDevice - to create Pipes and other special .inodes 2052 perhaps add a CreateDevice - to create Pipes and other special .inodes
1908 Also note POSIX open flags 2053 Also note POSIX open flags
1909 2) Close - to return the last write time to do cache across close more safely 2054 2) Close - to return the last write time to do cache across close more safely
1910 3) PosixQFSInfo - to return statfs info 2055 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) 2056 forms short (matches readdir) and full (enough info to cache inodes)
1912 5) Mkdir - set mode 2057 4) Mkdir - set mode
1913 2058
1914 And under consideration: 2059 And under consideration:
1915 6) FindClose2 (return nanosecond timestamp ??) 2060 5) FindClose2 (return nanosecond timestamp ??)
1916 7) Use nanosecond timestamps throughout all time fields if 2061 6) Use nanosecond timestamps throughout all time fields if
1917 corresponding attribute flag is set 2062 corresponding attribute flag is set
1918 8) sendfile - handle based copy 2063 7) sendfile - handle based copy
1919 9) Direct i/o 2064 8) Direct i/o
1920 10) "POSIX ACL" support 2065 9) Misc fcntls?
1921 11) Misc fcntls?
1922 2066
1923 what about fixing 64 bit alignment 2067 what about fixing 64 bit alignment
1924 2068
@@ -1974,7 +2118,7 @@ struct data_blob {
1974 2118
1975 */ 2119 */
1976 2120
1977/* xsymlink is a symlink format that can be used 2121/* xsymlink is a symlink format (used by MacOS) that can be used
1978 to save symlink info in a regular file when 2122 to save symlink info in a regular file when
1979 mounted to operating systems that do not 2123 mounted to operating systems that do not
1980 support the cifs Unix extensions or EAs (for xattr 2124 support the cifs Unix extensions or EAs (for xattr
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ea239dea571e..6943f7c6de08 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -47,6 +47,10 @@ 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 smb_hdr * /* input */ , int hdr_len,
52 const char * /* SMB data to send */ , int data_len,
53 int * /* bytes returned */ , const int long_op);
50extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 54extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
51extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 55extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
52extern int is_valid_oplock_break(struct smb_hdr *smb); 56extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -57,9 +61,9 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
57extern int cifs_inet_pton(int, char * source, void *dst); 61extern int cifs_inet_pton(int, char * source, void *dst);
58extern int map_smb_to_linux_error(struct smb_hdr *smb); 62extern int map_smb_to_linux_error(struct smb_hdr *smb);
59extern void header_assemble(struct smb_hdr *, char /* command */ , 63extern void header_assemble(struct smb_hdr *, char /* command */ ,
60 const struct cifsTconInfo *, int /* specifies length 64 const struct cifsTconInfo *, int /* length of
61 of fixed section (word count) in two byte units */ 65 fixed section (word count) in two byte units */);
62 ); 66extern __u16 GetNextMid(struct TCP_Server_Info *server);
63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 67extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
64 struct cifsTconInfo *); 68 struct cifsTconInfo *);
65extern void DeleteOplockQEntry(struct oplock_q_entry *); 69extern void DeleteOplockQEntry(struct oplock_q_entry *);
@@ -89,7 +93,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
89 93
90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 94extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
91 const char *searchName, const struct nls_table *nls_codepage, 95 const char *searchName, const struct nls_table *nls_codepage,
92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map); 96 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
93 97
94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 98extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
95 __u16 searchHandle, struct cifs_search_info * psrch_inf); 99 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -101,6 +105,10 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
101 const unsigned char *searchName, 105 const unsigned char *searchName,
102 FILE_ALL_INFO * findData, 106 FILE_ALL_INFO * findData,
103 const struct nls_table *nls_codepage, int remap); 107 const struct nls_table *nls_codepage, int remap);
108extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
109 const unsigned char *searchName,
110 FILE_ALL_INFO * findData,
111 const struct nls_table *nls_codepage, int remap);
104 112
105extern int CIFSSMBUnixQPathInfo(const int xid, 113extern int CIFSSMBUnixQPathInfo(const int xid,
106 struct cifsTconInfo *tcon, 114 struct cifsTconInfo *tcon,
@@ -125,6 +133,9 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
125 int remap); 133 int remap);
126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 134extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
127 struct kstatfs *FSData); 135 struct kstatfs *FSData);
136extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
137 __u64 cap);
138
128extern int CIFSSMBQFSAttributeInfo(const int xid, 139extern int CIFSSMBQFSAttributeInfo(const int xid,
129 struct cifsTconInfo *tcon); 140 struct cifsTconInfo *tcon);
130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); 141extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
@@ -207,6 +218,11 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
207 const int access_flags, const int omode, 218 const int access_flags, const int omode,
208 __u16 * netfid, int *pOplock, FILE_ALL_INFO *, 219 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
209 const struct nls_table *nls_codepage, int remap); 220 const struct nls_table *nls_codepage, int remap);
221extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
222 const char *fileName, const int disposition,
223 const int access_flags, const int omode,
224 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
225 const struct nls_table *nls_codepage, int remap);
210extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 226extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
211 const int smb_file_id); 227 const int smb_file_id);
212 228
@@ -222,7 +238,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
222extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 238extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
223 const int netfid, const unsigned int count, 239 const int netfid, const unsigned int count,
224 const __u64 offset, unsigned int *nbytes, 240 const __u64 offset, unsigned int *nbytes,
225 const char __user *buf,const int long_op); 241 const char *buf,const int long_op);
226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 242extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
227 const unsigned char *searchName, __u64 * inode_number, 243 const unsigned char *searchName, __u64 * inode_number,
228 const struct nls_table *nls_codepage, 244 const struct nls_table *nls_codepage,
@@ -264,7 +280,8 @@ extern int CIFSSMBCopy(int xid,
264 int remap_special_chars); 280 int remap_special_chars);
265extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 281extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
266 const int notify_subdirs,const __u16 netfid, 282 const int notify_subdirs,const __u16 netfid,
267 __u32 filter, const struct nls_table *nls_codepage); 283 __u32 filter, struct file * file, int multishot,
284 const struct nls_table *nls_codepage);
268extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 285extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
269 const unsigned char *searchName, char * EAData, 286 const unsigned char *searchName, char * EAData,
270 size_t bufsize, const struct nls_table *nls_codepage, 287 size_t bufsize, const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..b8830118f09a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -166,11 +166,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
166 166
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); 167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168 168
169#ifdef CONFIG_CIFS_STATS 169 if(tcon != NULL)
170 if(tcon != NULL) { 170 cifs_stats_inc(&tcon->num_smbs_sent);
171 atomic_inc(&tcon->num_smbs_sent); 171
172 }
173#endif /* CONFIG_CIFS_STATS */
174 return rc; 172 return rc;
175} 173}
176 174
@@ -269,11 +267,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 267 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
270 wct /*wct */ ); 268 wct /*wct */ );
271 269
272#ifdef CONFIG_CIFS_STATS 270 if(tcon != NULL)
273 if(tcon != NULL) { 271 cifs_stats_inc(&tcon->num_smbs_sent);
274 atomic_inc(&tcon->num_smbs_sent); 272
275 }
276#endif /* CONFIG_CIFS_STATS */
277 return rc; 273 return rc;
278} 274}
279 275
@@ -330,7 +326,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
330 (void **) &pSMB, (void **) &pSMBr); 326 (void **) &pSMB, (void **) &pSMBr);
331 if (rc) 327 if (rc)
332 return rc; 328 return rc;
333 329 pSMB->hdr.Mid = GetNextMid(server);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 330 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security) 331 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 332 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -422,8 +418,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
422 } 418 }
423 419
424 } 420 }
425 if (pSMB) 421
426 cifs_buf_release(pSMB); 422 cifs_buf_release(pSMB);
427 return rc; 423 return rc;
428} 424}
429 425
@@ -518,6 +514,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ 514 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
519 515
520 if(ses->server) { 516 if(ses->server) {
517 pSMB->hdr.Mid = GetNextMid(ses->server);
518
521 if(ses->server->secMode & 519 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 520 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 521 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -537,9 +535,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
537 rc = -ESHUTDOWN; 535 rc = -ESHUTDOWN;
538 } 536 }
539 } 537 }
540 if (pSMB)
541 cifs_small_buf_release(pSMB);
542 up(&ses->sesSem); 538 up(&ses->sesSem);
539 cifs_small_buf_release(pSMB);
543 540
544 /* if session dead then we do not need to do ulogoff, 541 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting 542 since server closed smb session, no sense reporting
@@ -583,14 +580,10 @@ DelFileRetry:
583 pSMB->ByteCount = cpu_to_le16(name_len + 1); 580 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
583 cifs_stats_inc(&tcon->num_deletes);
586 if (rc) { 584 if (rc) {
587 cFYI(1, ("Error in RMFile = %d", rc)); 585 cFYI(1, ("Error in RMFile = %d", rc));
588 } 586 }
589#ifdef CONFIG_CIFS_STATS
590 else {
591 atomic_inc(&tcon->num_deletes);
592 }
593#endif
594 587
595 cifs_buf_release(pSMB); 588 cifs_buf_release(pSMB);
596 if (rc == -EAGAIN) 589 if (rc == -EAGAIN)
@@ -632,14 +625,10 @@ RmDirRetry:
632 pSMB->ByteCount = cpu_to_le16(name_len + 1); 625 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
628 cifs_stats_inc(&tcon->num_rmdirs);
635 if (rc) { 629 if (rc) {
636 cFYI(1, ("Error in RMDir = %d", rc)); 630 cFYI(1, ("Error in RMDir = %d", rc));
637 } 631 }
638#ifdef CONFIG_CIFS_STATS
639 else {
640 atomic_inc(&tcon->num_rmdirs);
641 }
642#endif
643 632
644 cifs_buf_release(pSMB); 633 cifs_buf_release(pSMB);
645 if (rc == -EAGAIN) 634 if (rc == -EAGAIN)
@@ -680,20 +669,157 @@ MkDirRetry:
680 pSMB->ByteCount = cpu_to_le16(name_len + 1); 669 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
672 cifs_stats_inc(&tcon->num_mkdirs);
683 if (rc) { 673 if (rc) {
684 cFYI(1, ("Error in Mkdir = %d", rc)); 674 cFYI(1, ("Error in Mkdir = %d", rc));
685 } 675 }
686#ifdef CONFIG_CIFS_STATS 676
687 else {
688 atomic_inc(&tcon->num_mkdirs);
689 }
690#endif
691 cifs_buf_release(pSMB); 677 cifs_buf_release(pSMB);
692 if (rc == -EAGAIN) 678 if (rc == -EAGAIN)
693 goto MkDirRetry; 679 goto MkDirRetry;
694 return rc; 680 return rc;
695} 681}
696 682
683static __u16 convert_disposition(int disposition)
684{
685 __u16 ofun = 0;
686
687 switch (disposition) {
688 case FILE_SUPERSEDE:
689 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
690 break;
691 case FILE_OPEN:
692 ofun = SMBOPEN_OAPPEND;
693 break;
694 case FILE_CREATE:
695 ofun = SMBOPEN_OCREATE;
696 break;
697 case FILE_OPEN_IF:
698 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
699 break;
700 case FILE_OVERWRITE:
701 ofun = SMBOPEN_OTRUNC;
702 break;
703 case FILE_OVERWRITE_IF:
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
705 break;
706 default:
707 cFYI(1,("unknown disposition %d",disposition));
708 ofun = SMBOPEN_OAPPEND; /* regular open */
709 }
710 return ofun;
711}
712
713int
714SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
715 const char *fileName, const int openDisposition,
716 const int access_flags, const int create_options, __u16 * netfid,
717 int *pOplock, FILE_ALL_INFO * pfile_info,
718 const struct nls_table *nls_codepage, int remap)
719{
720 int rc = -EACCES;
721 OPENX_REQ *pSMB = NULL;
722 OPENX_RSP *pSMBr = NULL;
723 int bytes_returned;
724 int name_len;
725 __u16 count;
726
727OldOpenRetry:
728 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
729 (void **) &pSMBr);
730 if (rc)
731 return rc;
732
733 pSMB->AndXCommand = 0xFF; /* none */
734
735 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
736 count = 1; /* account for one byte pad to word boundary */
737 name_len =
738 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
739 fileName, PATH_MAX, nls_codepage, remap);
740 name_len++; /* trailing null */
741 name_len *= 2;
742 } else { /* BB improve check for buffer overruns BB */
743 count = 0; /* no pad */
744 name_len = strnlen(fileName, PATH_MAX);
745 name_len++; /* trailing null */
746 strncpy(pSMB->fileName, fileName, name_len);
747 }
748 if (*pOplock & REQ_OPLOCK)
749 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
750 else if (*pOplock & REQ_BATCHOPLOCK) {
751 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
752 }
753 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
754 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
755 /* 0 = read
756 1 = write
757 2 = rw
758 3 = execute
759 */
760 pSMB->Mode = cpu_to_le16(2);
761 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
762 /* set file as system file if special file such
763 as fifo and server expecting SFU style and
764 no Unix extensions */
765
766 if(create_options & CREATE_OPTION_SPECIAL)
767 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
768 else
769 pSMB->FileAttributes = cpu_to_le16(ATTR_NORMAL);
770
771 /* if ((omode & S_IWUGO) == 0)
772 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
773 /* Above line causes problems due to vfs splitting create into two
774 pieces - need to set mode after file created not while it is
775 being created */
776
777 /* BB FIXME BB */
778/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
779 /* BB FIXME END BB */
780 pSMB->OpenFunction = convert_disposition(openDisposition);
781 count += name_len;
782 pSMB->hdr.smb_buf_length += count;
783
784 pSMB->ByteCount = cpu_to_le16(count);
785 /* long_op set to 1 to allow for oplock break timeouts */
786 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
787 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
788 cifs_stats_inc(&tcon->num_opens);
789 if (rc) {
790 cFYI(1, ("Error in Open = %d", rc));
791 } else {
792 /* BB verify if wct == 15 */
793
794/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
795
796 *netfid = pSMBr->Fid; /* cifs fid stays in le */
797 /* Let caller know file was created so we can set the mode. */
798 /* Do we care about the CreateAction in any other cases? */
799 /* BB FIXME BB */
800/* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
801 *pOplock |= CIFS_CREATE_ACTION; */
802 /* BB FIXME END */
803
804 if(pfile_info) {
805 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
806 pfile_info->LastAccessTime = 0; /* BB fixme */
807 pfile_info->LastWriteTime = 0; /* BB fixme */
808 pfile_info->ChangeTime = 0; /* BB fixme */
809 pfile_info->Attributes = pSMBr->FileAttributes;
810 /* the file_info buf is endian converted by caller */
811 pfile_info->AllocationSize = pSMBr->EndOfFile;
812 pfile_info->EndOfFile = pSMBr->EndOfFile;
813 pfile_info->NumberOfLinks = cpu_to_le32(1);
814 }
815 }
816
817 cifs_buf_release(pSMB);
818 if (rc == -EAGAIN)
819 goto OldOpenRetry;
820 return rc;
821}
822
697int 823int
698CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, 824CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition, 825 const char *fileName, const int openDisposition,
@@ -738,7 +864,13 @@ openRetry:
738 } 864 }
739 pSMB->DesiredAccess = cpu_to_le32(access_flags); 865 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0; 866 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 867 /* set file as system file if special file such
868 as fifo and server expecting SFU style and
869 no Unix extensions */
870 if(create_options & CREATE_OPTION_SPECIAL)
871 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
872 else
873 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */ 874 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other 875 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */ 876 servers such as Samba */
@@ -752,7 +884,7 @@ openRetry:
752 being created */ 884 being created */
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 885 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 886 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options); 887 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
756 /* BB Expirement with various impersonation levels and verify */ 888 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 889 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags = 890 pSMB->SecurityFlags =
@@ -765,6 +897,7 @@ openRetry:
765 /* long_op set to 1 to allow for oplock break timeouts */ 897 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1); 899 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
900 cifs_stats_inc(&tcon->num_opens);
768 if (rc) { 901 if (rc) {
769 cFYI(1, ("Error in Open = %d", rc)); 902 cFYI(1, ("Error in Open = %d", rc));
770 } else { 903 } else {
@@ -782,11 +915,8 @@ openRetry:
782 pfile_info->EndOfFile = pSMBr->EndOfFile; 915 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1); 916 pfile_info->NumberOfLinks = cpu_to_le32(1);
784 } 917 }
785
786#ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
788#endif
789 } 918 }
919
790 cifs_buf_release(pSMB); 920 cifs_buf_release(pSMB);
791 if (rc == -EAGAIN) 921 if (rc == -EAGAIN)
792 goto openRetry; 922 goto openRetry;
@@ -807,11 +937,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
807 READ_RSP *pSMBr = NULL; 937 READ_RSP *pSMBr = NULL;
808 char *pReadData = NULL; 938 char *pReadData = NULL;
809 int bytes_returned; 939 int bytes_returned;
940 int wct;
810 941
811 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 942 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
943 if(tcon->ses->capabilities & CAP_LARGE_FILES)
944 wct = 12;
945 else
946 wct = 10; /* old style read */
812 947
813 *nbytes = 0; 948 *nbytes = 0;
814 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, 949 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
815 (void **) &pSMBr); 950 (void **) &pSMBr);
816 if (rc) 951 if (rc)
817 return rc; 952 return rc;
@@ -823,14 +958,26 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
823 pSMB->AndXCommand = 0xFF; /* none */ 958 pSMB->AndXCommand = 0xFF; /* none */
824 pSMB->Fid = netfid; 959 pSMB->Fid = netfid;
825 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 960 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
826 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 961 if(wct == 12)
962 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
963 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
964 return -EIO;
965
827 pSMB->Remaining = 0; 966 pSMB->Remaining = 0;
828 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 967 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
829 pSMB->MaxCountHigh = cpu_to_le32(count >> 16); 968 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
830 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ 969 if(wct == 12)
831 970 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
971 else {
972 /* old style read */
973 struct smb_com_readx_req * pSMBW =
974 (struct smb_com_readx_req *)pSMB;
975 pSMBW->ByteCount = 0;
976 }
977
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
980 cifs_stats_inc(&tcon->num_reads);
834 if (rc) { 981 if (rc) {
835 cERROR(1, ("Send error in read = %d", rc)); 982 cERROR(1, ("Send error in read = %d", rc));
836 } else { 983 } else {
@@ -876,12 +1023,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
876 int rc = -EACCES; 1023 int rc = -EACCES;
877 WRITE_REQ *pSMB = NULL; 1024 WRITE_REQ *pSMB = NULL;
878 WRITE_RSP *pSMBr = NULL; 1025 WRITE_RSP *pSMBr = NULL;
879 int bytes_returned; 1026 int bytes_returned, wct;
880 __u32 bytes_sent; 1027 __u32 bytes_sent;
881 __u16 byte_count; 1028 __u16 byte_count;
882 1029
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/ 1030 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, 1031 if(tcon->ses == NULL)
1032 return -ECONNABORTED;
1033
1034 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1035 wct = 14;
1036 else
1037 wct = 12;
1038
1039 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
885 (void **) &pSMBr); 1040 (void **) &pSMBr);
886 if (rc) 1041 if (rc)
887 return rc; 1042 return rc;
@@ -892,7 +1047,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
892 pSMB->AndXCommand = 0xFF; /* none */ 1047 pSMB->AndXCommand = 0xFF; /* none */
893 pSMB->Fid = netfid; 1048 pSMB->Fid = netfid;
894 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1049 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
895 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1050 if(wct == 14)
1051 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1052 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1053 return -EIO;
1054
896 pSMB->Reserved = 0xFFFFFFFF; 1055 pSMB->Reserved = 0xFFFFFFFF;
897 pSMB->WriteMode = 0; 1056 pSMB->WriteMode = 0;
898 pSMB->Remaining = 0; 1057 pSMB->Remaining = 0;
@@ -929,10 +1088,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
929 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); 1088 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
930 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); 1089 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
931 pSMB->hdr.smb_buf_length += bytes_sent+1; 1090 pSMB->hdr.smb_buf_length += bytes_sent+1;
932 pSMB->ByteCount = cpu_to_le16(byte_count); 1091
1092 if(wct == 14)
1093 pSMB->ByteCount = cpu_to_le16(byte_count);
1094 else { /* old style write has byte count 4 bytes earlier */
1095 struct smb_com_writex_req * pSMBW =
1096 (struct smb_com_writex_req *)pSMB;
1097 pSMBW->ByteCount = cpu_to_le16(byte_count);
1098 }
933 1099
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op); 1101 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1102 cifs_stats_inc(&tcon->num_writes);
936 if (rc) { 1103 if (rc) {
937 cFYI(1, ("Send error in write = %d", rc)); 1104 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = 0; 1105 *nbytes = 0;
@@ -951,56 +1118,70 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 1118}
952 1119
953#ifdef CONFIG_CIFS_EXPERIMENTAL 1120#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1121int
1122CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 1123 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 1124 const __u64 offset, unsigned int *nbytes, const char *buf,
957 const int long_op) 1125 const int long_op)
958{ 1126{
959 int rc = -EACCES; 1127 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 1128 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 1129 int bytes_returned;
962 /*int bytes_returned;*/ 1130 int smb_hdr_len;
963 unsigned bytes_sent; 1131 __u32 bytes_sent;
964 __u16 byte_count; 1132 __u16 byte_count;
965 1133
1134 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 1135 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
967
968 if (rc) 1136 if (rc)
969 return rc; 1137 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 1138 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 1139 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 1140 return -ECONNABORTED;
976 1141
977 pSMB->AndXCommand = 0xFF; /* none */ 1142 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 1143 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1144 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1145 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
981 pSMB->Reserved = 0xFFFFFFFF; 1146 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 1147 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 1148 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 1149
1150 /* Can increase buffer size if buffer is big enough in some cases - ie
1151 can send more if LARGE_WRITE_X capability returned by the server and if
1152 our buffer is big enough or if we convert to iovecs on socket writes
1153 and eliminate the copy to the CIFS buffer */
1154 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1155 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1156 } else {
1157 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1158 & ~0xFF;
1159 }
1160
985 if (bytes_sent > count) 1161 if (bytes_sent > count)
986 bytes_sent = count; 1162 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1163 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1164 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1165
991 byte_count = bytes_sent + 1 /* pad */ ; 1166 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1167 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
993 pSMB->DataLengthHigh = 0; 1168 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
994 pSMB->hdr.smb_buf_length += byte_count; 1169 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1170 pSMB->hdr.smb_buf_length += bytes_sent+1;
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1171 pSMB->ByteCount = cpu_to_le16(byte_count);
996 1172
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1173 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ 1174 buf, bytes_sent, &bytes_returned, long_op);
1175 cifs_stats_inc(&tcon->num_writes);
999 if (rc) { 1176 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1177 cFYI(1, ("Send error in write = %d", rc));
1001 *nbytes = 0; 1178 *nbytes = 0;
1002 } else 1179 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1180 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1181 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1182 *nbytes = (*nbytes) << 16;
1183 *nbytes += le16_to_cpu(pSMBr->Count);
1184 }
1004 1185
1005 cifs_small_buf_release(pSMB); 1186 cifs_small_buf_release(pSMB);
1006 1187
@@ -1009,6 +1190,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1190
1010 return rc; 1191 return rc;
1011} 1192}
1193
1194
1012#endif /* CIFS_EXPERIMENTAL */ 1195#endif /* CIFS_EXPERIMENTAL */
1013 1196
1014int 1197int
@@ -1065,7 +1248,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1065 1248
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1249 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1250 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 1251 cifs_stats_inc(&tcon->num_locks);
1069 if (rc) { 1252 if (rc) {
1070 cFYI(1, ("Send error in Lock = %d", rc)); 1253 cFYI(1, ("Send error in Lock = %d", rc));
1071 } 1254 }
@@ -1099,6 +1282,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1099 pSMB->ByteCount = 0; 1282 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1285 cifs_stats_inc(&tcon->num_closes);
1102 if (rc) { 1286 if (rc) {
1103 if(rc!=-EINTR) { 1287 if(rc!=-EINTR) {
1104 /* EINTR is expected when user ctl-c to kill app */ 1288 /* EINTR is expected when user ctl-c to kill app */
@@ -1171,16 +1355,11 @@ renameRetry:
1171 1355
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1356 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1357 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1358 cifs_stats_inc(&tcon->num_renames);
1174 if (rc) { 1359 if (rc) {
1175 cFYI(1, ("Send error in rename = %d", rc)); 1360 cFYI(1, ("Send error in rename = %d", rc));
1176 } 1361 }
1177 1362
1178#ifdef CONFIG_CIFS_STATS
1179 else {
1180 atomic_inc(&tcon->num_renames);
1181 }
1182#endif
1183
1184 cifs_buf_release(pSMB); 1363 cifs_buf_release(pSMB);
1185 1364
1186 if (rc == -EAGAIN) 1365 if (rc == -EAGAIN)
@@ -1255,14 +1434,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1255 pSMB->ByteCount = cpu_to_le16(byte_count); 1434 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, 1435 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1436 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1437 cifs_stats_inc(&pTcon->num_t2renames);
1258 if (rc) { 1438 if (rc) {
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc)); 1439 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1260 } 1440 }
1261#ifdef CONFIG_CIFS_STATS 1441
1262 else {
1263 atomic_inc(&pTcon->num_t2renames);
1264 }
1265#endif
1266 cifs_buf_release(pSMB); 1442 cifs_buf_release(pSMB);
1267 1443
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls 1444 /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -1416,6 +1592,7 @@ createSymLinkRetry:
1416 pSMB->ByteCount = cpu_to_le16(byte_count); 1592 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1593 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1594 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1595 cifs_stats_inc(&tcon->num_symlinks);
1419 if (rc) { 1596 if (rc) {
1420 cFYI(1, 1597 cFYI(1,
1421 ("Send error in SetPathInfo (create symlink) = %d", 1598 ("Send error in SetPathInfo (create symlink) = %d",
@@ -1505,6 +1682,7 @@ createHardLinkRetry:
1505 pSMB->ByteCount = cpu_to_le16(byte_count); 1682 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1683 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1684 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1685 cifs_stats_inc(&tcon->num_hardlinks);
1508 if (rc) { 1686 if (rc) {
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); 1687 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 } 1688 }
@@ -1575,6 +1753,7 @@ winCreateHardLinkRetry:
1575 1753
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1756 cifs_stats_inc(&tcon->num_hardlinks);
1578 if (rc) { 1757 if (rc) {
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); 1758 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1580 } 1759 }
@@ -1775,8 +1954,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1954 }
1776 } 1955 }
1777qreparse_out: 1956qreparse_out:
1778 if (pSMB) 1957 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1958
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1959 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 1960 since file handle passed in no longer valid */
@@ -2165,6 +2343,65 @@ GetExtAttrOut:
2165 2343
2166#endif /* CONFIG_POSIX */ 2344#endif /* CONFIG_POSIX */
2167 2345
2346/* Legacy Query Path Information call for lookup to old servers such
2347 as Win9x/WinME */
2348int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2349 const unsigned char *searchName,
2350 FILE_ALL_INFO * pFinfo,
2351 const struct nls_table *nls_codepage, int remap)
2352{
2353 QUERY_INFORMATION_REQ * pSMB;
2354 QUERY_INFORMATION_RSP * pSMBr;
2355 int rc = 0;
2356 int bytes_returned;
2357 int name_len;
2358
2359 cFYI(1, ("In SMBQPath path %s", searchName));
2360QInfRetry:
2361 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2362 (void **) &pSMBr);
2363 if (rc)
2364 return rc;
2365
2366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2367 name_len =
2368 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2369 PATH_MAX, nls_codepage, remap);
2370 name_len++; /* trailing null */
2371 name_len *= 2;
2372 } else {
2373 name_len = strnlen(searchName, PATH_MAX);
2374 name_len++; /* trailing null */
2375 strncpy(pSMB->FileName, searchName, name_len);
2376 }
2377 pSMB->BufferFormat = 0x04;
2378 name_len++; /* account for buffer type byte */
2379 pSMB->hdr.smb_buf_length += (__u16) name_len;
2380 pSMB->ByteCount = cpu_to_le16(name_len);
2381
2382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2384 if (rc) {
2385 cFYI(1, ("Send error in QueryInfo = %d", rc));
2386 } else if (pFinfo) { /* decode response */
2387 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2388 pFinfo->AllocationSize = (__le64) pSMBr->size;
2389 pFinfo->EndOfFile = (__le64) pSMBr->size;
2390 pFinfo->Attributes = (__le32) pSMBr->attr;
2391 } else
2392 rc = -EIO; /* bad buffer passed in */
2393
2394 cifs_buf_release(pSMB);
2395
2396 if (rc == -EAGAIN)
2397 goto QInfRetry;
2398
2399 return rc;
2400}
2401
2402
2403
2404
2168int 2405int
2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2406CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName, 2407 const unsigned char *searchName,
@@ -2396,7 +2633,7 @@ findUniqueRetry:
2396 if (rc) { 2633 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2634 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2635 } else { /* decode response */
2399 2636 cifs_stats_inc(&tcon->num_ffirst);
2400 /* BB fill in */ 2637 /* BB fill in */
2401 } 2638 }
2402 2639
@@ -2414,7 +2651,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2651 const char *searchName,
2415 const struct nls_table *nls_codepage, 2652 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2653 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2654 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2655{
2419/* level 257 SMB_ */ 2656/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2657 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2678,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2678 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2679 directory name instead of a wildcard */
2443 name_len *= 2; 2680 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2681 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2682 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2683 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2684 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2692,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2692 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2693 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2694 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2695 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2696 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2697 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2698 name_len += 3;
@@ -2496,6 +2733,7 @@ findFirstRetry:
2496 2733
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2734 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2735 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2736 cifs_stats_inc(&tcon->num_ffirst);
2499 2737
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2738 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 */ 2739 /* BB Add code to handle unsupported level rc */
@@ -2617,7 +2855,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2617 2855
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2857 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 2858 cifs_stats_inc(&tcon->num_fnext);
2621 if (rc) { 2859 if (rc) {
2622 if (rc == -EBADF) { 2860 if (rc == -EBADF) {
2623 psrch_inf->endOfSearch = TRUE; 2861 psrch_inf->endOfSearch = TRUE;
@@ -2694,6 +2932,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2932 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2933 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2934 }
2935 cifs_stats_inc(&tcon->num_fclose);
2697 cifs_small_buf_release(pSMB); 2936 cifs_small_buf_release(pSMB);
2698 2937
2699 /* Since session is dead, search handle closed on server already */ 2938 /* Since session is dead, search handle closed on server already */
@@ -2827,7 +3066,10 @@ getDFSRetry:
2827 (void **) &pSMBr); 3066 (void **) &pSMBr);
2828 if (rc) 3067 if (rc)
2829 return rc; 3068 return rc;
2830 3069
3070 /* server pointer checked in called function,
3071 but should never be null here anyway */
3072 pSMB->hdr.Mid = GetNextMid(ses->server);
2831 pSMB->hdr.Tid = ses->ipc_tid; 3073 pSMB->hdr.Tid = ses->ipc_tid;
2832 pSMB->hdr.Uid = ses->Suid; 3074 pSMB->hdr.Uid = ses->Suid;
2833 if (ses->capabilities & CAP_STATUS32) { 3075 if (ses->capabilities & CAP_STATUS32) {
@@ -3257,6 +3499,77 @@ QFSUnixRetry:
3257 return rc; 3499 return rc;
3258} 3500}
3259 3501
3502int
3503CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3504{
3505/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3506 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3507 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3508 int rc = 0;
3509 int bytes_returned = 0;
3510 __u16 params, param_offset, offset, byte_count;
3511
3512 cFYI(1, ("In SETFSUnixInfo"));
3513SETFSUnixRetry:
3514 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3515 (void **) &pSMBr);
3516 if (rc)
3517 return rc;
3518
3519 params = 4; /* 2 bytes zero followed by info level. */
3520 pSMB->MaxSetupCount = 0;
3521 pSMB->Reserved = 0;
3522 pSMB->Flags = 0;
3523 pSMB->Timeout = 0;
3524 pSMB->Reserved2 = 0;
3525 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3526 offset = param_offset + params;
3527
3528 pSMB->MaxParameterCount = cpu_to_le16(4);
3529 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3530 pSMB->SetupCount = 1;
3531 pSMB->Reserved3 = 0;
3532 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3533 byte_count = 1 /* pad */ + params + 12;
3534
3535 pSMB->DataCount = cpu_to_le16(12);
3536 pSMB->ParameterCount = cpu_to_le16(params);
3537 pSMB->TotalDataCount = pSMB->DataCount;
3538 pSMB->TotalParameterCount = pSMB->ParameterCount;
3539 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3540 pSMB->DataOffset = cpu_to_le16(offset);
3541
3542 /* Params. */
3543 pSMB->FileNum = 0;
3544 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3545
3546 /* Data. */
3547 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3548 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3549 pSMB->ClientUnixCap = cpu_to_le64(cap);
3550
3551 pSMB->hdr.smb_buf_length += byte_count;
3552 pSMB->ByteCount = cpu_to_le16(byte_count);
3553
3554 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3555 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3556 if (rc) {
3557 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3558 } else { /* decode response */
3559 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3560 if (rc) {
3561 rc = -EIO; /* bad smb */
3562 }
3563 }
3564 cifs_buf_release(pSMB);
3565
3566 if (rc == -EAGAIN)
3567 goto SETFSUnixRetry;
3568
3569 return rc;
3570}
3571
3572
3260 3573
3261int 3574int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3575CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3839,12 +4152,14 @@ setPermsRetry:
3839} 4152}
3840 4153
3841int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 4154int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3842 const int notify_subdirs, const __u16 netfid, 4155 const int notify_subdirs, const __u16 netfid,
3843 __u32 filter, const struct nls_table *nls_codepage) 4156 __u32 filter, struct file * pfile, int multishot,
4157 const struct nls_table *nls_codepage)
3844{ 4158{
3845 int rc = 0; 4159 int rc = 0;
3846 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4160 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3847 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4161 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4162 struct dir_notify_req *dnotify_req;
3848 int bytes_returned; 4163 int bytes_returned;
3849 4164
3850 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); 4165 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
@@ -3877,6 +4192,22 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, -1); 4192 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3878 if (rc) { 4193 if (rc) {
3879 cFYI(1, ("Error in Notify = %d", rc)); 4194 cFYI(1, ("Error in Notify = %d", rc));
4195 } else {
4196 /* Add file to outstanding requests */
4197 dnotify_req = (struct dir_notify_req *) kmalloc(
4198 sizeof(struct dir_notify_req), GFP_KERNEL);
4199 dnotify_req->Pid = pSMB->hdr.Pid;
4200 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4201 dnotify_req->Mid = pSMB->hdr.Mid;
4202 dnotify_req->Tid = pSMB->hdr.Tid;
4203 dnotify_req->Uid = pSMB->hdr.Uid;
4204 dnotify_req->netfid = netfid;
4205 dnotify_req->pfile = pfile;
4206 dnotify_req->filter = filter;
4207 dnotify_req->multishot = multishot;
4208 spin_lock(&GlobalMid_Lock);
4209 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4210 spin_unlock(&GlobalMid_Lock);
3880 } 4211 }
3881 cifs_buf_release(pSMB); 4212 cifs_buf_release(pSMB);
3882 return rc; 4213 return rc;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc47a7f9..196976049c00 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -29,6 +29,7 @@
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>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33#include <asm/processor.h> 34#include <asm/processor.h>
34#include "cifspdu.h" 35#include "cifspdu.h"
@@ -44,6 +45,8 @@
44#define CIFS_PORT 445 45#define CIFS_PORT 445
45#define RFC1001_PORT 139 46#define RFC1001_PORT 139
46 47
48static DECLARE_COMPLETION(cifsd_complete);
49
47extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, 50extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
48 unsigned char *p24); 51 unsigned char *p24);
49extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
@@ -60,6 +63,7 @@ struct smb_vol {
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */ 63 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */ 64 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */ 65 char source_rfc1001_name[16]; /* netbios name of client */
66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
63 uid_t linux_uid; 67 uid_t linux_uid;
64 gid_t linux_gid; 68 gid_t linux_gid;
65 mode_t file_mode; 69 mode_t file_mode;
@@ -74,6 +78,10 @@ struct smb_vol {
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 78 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
75 unsigned direct_io:1; 79 unsigned direct_io:1;
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 80 unsigned remap:1; /* set to remap seven reserved chars in filenames */
81 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
82 unsigned sfu_emul:1;
83 unsigned nocase; /* request case insensitive filenames */
84 unsigned nobrl; /* disable sending byte range locks to srv */
77 unsigned int rsize; 85 unsigned int rsize;
78 unsigned int wsize; 86 unsigned int wsize;
79 unsigned int sockopt; 87 unsigned int sockopt;
@@ -82,7 +90,8 @@ struct smb_vol {
82 90
83static int ipv4_connect(struct sockaddr_in *psin_server, 91static int ipv4_connect(struct sockaddr_in *psin_server,
84 struct socket **csocket, 92 struct socket **csocket,
85 char * netb_name); 93 char * netb_name,
94 char * server_netb_name);
86static int ipv6_connect(struct sockaddr_in6 *psin_server, 95static int ipv6_connect(struct sockaddr_in6 *psin_server,
87 struct socket **csocket); 96 struct socket **csocket);
88 97
@@ -175,7 +184,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
175 } else { 184 } else {
176 rc = ipv4_connect(&server->addr.sockAddr, 185 rc = ipv4_connect(&server->addr.sockAddr,
177 &server->ssocket, 186 &server->ssocket,
178 server->workstation_RFC1001_name); 187 server->workstation_RFC1001_name,
188 server->server_RFC1001_name);
179 } 189 }
180 if(rc) { 190 if(rc) {
181 msleep(3000); 191 msleep(3000);
@@ -337,6 +347,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
337 atomic_inc(&tcpSesAllocCount); 347 atomic_inc(&tcpSesAllocCount);
338 length = tcpSesAllocCount.counter; 348 length = tcpSesAllocCount.counter;
339 write_unlock(&GlobalSMBSeslock); 349 write_unlock(&GlobalSMBSeslock);
350 complete(&cifsd_complete);
340 if(length > 1) { 351 if(length > 1) {
341 mempool_resize(cifs_req_poolp, 352 mempool_resize(cifs_req_poolp,
342 length + cifs_min_rcv, 353 length + cifs_min_rcv,
@@ -344,6 +355,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
344 } 355 }
345 356
346 while (server->tcpStatus != CifsExiting) { 357 while (server->tcpStatus != CifsExiting) {
358 if(try_to_freeze())
359 continue;
347 if (bigbuf == NULL) { 360 if (bigbuf == NULL) {
348 bigbuf = cifs_buf_get(); 361 bigbuf = cifs_buf_get();
349 if(bigbuf == NULL) { 362 if(bigbuf == NULL) {
@@ -674,7 +687,7 @@ multi_t2_fnd:
674 msleep(125); 687 msleep(125);
675 } 688 }
676 689
677 if (list_empty(&server->pending_mid_q)) { 690 if (!list_empty(&server->pending_mid_q)) {
678 /* mpx threads have not exited yet give them 691 /* mpx threads have not exited yet give them
679 at least the smb send timeout time for long ops */ 692 at least the smb send timeout time for long ops */
680 /* due to delays on oplock break requests, we need 693 /* due to delays on oplock break requests, we need
@@ -711,7 +724,7 @@ multi_t2_fnd:
711 GFP_KERNEL); 724 GFP_KERNEL);
712 } 725 }
713 726
714 msleep(250); 727 complete_and_exit(&cifsd_complete, 0);
715 return 0; 728 return 0;
716} 729}
717 730
@@ -735,7 +748,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
735 toupper(system_utsname.nodename[i]); 748 toupper(system_utsname.nodename[i]);
736 } 749 }
737 vol->source_rfc1001_name[15] = 0; 750 vol->source_rfc1001_name[15] = 0;
738 751 /* null target name indicates to use *SMBSERVR default called name
752 if we end up sending RFC1001 session initialize */
753 vol->target_rfc1001_name[0] = 0;
739 vol->linux_uid = current->uid; /* current->euid instead? */ 754 vol->linux_uid = current->uid; /* current->euid instead? */
740 vol->linux_gid = current->gid; 755 vol->linux_gid = current->gid;
741 vol->dir_mode = S_IRWXUGO; 756 vol->dir_mode = S_IRWXUGO;
@@ -745,6 +760,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
745 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 760 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
746 vol->rw = TRUE; 761 vol->rw = TRUE;
747 762
763 /* default is always to request posix paths. */
764 vol->posix_paths = 1;
765
748 if (!options) 766 if (!options)
749 return 1; 767 return 1;
750 768
@@ -985,7 +1003,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
985 /* The string has 16th byte zero still from 1003 /* The string has 16th byte zero still from
986 set at top of the function */ 1004 set at top of the function */
987 if((i==15) && (value[i] != 0)) 1005 if((i==15) && (value[i] != 0))
988 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); 1006 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1007 }
1008 } else if (strnicmp(data, "servern", 7) == 0) {
1009 /* servernetbiosname specified override *SMBSERVER */
1010 if (!value || !*value || (*value == ' ')) {
1011 cFYI(1,("empty server netbiosname specified"));
1012 } else {
1013 /* last byte, type, is 0x20 for servr type */
1014 memset(vol->target_rfc1001_name,0x20,16);
1015
1016 for(i=0;i<15;i++) {
1017 /* BB are there cases in which a comma can be
1018 valid in this workstation netbios name (and need
1019 special handling)? */
1020
1021 /* user or mount helper must uppercase netbiosname */
1022 if (value[i]==0)
1023 break;
1024 else
1025 vol->target_rfc1001_name[i] = value[i];
1026 }
1027 /* The string has 16th byte zero still from
1028 set at top of the function */
1029 if((i==15) && (value[i] != 0))
1030 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
989 } 1031 }
990 } else if (strnicmp(data, "credentials", 4) == 0) { 1032 } else if (strnicmp(data, "credentials", 4) == 0) {
991 /* ignore */ 1033 /* ignore */
@@ -1023,6 +1065,27 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1023 vol->remap = 1; 1065 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1066 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0; 1067 vol->remap = 0;
1068 } else if (strnicmp(data, "sfu", 3) == 0) {
1069 vol->sfu_emul = 1;
1070 } else if (strnicmp(data, "nosfu", 5) == 0) {
1071 vol->sfu_emul = 0;
1072 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1073 vol->posix_paths = 1;
1074 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1075 vol->posix_paths = 0;
1076 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1077 (strnicmp(data, "ignorecase", 10) == 0)) {
1078 vol->nocase = 1;
1079 } else if (strnicmp(data, "brl", 3) == 0) {
1080 vol->nobrl = 0;
1081 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1082 (strnicmp(data, "nolock", 6) == 0)) {
1083 vol->nobrl = 1;
1084 /* turn off mandatory locking in mode
1085 if remote locking is turned off since the
1086 local vfs will do advisory */
1087 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1088 vol->file_mode = S_IALLUGO;
1026 } else if (strnicmp(data, "setuids", 7) == 0) { 1089 } else if (strnicmp(data, "setuids", 7) == 0) {
1027 vol->setuids = 1; 1090 vol->setuids = 1;
1028 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1091 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1242,7 +1305,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length)
1242 1305
1243static int 1306static int
1244ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, 1307ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1245 char * netbios_name) 1308 char * netbios_name, char * target_name)
1246{ 1309{
1247 int rc = 0; 1310 int rc = 0;
1248 int connected = 0; 1311 int connected = 0;
@@ -1320,8 +1383,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1320 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); 1383 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1321 if(ses_init_buf) { 1384 if(ses_init_buf) {
1322 ses_init_buf->trailer.session_req.called_len = 32; 1385 ses_init_buf->trailer.session_req.called_len = 32;
1323 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1386 if(target_name && (target_name[0] != 0)) {
1324 DEFAULT_CIFS_CALLED_NAME,16); 1387 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1388 target_name, 16);
1389 } else {
1390 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1391 DEFAULT_CIFS_CALLED_NAME,16);
1392 }
1393
1325 ses_init_buf->trailer.session_req.calling_len = 32; 1394 ses_init_buf->trailer.session_req.calling_len = 32;
1326 /* calling name ends in null (byte 16) from old smb 1395 /* calling name ends in null (byte 16) from old smb
1327 convention. */ 1396 convention. */
@@ -1554,7 +1623,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1554 sin_server.sin_port = htons(volume_info.port); 1623 sin_server.sin_port = htons(volume_info.port);
1555 else 1624 else
1556 sin_server.sin_port = 0; 1625 sin_server.sin_port = 0;
1557 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); 1626 rc = ipv4_connect(&sin_server,&csocket,
1627 volume_info.source_rfc1001_name,
1628 volume_info.target_rfc1001_name);
1558 if (rc < 0) { 1629 if (rc < 0) {
1559 cERROR(1, 1630 cERROR(1,
1560 ("Error connecting to IPv4 socket. Aborting operation")); 1631 ("Error connecting to IPv4 socket. Aborting operation"));
@@ -1604,9 +1675,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1604 kfree(volume_info.password); 1675 kfree(volume_info.password);
1605 FreeXid(xid); 1676 FreeXid(xid);
1606 return rc; 1677 return rc;
1607 } else 1678 }
1608 rc = 0; 1679 wait_for_completion(&cifsd_complete);
1680 rc = 0;
1609 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1681 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1682 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1610 srvTcp->sequence_number = 0; 1683 srvTcp->sequence_number = 0;
1611 } 1684 }
1612 } 1685 }
@@ -1660,8 +1733,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1660 else 1733 else
1661 cifs_sb->wsize = CIFSMaxBufSize; /* default */ 1734 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1662 if(cifs_sb->rsize < PAGE_CACHE_SIZE) { 1735 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1663 cifs_sb->rsize = PAGE_CACHE_SIZE; 1736 cifs_sb->rsize = PAGE_CACHE_SIZE;
1664 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); 1737 /* Windows ME does this */
1738 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1665 } 1739 }
1666 cifs_sb->mnt_uid = volume_info.linux_uid; 1740 cifs_sb->mnt_uid = volume_info.linux_uid;
1667 cifs_sb->mnt_gid = volume_info.linux_gid; 1741 cifs_sb->mnt_gid = volume_info.linux_gid;
@@ -1679,8 +1753,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 1753 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1680 if(volume_info.no_xattr) 1754 if(volume_info.no_xattr)
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1755 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1756 if(volume_info.sfu_emul)
1757 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1758 if(volume_info.nobrl)
1759 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1760
1682 if(volume_info.direct_io) { 1761 if(volume_info.direct_io) {
1683 cERROR(1,("mounting share using direct i/o")); 1762 cFYI(1,("mounting share using direct i/o"));
1684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 1763 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1685 } 1764 }
1686 1765
@@ -1694,6 +1773,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1694 to the same server share the last value passed in 1773 to the same server share the last value passed in
1695 for the retry flag is used */ 1774 for the retry flag is used */
1696 tcon->retry = volume_info.retry; 1775 tcon->retry = volume_info.retry;
1776 tcon->nocase = volume_info.nocase;
1697 } else { 1777 } else {
1698 tcon = tconInfoAlloc(); 1778 tcon = tconInfoAlloc();
1699 if (tcon == NULL) 1779 if (tcon == NULL)
@@ -1722,6 +1802,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1722 if (!rc) { 1802 if (!rc) {
1723 atomic_inc(&pSesInfo->inUse); 1803 atomic_inc(&pSesInfo->inUse);
1724 tcon->retry = volume_info.retry; 1804 tcon->retry = volume_info.retry;
1805 tcon->nocase = volume_info.nocase;
1725 } 1806 }
1726 } 1807 }
1727 } 1808 }
@@ -1743,8 +1824,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1743 spin_lock(&GlobalMid_Lock); 1824 spin_lock(&GlobalMid_Lock);
1744 srvTcp->tcpStatus = CifsExiting; 1825 srvTcp->tcpStatus = CifsExiting;
1745 spin_unlock(&GlobalMid_Lock); 1826 spin_unlock(&GlobalMid_Lock);
1746 if(srvTcp->tsk) 1827 if(srvTcp->tsk) {
1747 send_sig(SIGKILL,srvTcp->tsk,1); 1828 send_sig(SIGKILL,srvTcp->tsk,1);
1829 wait_for_completion(&cifsd_complete);
1830 }
1748 } 1831 }
1749 /* If find_unc succeeded then rc == 0 so we can not end */ 1832 /* If find_unc succeeded then rc == 0 so we can not end */
1750 if (tcon) /* up accidently freeing someone elses tcon struct */ 1833 if (tcon) /* up accidently freeing someone elses tcon struct */
@@ -1757,8 +1840,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1757 temp_rc = CIFSSMBLogoff(xid, pSesInfo); 1840 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1758 /* if the socketUseCount is now zero */ 1841 /* if the socketUseCount is now zero */
1759 if((temp_rc == -ESHUTDOWN) && 1842 if((temp_rc == -ESHUTDOWN) &&
1760 (pSesInfo->server->tsk)) 1843 (pSesInfo->server->tsk)) {
1761 send_sig(SIGKILL,pSesInfo->server->tsk,1); 1844 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1845 wait_for_completion(&cifsd_complete);
1846 }
1762 } else 1847 } else
1763 cFYI(1, ("No session or bad tcon")); 1848 cFYI(1, ("No session or bad tcon"));
1764 sesInfoFree(pSesInfo); 1849 sesInfoFree(pSesInfo);
@@ -1781,6 +1866,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1781 cFYI(1,("server negotiated posix acl support")); 1866 cFYI(1,("server negotiated posix acl support"));
1782 sb->s_flags |= MS_POSIXACL; 1867 sb->s_flags |= MS_POSIXACL;
1783 } 1868 }
1869
1870 /* Try and negotiate POSIX pathnames if we can. */
1871 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1872 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1873 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1874 cFYI(1,("negotiated posix pathnames support"));
1875 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1876 } else {
1877 cFYI(1,("posix pathnames support requested but not supported"));
1878 }
1879 }
1784 } 1880 }
1785 } 1881 }
1786 } 1882 }
@@ -1830,6 +1926,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1830 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 1926 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1831 NULL /* no tCon exists yet */ , 13 /* wct */ ); 1927 NULL /* no tCon exists yet */ , 13 /* wct */ );
1832 1928
1929 smb_buffer->Mid = GetNextMid(ses->server);
1833 pSMB->req_no_secext.AndXCommand = 0xFF; 1930 pSMB->req_no_secext.AndXCommand = 0xFF;
1834 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 1931 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1835 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 1932 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
@@ -2105,6 +2202,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2105 /* send SMBsessionSetup here */ 2202 /* send SMBsessionSetup here */
2106 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2203 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2107 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2204 NULL /* no tCon exists yet */ , 12 /* wct */ );
2205
2206 smb_buffer->Mid = GetNextMid(ses->server);
2108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2207 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2109 pSMB->req.AndXCommand = 0xFF; 2208 pSMB->req.AndXCommand = 0xFF;
2110 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2209 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
@@ -2371,6 +2470,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2371 /* send SMBsessionSetup here */ 2470 /* send SMBsessionSetup here */
2372 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2471 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2373 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2472 NULL /* no tCon exists yet */ , 12 /* wct */ );
2473
2474 smb_buffer->Mid = GetNextMid(ses->server);
2374 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2475 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2375 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2476 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2376 2477
@@ -2713,6 +2814,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2713 /* send SMBsessionSetup here */ 2814 /* send SMBsessionSetup here */
2714 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2815 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2715 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2816 NULL /* no tCon exists yet */ , 12 /* wct */ );
2817
2818 smb_buffer->Mid = GetNextMid(ses->server);
2716 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2819 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2717 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2820 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2718 pSMB->req.AndXCommand = 0xFF; 2821 pSMB->req.AndXCommand = 0xFF;
@@ -3084,6 +3187,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3084 3187
3085 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, 3188 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3086 NULL /*no tid */ , 4 /*wct */ ); 3189 NULL /*no tid */ , 4 /*wct */ );
3190
3191 smb_buffer->Mid = GetNextMid(ses->server);
3087 smb_buffer->Uid = ses->Suid; 3192 smb_buffer->Uid = ses->Suid;
3088 pSMB = (TCONX_REQ *) smb_buffer; 3193 pSMB = (TCONX_REQ *) smb_buffer;
3089 pSMBr = (TCONX_RSP *) smb_buffer_response; 3194 pSMBr = (TCONX_RSP *) smb_buffer_response;
@@ -3205,8 +3310,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3205 return 0; 3310 return 0;
3206 } else if (rc == -ESHUTDOWN) { 3311 } else if (rc == -ESHUTDOWN) {
3207 cFYI(1,("Waking up socket by sending it signal")); 3312 cFYI(1,("Waking up socket by sending it signal"));
3208 if(cifsd_task) 3313 if(cifsd_task) {
3209 send_sig(SIGKILL,cifsd_task,1); 3314 send_sig(SIGKILL,cifsd_task,1);
3315 wait_for_completion(&cifsd_complete);
3316 }
3210 rc = 0; 3317 rc = 0;
3211 } /* else - we have an smb session 3318 } /* else - we have an smb session
3212 left on this socket do not kill cifsd */ 3319 left on this socket do not kill cifsd */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d4a1fa..cf90c9ad2c87 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));
@@ -184,6 +185,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
184 desiredAccess, CREATE_NOT_DIR, 185 desiredAccess, CREATE_NOT_DIR,
185 &fileHandle, &oplock, buf, cifs_sb->local_nls, 186 &fileHandle, &oplock, buf, cifs_sb->local_nls,
186 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 187 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
188 if(rc == -EIO) {
189 /* old server, retry the open legacy style */
190 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
191 desiredAccess, CREATE_NOT_DIR,
192 &fileHandle, &oplock, buf, cifs_sb->local_nls,
193 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
194 }
187 if (rc) { 195 if (rc) {
188 cFYI(1, ("cifs_create returned 0x%x ", rc)); 196 cFYI(1, ("cifs_create returned 0x%x ", rc));
189 } else { 197 } else {
@@ -209,7 +217,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
209 CIFS_MOUNT_MAP_SPECIAL_CHR); 217 CIFS_MOUNT_MAP_SPECIAL_CHR);
210 } 218 }
211 else { 219 else {
212 /* BB implement via Windows security descriptors */ 220 /* BB implement mode setting via Windows security descriptors */
213 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ 221 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
214 /* could set r/o dos attribute if mode & 0222 == 0 */ 222 /* could set r/o dos attribute if mode & 0222 == 0 */
215 } 223 }
@@ -226,10 +234,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
226 } 234 }
227 235
228 if (rc != 0) { 236 if (rc != 0) {
229 cFYI(1,("Create worked but get_inode_info failed with rc = %d", 237 cFYI(1,
238 ("Create worked but get_inode_info failed rc = %d",
230 rc)); 239 rc));
231 } else { 240 } else {
232 direntry->d_op = &cifs_dentry_ops; 241 if (pTcon->nocase)
242 direntry->d_op = &cifs_ci_dentry_ops;
243 else
244 direntry->d_op = &cifs_dentry_ops;
233 d_instantiate(direntry, newinode); 245 d_instantiate(direntry, newinode);
234 } 246 }
235 if((nd->flags & LOOKUP_OPEN) == FALSE) { 247 if((nd->flags & LOOKUP_OPEN) == FALSE) {
@@ -303,8 +315,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
303 up(&direntry->d_sb->s_vfs_rename_sem); 315 up(&direntry->d_sb->s_vfs_rename_sem);
304 if(full_path == NULL) 316 if(full_path == NULL)
305 rc = -ENOMEM; 317 rc = -ENOMEM;
306 318 else if (pTcon->ses->capabilities & CAP_UNIX) {
307 if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 319 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 320 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
310 mode,(__u64)current->euid,(__u64)current->egid, 321 mode,(__u64)current->euid,(__u64)current->egid,
@@ -322,10 +333,49 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
322 if(!rc) { 333 if(!rc) {
323 rc = cifs_get_inode_info_unix(&newinode, full_path, 334 rc = cifs_get_inode_info_unix(&newinode, full_path,
324 inode->i_sb,xid); 335 inode->i_sb,xid);
325 direntry->d_op = &cifs_dentry_ops; 336 if (pTcon->nocase)
337 direntry->d_op = &cifs_ci_dentry_ops;
338 else
339 direntry->d_op = &cifs_dentry_ops;
326 if(rc == 0) 340 if(rc == 0)
327 d_instantiate(direntry, newinode); 341 d_instantiate(direntry, newinode);
328 } 342 }
343 } else {
344 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
345 int oplock = 0;
346 u16 fileHandle;
347 FILE_ALL_INFO * buf;
348
349 cFYI(1,("sfu compat create special file"));
350
351 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
352 if(buf == NULL) {
353 kfree(full_path);
354 FreeXid(xid);
355 return -ENOMEM;
356 }
357
358 rc = CIFSSMBOpen(xid, pTcon, full_path,
359 FILE_CREATE, /* fail if exists */
360 GENERIC_WRITE /* BB would
361 WRITE_OWNER | WRITE_DAC be better? */,
362 /* Create a file and set the
363 file attribute to SYSTEM */
364 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
365 &fileHandle, &oplock, buf,
366 cifs_sb->local_nls,
367 cifs_sb->mnt_cifs_flags &
368 CIFS_MOUNT_MAP_SPECIAL_CHR);
369
370 if(!rc) {
371 /* BB Do not bother to decode buf since no
372 local inode yet to put timestamps in */
373 CIFSSMBClose(xid, pTcon, fileHandle);
374 d_drop(direntry);
375 }
376 kfree(buf);
377 /* add code here to set EAs */
378 }
329 } 379 }
330 380
331 kfree(full_path); 381 kfree(full_path);
@@ -382,7 +432,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
382 parent_dir_inode->i_sb,xid); 432 parent_dir_inode->i_sb,xid);
383 433
384 if ((rc == 0) && (newInode != NULL)) { 434 if ((rc == 0) && (newInode != NULL)) {
385 direntry->d_op = &cifs_dentry_ops; 435 if (pTcon->nocase)
436 direntry->d_op = &cifs_ci_dentry_ops;
437 else
438 direntry->d_op = &cifs_dentry_ops;
386 d_add(direntry, newInode); 439 d_add(direntry, newInode);
387 440
388 /* since paths are not looked up by component - the parent directories are presumed to be good here */ 441 /* since paths are not looked up by component - the parent directories are presumed to be good here */
@@ -441,3 +494,42 @@ struct dentry_operations cifs_dentry_ops = {
441/* d_delete: cifs_d_delete, *//* not needed except for debugging */ 494/* d_delete: cifs_d_delete, *//* not needed except for debugging */
442 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ 495 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
443}; 496};
497
498static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
499{
500 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
501 unsigned long hash;
502 int i;
503
504 hash = init_name_hash();
505 for (i = 0; i < q->len; i++)
506 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
507 hash);
508 q->hash = end_name_hash(hash);
509
510 return 0;
511}
512
513static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
514 struct qstr *b)
515{
516 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
517
518 if ((a->len == b->len) &&
519 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
520 /*
521 * To preserve case, don't let an existing negative dentry's
522 * case take precedence. If a is not a negative dentry, this
523 * should have no side effects
524 */
525 memcpy((unsigned char *)a->name, b->name, a->len);
526 return 0;
527 }
528 return 1;
529}
530
531struct dentry_operations cifs_ci_dentry_ops = {
532 .d_revalidate = cifs_d_revalidate,
533 .d_hash = cifs_ci_hash,
534 .d_compare = cifs_ci_compare,
535};
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 7d2a9202c39a..d527e2c76073 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -100,8 +100,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
100 } else { 100 } else {
101 filter = convert_to_cifs_notify_flags(arg); 101 filter = convert_to_cifs_notify_flags(arg);
102 if(filter != 0) { 102 if(filter != 0) {
103 rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, 103 rc = CIFSSMBNotify(xid, pTcon,
104 filter, cifs_sb->local_nls); 104 0 /* no subdirs */, netfid,
105 filter, file, arg & DN_MULTISHOT,
106 cifs_sb->local_nls);
105 } else { 107 } else {
106 rc = -EINVAL; 108 rc = -EINVAL;
107 } 109 }
@@ -109,7 +111,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
109 it would close automatically but may be a way 111 it would close automatically but may be a way
110 to do it easily when inode freed or when 112 to do it easily when inode freed or when
111 notify info is cleared/changed */ 113 notify info is cleared/changed */
112 cERROR(1,("notify rc %d",rc)); 114 cFYI(1,("notify rc %d",rc));
113 } 115 }
114 } 116 }
115 117
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 3497125189df..5ecda554f913 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -256,6 +256,13 @@ int cifs_open(struct inode *inode, struct file *file)
256 CREATE_NOT_DIR, &netfid, &oplock, buf, 256 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258 & CIFS_MOUNT_MAP_SPECIAL_CHR); 258 & CIFS_MOUNT_MAP_SPECIAL_CHR);
259 if (rc == -EIO) {
260 /* Old server, try legacy style OpenX */
261 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
262 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
263 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
264 & CIFS_MOUNT_MAP_SPECIAL_CHR);
265 }
259 if (rc) { 266 if (rc) {
260 cFYI(1, ("cifs_open returned 0x%x ", rc)); 267 cFYI(1, ("cifs_open returned 0x%x ", rc));
261 goto out; 268 goto out;
@@ -744,14 +751,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
744 15 seconds is plenty */ 751 15 seconds is plenty */
745 } 752 }
746 753
747#ifdef CONFIG_CIFS_STATS 754 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 755
756 /* since the write may have blocked check these pointers again */ 756 /* since the write may have blocked check these pointers again */
757 if (file->f_dentry) { 757 if (file->f_dentry) {
@@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
791 791
792 pTcon = cifs_sb->tcon; 792 pTcon = cifs_sb->tcon;
793 793
794 /* cFYI(1, 794 cFYI(1,(" write %d bytes to offset %lld of %s", write_size,
795 (" write %d bytes to offset %lld of %s", write_size, 795 *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */
796 *poffset, file->f_dentry->d_name.name)); */
797 796
798 if (file->private_data == NULL) 797 if (file->private_data == NULL)
799 return -EBADF; 798 return -EBADF;
@@ -846,7 +845,20 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
846 if (rc != 0) 845 if (rc != 0)
847 break; 846 break;
848 } 847 }
849 848#ifdef CONFIG_CIFS_EXPERIMENTAL
849 /* BB FIXME We can not sign across two buffers yet */
850 if((experimEnabled) && ((pTcon->ses->server->secMode &
851 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
852 rc = CIFSSMBWrite2(xid, pTcon,
853 open_file->netfid,
854 min_t(const int, cifs_sb->wsize,
855 write_size - total_written),
856 *poffset, &bytes_written,
857 write_data + total_written,
858 long_op);
859 } else
860 /* BB FIXME fixup indentation of line below */
861#endif
850 rc = CIFSSMBWrite(xid, pTcon, 862 rc = CIFSSMBWrite(xid, pTcon,
851 open_file->netfid, 863 open_file->netfid,
852 min_t(const int, cifs_sb->wsize, 864 min_t(const int, cifs_sb->wsize,
@@ -867,14 +879,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
867 15 seconds is plenty */ 879 15 seconds is plenty */
868 } 880 }
869 881
870#ifdef CONFIG_CIFS_STATS 882 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 883
879 /* since the write may have blocked check these pointers again */ 884 /* since the write may have blocked check these pointers again */
880 if (file->f_dentry) { 885 if (file->f_dentry) {
@@ -1207,12 +1212,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1207 if (rc != 0) 1212 if (rc != 0)
1208 break; 1213 break;
1209 } 1214 }
1210
1211 rc = CIFSSMBRead(xid, pTcon, 1215 rc = CIFSSMBRead(xid, pTcon,
1212 open_file->netfid, 1216 open_file->netfid,
1213 current_read_size, *poffset, 1217 current_read_size, *poffset,
1214 &bytes_read, &smb_read_data); 1218 &bytes_read, &smb_read_data);
1215
1216 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1219 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1217 if (copy_to_user(current_offset, 1220 if (copy_to_user(current_offset,
1218 smb_read_data + 4 /* RFC1001 hdr */ 1221 smb_read_data + 4 /* RFC1001 hdr */
@@ -1235,12 +1238,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1235 return rc; 1238 return rc;
1236 } 1239 }
1237 } else { 1240 } else {
1238#ifdef CONFIG_CIFS_STATS 1241 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; 1242 *poffset += bytes_read;
1245 } 1243 }
1246 } 1244 }
@@ -1289,11 +1287,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1289 if (rc != 0) 1287 if (rc != 0)
1290 break; 1288 break;
1291 } 1289 }
1292
1293 rc = CIFSSMBRead(xid, pTcon, 1290 rc = CIFSSMBRead(xid, pTcon,
1294 open_file->netfid, 1291 open_file->netfid,
1295 current_read_size, *poffset, 1292 current_read_size, *poffset,
1296 &bytes_read, &current_offset); 1293 &bytes_read, &current_offset);
1297 } 1294 }
1298 if (rc || (bytes_read == 0)) { 1295 if (rc || (bytes_read == 0)) {
1299 if (total_read) { 1296 if (total_read) {
@@ -1303,12 +1300,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1303 return rc; 1300 return rc;
1304 } 1301 }
1305 } else { 1302 } else {
1306#ifdef CONFIG_CIFS_STATS 1303 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; 1304 *poffset += bytes_read;
1313 } 1305 }
1314 } 1306 }
@@ -1452,10 +1444,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1452 } 1444 }
1453 1445
1454 rc = CIFSSMBRead(xid, pTcon, 1446 rc = CIFSSMBRead(xid, pTcon,
1455 open_file->netfid, 1447 open_file->netfid,
1456 read_size, offset, 1448 read_size, offset,
1457 &bytes_read, &smb_read_data); 1449 &bytes_read, &smb_read_data);
1458 /* BB need to check return code here */ 1450
1451 /* BB more RC checks ? */
1459 if (rc== -EAGAIN) { 1452 if (rc== -EAGAIN) {
1460 if (smb_read_data) { 1453 if (smb_read_data) {
1461 cifs_buf_release(smb_read_data); 1454 cifs_buf_release(smb_read_data);
@@ -1480,12 +1473,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1480 le16_to_cpu(pSMBr->DataOffset), &lru_pvec); 1473 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1481 1474
1482 i += bytes_read >> PAGE_CACHE_SHIFT; 1475 i += bytes_read >> PAGE_CACHE_SHIFT;
1483#ifdef CONFIG_CIFS_STATS 1476 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) { 1477 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1490 i++; /* account for partial page */ 1478 i++; /* account for partial page */
1491 1479
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..0fbe02ebc033 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;
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..fafbdbfa63a1 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))
@@ -448,9 +520,7 @@ is_valid_oplock_break(struct smb_hdr *buf)
448 list_for_each(tmp, &GlobalTreeConnectionList) { 520 list_for_each(tmp, &GlobalTreeConnectionList) {
449 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 521 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
450 if (tcon->tid == buf->Tid) { 522 if (tcon->tid == buf->Tid) {
451#ifdef CONFIG_CIFS_STATS 523 cifs_stats_inc(&tcon->num_oplock_brks);
452 atomic_inc(&tcon->num_oplock_brks);
453#endif
454 list_for_each(tmp1,&tcon->openFileList){ 524 list_for_each(tmp1,&tcon->openFileList){
455 netfile = list_entry(tmp1,struct cifsFileInfo, 525 netfile = list_entry(tmp1,struct cifsFileInfo,
456 tlist); 526 tlist);
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index a92af41d4411..873b812c0f40 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
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 22557716f9af..a1e8dc901de4 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,7 @@ 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 & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
378 if(rc == 0) 400 if(rc == 0)
379 cifsFile->invalidHandle = FALSE; 401 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) && 402 if((rc == -EOPNOTSUPP) &&
@@ -536,7 +558,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
536 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 558 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
537 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ 559 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
538 cFYI(1,("calling findnext2")); 560 cFYI(1,("calling findnext2"));
539 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); 561 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
562 &cifsFile->srch_inf);
540 if(rc) 563 if(rc)
541 return -ENOENT; 564 return -ENOENT;
542 } 565 }
@@ -548,14 +571,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
548 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 571 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
549 smbCalcSize((struct smb_hdr *) 572 smbCalcSize((struct smb_hdr *)
550 cifsFile->srch_inf.ntwrk_buf_start); 573 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 574 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
553 - cifsFile->srch_inf.entries_in_buffer; 575 - cifsFile->srch_inf.entries_in_buffer;
554 pos_in_buf = index_to_find - first_entry_in_buffer; 576 pos_in_buf = index_to_find - first_entry_in_buffer;
555 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 577 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
556 current_entry = cifsFile->srch_inf.srch_entries_start; 578 current_entry = cifsFile->srch_inf.srch_entries_start;
557 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 579 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 */ 580 /* go entry by entry figuring out which is first */
559 /* if( . or ..) 581 /* if( . or ..)
560 skip */ 582 skip */
561 rc = cifs_entry_is_dot(current_entry,cifsFile); 583 rc = cifs_entry_is_dot(current_entry,cifsFile);
@@ -586,7 +608,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
586 *num_to_ret = 0; 608 *num_to_ret = 0;
587 } else 609 } else
588 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; 610 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
589/* dump_cifs_file_struct(file, "end fce ");*/
590 611
591 return rc; 612 return rc;
592} 613}
@@ -721,7 +742,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 742 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
722 } 743 }
723 744
724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 745 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
746 tmp_inode->i_ino,obj_type);
725 if(rc) { 747 if(rc) {
726 cFYI(1,("filldir rc = %d",rc)); 748 cFYI(1,("filldir rc = %d",rc));
727 } 749 }
@@ -805,14 +827,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
805 FreeXid(xid); 827 FreeXid(xid);
806 return -EIO; 828 return -EIO;
807 } 829 }
808/* dump_cifs_file_struct(file, "Begin rdir "); */
809 830
810 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 831 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
811 pTcon = cifs_sb->tcon; 832 pTcon = cifs_sb->tcon;
812 if(pTcon == NULL) 833 if(pTcon == NULL)
813 return -EINVAL; 834 return -EINVAL;
814 835
815/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
816 836
817 switch ((int) file->f_pos) { 837 switch ((int) file->f_pos) {
818 case 0: 838 case 0:
@@ -866,7 +886,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
866 cifsFile->search_resume_name = NULL; */ 886 cifsFile->search_resume_name = NULL; */
867 887
868 /* BB account for . and .. in f_pos as special case */ 888 /* BB account for . and .. in f_pos as special case */
869 /* dump_cifs_file_struct(file, "rdir after default ");*/
870 889
871 rc = find_cifs_entry(xid,pTcon, file, 890 rc = find_cifs_entry(xid,pTcon, file,
872 &current_entry,&num_to_fill); 891 &current_entry,&num_to_fill);
@@ -906,14 +925,14 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
906 cifs_save_resume_key(current_entry,cifsFile); 925 cifs_save_resume_key(current_entry,cifsFile);
907 break; 926 break;
908 } else 927 } else
909 current_entry = nxt_dir_entry(current_entry,end_of_smb); 928 current_entry = nxt_dir_entry(current_entry,
929 end_of_smb);
910 } 930 }
911 kfree(tmp_buf); 931 kfree(tmp_buf);
912 break; 932 break;
913 } /* end switch */ 933 } /* end switch */
914 934
915rddir2_exit: 935rddir2_exit:
916 /* dump_cifs_file_struct(file, "end rdir "); */
917 FreeXid(xid); 936 FreeXid(xid);
918 return rc; 937 return rc;
919} 938}
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0046c219833d..96f89eb66040 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 {
@@ -179,27 +180,24 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
179 return rc; 180 return rc;
180} 181}
181 182
182#ifdef CIFS_EXPERIMENTAL 183#ifdef CONFIG_CIFS_EXPERIMENTAL
183/* BB finish off this function, adding support for writing set of pages as iovec */ 184static int
184/* and also adding support for operations that need to parse the response smb */ 185smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 186 unsigned int smb_hdr_length, const char * data, unsigned int datalen,
186int 187 struct sockaddr *sin)
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{ 188{
191 int rc = 0; 189 int rc = 0;
192 int i = 0; 190 int i = 0;
193 struct msghdr smb_msg; 191 struct msghdr smb_msg;
194 number_of_pages += 1; /* account for SMB header */ 192 struct kvec iov[2];
195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 193 unsigned len = smb_hdr_length + 4;
196 unsigned len = smb_buf_length + 4; 194
197
198 if(ssocket == NULL) 195 if(ssocket == NULL)
199 return -ENOTSOCK; /* BB eventually add reconnect code here */ 196 return -ENOTSOCK; /* BB eventually add reconnect code here */
200 iov.iov_base = smb_buffer; 197 iov[0].iov_base = smb_buffer;
201 iov.iov_len = len; 198 iov[0].iov_len = len;
202 199 iov[1].iov_base = data;
200 iov[1].iov_len = datalen;
203 smb_msg.msg_name = sin; 201 smb_msg.msg_name = sin;
204 smb_msg.msg_namelen = sizeof (struct sockaddr); 202 smb_msg.msg_namelen = sizeof (struct sockaddr);
205 smb_msg.msg_control = NULL; 203 smb_msg.msg_control = NULL;
@@ -212,12 +210,12 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
212 Flags2 is converted in SendReceive */ 210 Flags2 is converted in SendReceive */
213 211
214 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 212 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
215 cFYI(1, ("Sending smb of length %d ", smb_buf_length)); 213 cFYI(1, ("Sending smb: hdrlen %d datalen %d",
214 smb_hdr_length,datalen));
216 dump_smb(smb_buffer, len); 215 dump_smb(smb_buffer, len);
217 216
218 while (len > 0) { 217 while (len + datalen > 0) {
219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 218 rc = kernel_sendmsg(ssocket, &smb_msg, iov, 2, len);
220 len);
221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 219 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
222 i++; 220 i++;
223 if(i > 60) { 221 if(i > 60) {
@@ -232,9 +230,23 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
232 } 230 }
233 if (rc < 0) 231 if (rc < 0)
234 break; 232 break;
235 iov.iov_base += rc; 233 if(iov[0].iov_len > 0) {
236 iov.iov_len -= rc; 234 if(rc >= len) {
237 len -= rc; 235 iov[0].iov_len = 0;
236 rc -= len;
237 len = 0;
238 } else { /* some of hdr was not sent */
239 len -= rc;
240 iov[0].iov_len -= rc;
241 iov[0].iov_base += rc;
242 continue;
243 }
244 }
245 if((iov[0].iov_len == 0) && (rc > 0)){
246 iov[1].iov_base += rc;
247 iov[1].iov_len -= rc;
248 datalen -= rc;
249 }
238 } 250 }
239 251
240 if (rc < 0) { 252 if (rc < 0) {
@@ -246,14 +258,15 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
246 return rc; 258 return rc;
247} 259}
248 260
249
250int 261int
251CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, 262SendReceive2(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) 263 struct smb_hdr *in_buf, int hdrlen, const char * data,
264 int datalen, int *pbytes_returned, const int long_op)
253{ 265{
254 int rc = 0; 266 int rc = 0;
255 unsigned long timeout = 15 * HZ; 267 unsigned int receive_len;
256 struct mid_q_entry *midQ = NULL; 268 unsigned long timeout;
269 struct mid_q_entry *midQ;
257 270
258 if (ses == NULL) { 271 if (ses == NULL) {
259 cERROR(1,("Null smb session")); 272 cERROR(1,("Null smb session"));
@@ -263,14 +276,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
263 cERROR(1,("Null tcp session")); 276 cERROR(1,("Null tcp session"));
264 return -EIO; 277 return -EIO;
265 } 278 }
266 if(pbytes_returned == NULL)
267 return -EIO;
268 else
269 *pbytes_returned = 0;
270 279
271 280 if(ses->server->tcpStatus == CifsExiting)
272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT; 281 return -ENOENT;
275 282
276 /* Ensure that we do not send more than 50 overlapping requests 283 /* Ensure that we do not send more than 50 overlapping requests
@@ -282,7 +289,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
282 } else { 289 } else {
283 spin_lock(&GlobalMid_Lock); 290 spin_lock(&GlobalMid_Lock);
284 while(1) { 291 while(1) {
285 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 292 if(atomic_read(&ses->server->inFlight) >=
293 cifs_max_pending){
286 spin_unlock(&GlobalMid_Lock); 294 spin_unlock(&GlobalMid_Lock);
287 wait_event(ses->server->request_q, 295 wait_event(ses->server->request_q,
288 atomic_read(&ses->server->inFlight) 296 atomic_read(&ses->server->inFlight)
@@ -314,17 +322,17 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
314 322
315 if (ses->server->tcpStatus == CifsExiting) { 323 if (ses->server->tcpStatus == CifsExiting) {
316 rc = -ENOENT; 324 rc = -ENOENT;
317 goto cifs_out_label; 325 goto out_unlock2;
318 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 326 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
319 cFYI(1,("tcp session dead - return to caller to retry")); 327 cFYI(1,("tcp session dead - return to caller to retry"));
320 rc = -EAGAIN; 328 rc = -EAGAIN;
321 goto cifs_out_label; 329 goto out_unlock2;
322 } else if (ses->status != CifsGood) { 330 } else if (ses->status != CifsGood) {
323 /* check if SMB session is bad because we are setting it up */ 331 /* check if SMB session is bad because we are setting it up */
324 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 332 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
325 (in_buf->Command != SMB_COM_NEGOTIATE)) { 333 (in_buf->Command != SMB_COM_NEGOTIATE)) {
326 rc = -EAGAIN; 334 rc = -EAGAIN;
327 goto cifs_out_label; 335 goto out_unlock2;
328 } /* else ok - we are setting up session */ 336 } /* else ok - we are setting up session */
329 } 337 }
330 midQ = AllocMidQEntry(in_buf, ses); 338 midQ = AllocMidQEntry(in_buf, ses);
@@ -352,13 +360,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
352 return -EIO; 360 return -EIO;
353 } 361 }
354 362
355 /* BB can we sign efficiently in this path? */ 363/* BB FIXME */
356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 364/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */
357 365
358 midQ->midState = MID_REQUEST_SUBMITTED; 366 midQ->midState = MID_REQUEST_SUBMITTED;
359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 367 rc = smb_send2(ses->server->ssocket, in_buf, hdrlen, data, datalen,
360 piovec, 368 (struct sockaddr *) &(ses->server->addr.sockAddr));
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
362 if(rc < 0) { 369 if(rc < 0) {
363 DeleteMidQEntry(midQ); 370 DeleteMidQEntry(midQ);
364 up(&ses->server->tcpSem); 371 up(&ses->server->tcpSem);
@@ -370,19 +377,137 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
370 return rc; 377 return rc;
371 } else 378 } else
372 up(&ses->server->tcpSem); 379 up(&ses->server->tcpSem);
373cifs_out_label: 380 if (long_op == -1)
374 if(midQ) 381 goto cifs_no_response_exit2;
375 DeleteMidQEntry(midQ); 382 else if (long_op == 2) /* writes past end of file can take loong time */
376 383 timeout = 300 * HZ;
384 else if (long_op == 1)
385 timeout = 45 * HZ; /* should be greater than
386 servers oplock break timeout (about 43 seconds) */
387 else if (long_op > 2) {
388 timeout = MAX_SCHEDULE_TIMEOUT;
389 } else
390 timeout = 15 * HZ;
391 /* wait for 15 seconds or until woken up due to response arriving or
392 due to last connection to this server being unmounted */
393 if (signal_pending(current)) {
394 /* if signal pending do not hold up user for full smb timeout
395 but we still give response a change to complete */
396 timeout = 2 * HZ;
397 }
398
399 /* No user interrupts in wait - wreaks havoc with performance */
400 if(timeout != MAX_SCHEDULE_TIMEOUT) {
401 timeout += jiffies;
402 wait_event(ses->server->response_q,
403 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
404 time_after(jiffies, timeout) ||
405 ((ses->server->tcpStatus != CifsGood) &&
406 (ses->server->tcpStatus != CifsNew)));
407 } else {
408 wait_event(ses->server->response_q,
409 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
410 ((ses->server->tcpStatus != CifsGood) &&
411 (ses->server->tcpStatus != CifsNew)));
412 }
413
414 spin_lock(&GlobalMid_Lock);
415 if (midQ->resp_buf) {
416 spin_unlock(&GlobalMid_Lock);
417 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
418 } else {
419 cERROR(1,("No response buffer"));
420 if(midQ->midState == MID_REQUEST_SUBMITTED) {
421 if(ses->server->tcpStatus == CifsExiting)
422 rc = -EHOSTDOWN;
423 else {
424 ses->server->tcpStatus = CifsNeedReconnect;
425 midQ->midState = MID_RETRY_NEEDED;
426 }
427 }
428
429 if (rc != -EHOSTDOWN) {
430 if(midQ->midState == MID_RETRY_NEEDED) {
431 rc = -EAGAIN;
432 cFYI(1,("marking request for retry"));
433 } else {
434 rc = -EIO;
435 }
436 }
437 spin_unlock(&GlobalMid_Lock);
438 DeleteMidQEntry(midQ);
439 /* If not lock req, update # of requests on wire to server */
440 if(long_op < 3) {
441 atomic_dec(&ses->server->inFlight);
442 wake_up(&ses->server->request_q);
443 }
444 return rc;
445 }
446
447 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
448 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
449 receive_len, xid));
450 rc = -EIO;
451 } else { /* rcvd frame is ok */
452
453 if (midQ->resp_buf &&
454 (midQ->midState == MID_RESPONSE_RECEIVED)) {
455 in_buf->smb_buf_length = receive_len;
456 /* BB verify that length would not overrun small buf */
457 memcpy((char *)in_buf + 4,
458 (char *)midQ->resp_buf + 4,
459 receive_len);
460
461 dump_smb(in_buf, 80);
462 /* convert the length into a more usable form */
463 if((receive_len > 24) &&
464 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
465 SECMODE_SIGN_ENABLED))) {
466 rc = cifs_verify_signature(in_buf,
467 ses->server->mac_signing_key,
468 midQ->sequence_number+1);
469 if(rc) {
470 cERROR(1,("Unexpected SMB signature"));
471 /* BB FIXME add code to kill session */
472 }
473 }
474
475 *pbytes_returned = in_buf->smb_buf_length;
476
477 /* BB special case reconnect tid and uid here? */
478 rc = map_smb_to_linux_error(in_buf);
479
480 /* convert ByteCount if necessary */
481 if (receive_len >=
482 sizeof (struct smb_hdr) -
483 4 /* do not count RFC1001 header */ +
484 (2 * in_buf->WordCount) + 2 /* bcc */ )
485 BCC(in_buf) = le16_to_cpu(BCC(in_buf));
486 } else {
487 rc = -EIO;
488 cFYI(1,("Bad MID state? "));
489 }
490 }
491cifs_no_response_exit2:
492 DeleteMidQEntry(midQ);
493
377 if(long_op < 3) { 494 if(long_op < 3) {
378 atomic_dec(&ses->server->inFlight); 495 atomic_dec(&ses->server->inFlight);
379 wake_up(&ses->server->request_q); 496 wake_up(&ses->server->request_q);
380 } 497 }
381 498
382 return rc; 499 return rc;
383}
384 500
501out_unlock2:
502 up(&ses->server->tcpSem);
503 /* If not lock req, update # of requests on wire to server */
504 if(long_op < 3) {
505 atomic_dec(&ses->server->inFlight);
506 wake_up(&ses->server->request_q);
507 }
385 508
509 return rc;
510}
386#endif /* CIFS_EXPERIMENTAL */ 511#endif /* CIFS_EXPERIMENTAL */
387 512
388int 513int
@@ -610,7 +735,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
610 BCC(out_buf) = le16_to_cpu(BCC(out_buf)); 735 BCC(out_buf) = le16_to_cpu(BCC(out_buf));
611 } else { 736 } else {
612 rc = -EIO; 737 rc = -EIO;
613 cFYI(1,("Bad MID state? ")); 738 cERROR(1,("Bad MID state? "));
614 } 739 }
615 } 740 }
616cifs_no_response_exit: 741cifs_no_response_exit: