aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/AUTHORS4
-rw-r--r--fs/cifs/CHANGES31
-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.c34
-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.h32
-rw-r--r--fs/cifs/cifssmb.c529
-rw-r--r--fs/cifs/connect.c140
-rw-r--r--fs/cifs/dir.c108
-rw-r--r--fs/cifs/fcntl.c8
-rw-r--r--fs/cifs/file.c88
-rw-r--r--fs/cifs/inode.c31
-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.c40
-rw-r--r--fs/cifs/transport.c227
21 files changed, 1399 insertions, 274 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..340b4ffb3493 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,23 @@
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).
6Add mount option for disabling the default behavior of sending byte range lock
7requests to the server (necessary for certain applications which break with
8mandatory lock behavior such as Evolution), and also mount option for
9requesting case insensitive matching for path based requests (requesting
10case sensitive is the default).
11
1Version 1.35 12Version 1.35
2------------ 13------------
3Add writepage performance improvements. Fix path name conversions 14Add writepage performance improvements. Fix path name conversions
4for long filenames on mounts which were done with "mapchars" mount option 15for long filenames on mounts which were done with "mapchars" mount option
5specified. 16specified. Ensure multiplex ids do not collide. Fix case in which
17rmmod can oops if done soon after last unmount. Fix truncated
18search (readdir) output when resume filename was a long filename.
19Fix filename conversion when mapchars mount option was specified and
20filename was a long filename.
6 21
7Version 1.34 22Version 1.34
8------------ 23------------
@@ -11,7 +26,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 26kills the cifsd thread (NB: killing the cifs kernel threads is not
12recommended, unmount and rmmod cifs will kill them when they are 27recommended, unmount and rmmod cifs will kill them when they are
13no longer needed). Fix readdir to ASCII servers (ie older servers 28no longer needed). Fix readdir to ASCII servers (ie older servers
14which do not support Unicode) and also require asterik. 29which do not support Unicode) and also require asterisk.
15Fix out of memory case in which data could be written one page 30Fix out of memory case in which data could be written one page
16off in the page cache. 31off in the page cache.
17 32
@@ -101,7 +116,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call.
101 116
102Version 1.25 117Version 1.25
103------------ 118------------
104Fix internationlization problem in cifs readdir with filenames that map to 119Fix internationalization problem in cifs readdir with filenames that map to
105longer UTF8 strings than the string on the wire was in Unicode. Add workaround 120longer 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 121for readdir to netapp servers. Fix search rewind (seek into readdir to return
107non-consecutive entries). Do not do readdir when server negotiates 122non-consecutive entries). Do not do readdir when server negotiates
@@ -276,7 +291,7 @@ Fix caching problem when files opened by multiple clients in which
276page cache could contain stale data, and write through did 291page cache could contain stale data, and write through did
277not occur often enough while file was still open when read ahead 292not occur often enough while file was still open when read ahead
278(read oplock) not allowed. Treat "sep=" when first mount option 293(read oplock) not allowed. Treat "sep=" when first mount option
279as an overrride of comma as the default separator between mount 294as an override of comma as the default separator between mount
280options. 295options.
281 296
282Version 1.01 297Version 1.01
@@ -286,7 +301,7 @@ Allow passwords longer than 16 bytes. Allow null password string.
286Version 1.00 301Version 1.00
287------------ 302------------
288Gracefully clean up failed mounts when attempting to mount to servers such as 303Gracefully clean up failed mounts when attempting to mount to servers such as
289Windows 98 that terminate tcp sessions during prototocol negotiation. Handle 304Windows 98 that terminate tcp sessions during protocol negotiation. Handle
290embedded commas in mount parsing of passwords. 305embedded commas in mount parsing of passwords.
291 306
292Version 0.99 307Version 0.99
@@ -295,7 +310,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 310instance is closed so that the client does not continue using stale local
296copy rather than later modified server copy of file. Do not reconnect 311copy rather than later modified server copy of file. Do not reconnect
297when server drops the tcp session prematurely before negotiate 312when server drops the tcp session prematurely before negotiate
298protocol response. Fix oops in roepen_file when dentry freed. Allow 313protocol response. Fix oops in reopen_file when dentry freed. Allow
299the support for CIFS Unix Extensions to be disabled via proc interface. 314the support for CIFS Unix Extensions to be disabled via proc interface.
300 315
301Version 0.98 316Version 0.98
@@ -637,7 +652,7 @@ versions of 2.4 kernel (now builds and works again on kernels at least as early
637Version 0.41 652Version 0.41
638------------ 653------------
639Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked 654Various 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. 655files now return the correct number of links on fstat as they are repeatedly linked and unlinked.
641 656
642Version 0.40 657Version 0.40
643------------ 658------------
@@ -704,7 +719,7 @@ session)
704and cleaned them up and made them more consistent with other cifs functions. 719and cleaned them up and made them more consistent with other cifs functions.
705 720
7067) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways 7217) 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, 722(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 723nor is the symlink support using the Unix extensions
709 724
7108) Started adding the readlink and follow_link code 7258) 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..d77abe236a67 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;
@@ -834,8 +837,21 @@ static int cifs_oplock_thread(void * dummyarg)
834 spin_unlock(&GlobalMid_Lock); 837 spin_unlock(&GlobalMid_Lock);
835 } 838 }
836 } while(!signal_pending(current)); 839 } while(!signal_pending(current));
837 complete_and_exit (&cifs_oplock_exited, 0);
838 oplockThread = NULL; 840 oplockThread = NULL;
841 complete_and_exit (&cifs_oplock_exited, 0);
842}
843
844static int cifs_dnotify_thread(void * dummyarg)
845{
846 daemonize("cifsdnotifyd");
847 allow_signal(SIGTERM);
848
849 dnotifyThread = current;
850 do {
851 set_current_state(TASK_INTERRUPTIBLE);
852 schedule_timeout(39*HZ);
853 } while(!signal_pending(current));
854 complete_and_exit (&cifs_dnotify_exited, 0);
839} 855}
840 856
841static int __init 857static int __init
@@ -884,10 +900,16 @@ init_cifs(void)
884 if (!rc) { 900 if (!rc) {
885 rc = (int)kernel_thread(cifs_oplock_thread, NULL, 901 rc = (int)kernel_thread(cifs_oplock_thread, NULL,
886 CLONE_FS | CLONE_FILES | CLONE_VM); 902 CLONE_FS | CLONE_FILES | CLONE_VM);
887 if(rc > 0) 903 if(rc > 0) {
888 return 0; 904 rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
889 else 905 CLONE_FS | CLONE_FILES | CLONE_VM);
906 if(rc > 0)
907 return 0;
908 else
909 cERROR(1,("error %d create dnotify thread", rc));
910 } else {
890 cERROR(1,("error %d create oplock thread",rc)); 911 cERROR(1,("error %d create oplock thread",rc));
912 }
891 } 913 }
892 cifs_destroy_request_bufs(); 914 cifs_destroy_request_bufs();
893 } 915 }
@@ -916,6 +938,10 @@ exit_cifs(void)
916 send_sig(SIGTERM, oplockThread, 1); 938 send_sig(SIGTERM, oplockThread, 1);
917 wait_for_completion(&cifs_oplock_exited); 939 wait_for_completion(&cifs_oplock_exited);
918 } 940 }
941 if(dnotifyThread) {
942 send_sig(SIGTERM, dnotifyThread, 1);
943 wait_for_completion(&cifs_dnotify_exited);
944 }
919} 945}
920 946
921MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); 947MODULE_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..656b78ddf674 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,9 +218,17 @@ 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
229extern int SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
230 const int netfid, unsigned int count,
231 const __u64 lseek, unsigned int *nbytes, char **buf);
213extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 232extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
214 const int netfid, unsigned int count, 233 const int netfid, unsigned int count,
215 const __u64 lseek, unsigned int *nbytes, char **buf); 234 const __u64 lseek, unsigned int *nbytes, char **buf);
@@ -222,7 +241,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
222extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 241extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
223 const int netfid, const unsigned int count, 242 const int netfid, const unsigned int count,
224 const __u64 offset, unsigned int *nbytes, 243 const __u64 offset, unsigned int *nbytes,
225 const char __user *buf,const int long_op); 244 const char *buf,const int long_op);
226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 245extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
227 const unsigned char *searchName, __u64 * inode_number, 246 const unsigned char *searchName, __u64 * inode_number,
228 const struct nls_table *nls_codepage, 247 const struct nls_table *nls_codepage,
@@ -264,7 +283,8 @@ extern int CIFSSMBCopy(int xid,
264 int remap_special_chars); 283 int remap_special_chars);
265extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 284extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
266 const int notify_subdirs,const __u16 netfid, 285 const int notify_subdirs,const __u16 netfid,
267 __u32 filter, const struct nls_table *nls_codepage); 286 __u32 filter, struct file * file, int multishot,
287 const struct nls_table *nls_codepage);
268extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 288extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
269 const unsigned char *searchName, char * EAData, 289 const unsigned char *searchName, char * EAData,
270 size_t bufsize, const struct nls_table *nls_codepage, 290 size_t bufsize, const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..c8ae3ef422ba 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,17 +915,89 @@ 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;
793 return rc; 923 return rc;
794} 924}
795 925
926int
927SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
928 const int netfid, unsigned int count,
929 const __u64 lseek, unsigned int *nbytes, char **buf)
930{
931 int rc = -EACCES;
932 READX_REQ *pSMB = NULL;
933 READ_RSP *pSMBr = NULL;
934 char *pReadData = NULL;
935 int bytes_returned;
936
937 cFYI(1,("Legacy read %d bytes fid %d",count,netfid));
938
939 /* field is shorter in legacy read, only 16 bits */
940 if(count > 2048)
941 count = 2048; /* BB FIXME make this configurable */
942
943 if(lseek > 0xFFFFFFFF)
944 return -EIO; /* can not read that far into file on old server */
945
946 *nbytes = 0;
947 rc = smb_init(SMB_COM_READ_ANDX, 10, tcon, (void **) &pSMB,
948 (void **) &pSMBr);
949 if (rc)
950 return rc;
951
952 /* tcon and ses pointer are checked in smb_init */
953 if (tcon->ses->server == NULL)
954 return -ECONNABORTED;
955
956 pSMB->AndXCommand = 0xFF; /* none */
957 pSMB->Fid = netfid;
958 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
959 pSMB->Remaining = 0;
960 pSMB->MaxCount = cpu_to_le16(count);
961 pSMB->Reserved = 0; /* Must Be Zero */
962 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
963
964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
966 cifs_stats_inc(&tcon->num_reads);
967 if (rc) {
968 cERROR(1, ("Send error in legacy read = %d", rc));
969 } else {
970 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
971 data_length = data_length << 16;
972 data_length += le16_to_cpu(pSMBr->DataLength);
973 *nbytes = data_length;
974
975 /*check that DataLength would not go beyond end of SMB */
976 if ((data_length > CIFSMaxBufSize) || (data_length > count)) {
977 cFYI(1,("bad length %d for count %d",data_length,count));
978 rc = -EIO;
979 *nbytes = 0;
980 } else {
981 pReadData = (char *) (&pSMBr->hdr.Protocol) +
982 le16_to_cpu(pSMBr->DataOffset);
983/* if(rc = copy_to_user(buf, pReadData, data_length)) {
984 cERROR(1,("Faulting on read rc = %d",rc));
985 rc = -EFAULT;
986 }*/ /* can not use copy_to_user when using page cache*/
987 if(*buf)
988 memcpy(*buf,pReadData,data_length);
989 }
990 }
991 if(*buf)
992 cifs_buf_release(pSMB);
993 else
994 *buf = (char *)pSMB;
995
996 /* Note: On -EAGAIN error only caller can retry on handle based calls
997 since file handle passed in no longer valid */
998 return rc;
999}
1000
796/* If no buffer passed in, then caller wants to do the copy 1001/* If no buffer passed in, then caller wants to do the copy
797 as in the case of readpages so the SMB buffer must be 1002 as in the case of readpages so the SMB buffer must be
798 freed by the caller */ 1003 freed by the caller */
@@ -831,6 +1036,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
831 1036
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1037 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1038 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1039 cifs_stats_inc(&tcon->num_reads);
834 if (rc) { 1040 if (rc) {
835 cERROR(1, ("Send error in read = %d", rc)); 1041 cERROR(1, ("Send error in read = %d", rc));
836 } else { 1042 } else {
@@ -933,6 +1139,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
933 1139
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op); 1141 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1142 cifs_stats_inc(&tcon->num_writes);
936 if (rc) { 1143 if (rc) {
937 cFYI(1, ("Send error in write = %d", rc)); 1144 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = 0; 1145 *nbytes = 0;
@@ -951,56 +1158,70 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 1158}
952 1159
953#ifdef CONFIG_CIFS_EXPERIMENTAL 1160#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1161int
1162CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 1163 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 1164 const __u64 offset, unsigned int *nbytes, const char *buf,
957 const int long_op) 1165 const int long_op)
958{ 1166{
959 int rc = -EACCES; 1167 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 1168 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 1169 int bytes_returned;
962 /*int bytes_returned;*/ 1170 int smb_hdr_len;
963 unsigned bytes_sent; 1171 __u32 bytes_sent;
964 __u16 byte_count; 1172 __u16 byte_count;
965 1173
1174 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); 1175 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
967
968 if (rc) 1176 if (rc)
969 return rc; 1177 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 1178 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 1179 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 1180 return -ECONNABORTED;
976 1181
977 pSMB->AndXCommand = 0xFF; /* none */ 1182 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 1183 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1184 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1185 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
981 pSMB->Reserved = 0xFFFFFFFF; 1186 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 1187 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 1188 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 1189
1190 /* Can increase buffer size if buffer is big enough in some cases - ie
1191 can send more if LARGE_WRITE_X capability returned by the server and if
1192 our buffer is big enough or if we convert to iovecs on socket writes
1193 and eliminate the copy to the CIFS buffer */
1194 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1195 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1196 } else {
1197 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1198 & ~0xFF;
1199 }
1200
985 if (bytes_sent > count) 1201 if (bytes_sent > count)
986 bytes_sent = count; 1202 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1203 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1204 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1205
991 byte_count = bytes_sent + 1 /* pad */ ; 1206 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1207 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
993 pSMB->DataLengthHigh = 0; 1208 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
994 pSMB->hdr.smb_buf_length += byte_count; 1209 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1210 pSMB->hdr.smb_buf_length += bytes_sent+1;
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1211 pSMB->ByteCount = cpu_to_le16(byte_count);
996 1212
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1213 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 */ 1214 buf, bytes_sent, &bytes_returned, long_op);
1215 cifs_stats_inc(&tcon->num_writes);
999 if (rc) { 1216 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1217 cFYI(1, ("Send error in write = %d", rc));
1001 *nbytes = 0; 1218 *nbytes = 0;
1002 } else 1219 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1220 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1221 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1222 *nbytes = (*nbytes) << 16;
1223 *nbytes += le16_to_cpu(pSMBr->Count);
1224 }
1004 1225
1005 cifs_small_buf_release(pSMB); 1226 cifs_small_buf_release(pSMB);
1006 1227
@@ -1009,6 +1230,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1230
1010 return rc; 1231 return rc;
1011} 1232}
1233
1234
1012#endif /* CIFS_EXPERIMENTAL */ 1235#endif /* CIFS_EXPERIMENTAL */
1013 1236
1014int 1237int
@@ -1065,7 +1288,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1065 1288
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1290 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 1291 cifs_stats_inc(&tcon->num_locks);
1069 if (rc) { 1292 if (rc) {
1070 cFYI(1, ("Send error in Lock = %d", rc)); 1293 cFYI(1, ("Send error in Lock = %d", rc));
1071 } 1294 }
@@ -1099,6 +1322,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1099 pSMB->ByteCount = 0; 1322 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1325 cifs_stats_inc(&tcon->num_closes);
1102 if (rc) { 1326 if (rc) {
1103 if(rc!=-EINTR) { 1327 if(rc!=-EINTR) {
1104 /* EINTR is expected when user ctl-c to kill app */ 1328 /* EINTR is expected when user ctl-c to kill app */
@@ -1171,16 +1395,11 @@ renameRetry:
1171 1395
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1396 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1397 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1398 cifs_stats_inc(&tcon->num_renames);
1174 if (rc) { 1399 if (rc) {
1175 cFYI(1, ("Send error in rename = %d", rc)); 1400 cFYI(1, ("Send error in rename = %d", rc));
1176 } 1401 }
1177 1402
1178#ifdef CONFIG_CIFS_STATS
1179 else {
1180 atomic_inc(&tcon->num_renames);
1181 }
1182#endif
1183
1184 cifs_buf_release(pSMB); 1403 cifs_buf_release(pSMB);
1185 1404
1186 if (rc == -EAGAIN) 1405 if (rc == -EAGAIN)
@@ -1255,14 +1474,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1255 pSMB->ByteCount = cpu_to_le16(byte_count); 1474 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, 1475 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1477 cifs_stats_inc(&pTcon->num_t2renames);
1258 if (rc) { 1478 if (rc) {
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc)); 1479 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1260 } 1480 }
1261#ifdef CONFIG_CIFS_STATS 1481
1262 else {
1263 atomic_inc(&pTcon->num_t2renames);
1264 }
1265#endif
1266 cifs_buf_release(pSMB); 1482 cifs_buf_release(pSMB);
1267 1483
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls 1484 /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -1416,6 +1632,7 @@ createSymLinkRetry:
1416 pSMB->ByteCount = cpu_to_le16(byte_count); 1632 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1635 cifs_stats_inc(&tcon->num_symlinks);
1419 if (rc) { 1636 if (rc) {
1420 cFYI(1, 1637 cFYI(1,
1421 ("Send error in SetPathInfo (create symlink) = %d", 1638 ("Send error in SetPathInfo (create symlink) = %d",
@@ -1505,6 +1722,7 @@ createHardLinkRetry:
1505 pSMB->ByteCount = cpu_to_le16(byte_count); 1722 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1725 cifs_stats_inc(&tcon->num_hardlinks);
1508 if (rc) { 1726 if (rc) {
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); 1727 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 } 1728 }
@@ -1575,6 +1793,7 @@ winCreateHardLinkRetry:
1575 1793
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1795 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1796 cifs_stats_inc(&tcon->num_hardlinks);
1578 if (rc) { 1797 if (rc) {
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); 1798 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1580 } 1799 }
@@ -1775,8 +1994,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1994 }
1776 } 1995 }
1777qreparse_out: 1996qreparse_out:
1778 if (pSMB) 1997 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1998
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1999 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 2000 since file handle passed in no longer valid */
@@ -2165,6 +2383,65 @@ GetExtAttrOut:
2165 2383
2166#endif /* CONFIG_POSIX */ 2384#endif /* CONFIG_POSIX */
2167 2385
2386/* Legacy Query Path Information call for lookup to old servers such
2387 as Win9x/WinME */
2388int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2389 const unsigned char *searchName,
2390 FILE_ALL_INFO * pFinfo,
2391 const struct nls_table *nls_codepage, int remap)
2392{
2393 QUERY_INFORMATION_REQ * pSMB;
2394 QUERY_INFORMATION_RSP * pSMBr;
2395 int rc = 0;
2396 int bytes_returned;
2397 int name_len;
2398
2399 cFYI(1, ("In SMBQPath path %s", searchName));
2400QInfRetry:
2401 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2402 (void **) &pSMBr);
2403 if (rc)
2404 return rc;
2405
2406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 name_len =
2408 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2409 PATH_MAX, nls_codepage, remap);
2410 name_len++; /* trailing null */
2411 name_len *= 2;
2412 } else {
2413 name_len = strnlen(searchName, PATH_MAX);
2414 name_len++; /* trailing null */
2415 strncpy(pSMB->FileName, searchName, name_len);
2416 }
2417 pSMB->BufferFormat = 0x04;
2418 name_len++; /* account for buffer type byte */
2419 pSMB->hdr.smb_buf_length += (__u16) name_len;
2420 pSMB->ByteCount = cpu_to_le16(name_len);
2421
2422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2424 if (rc) {
2425 cFYI(1, ("Send error in QueryInfo = %d", rc));
2426 } else if (pFinfo) { /* decode response */
2427 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2428 pFinfo->AllocationSize = (__le64) pSMBr->size;
2429 pFinfo->EndOfFile = (__le64) pSMBr->size;
2430 pFinfo->Attributes = (__le32) pSMBr->attr;
2431 } else
2432 rc = -EIO; /* bad buffer passed in */
2433
2434 cifs_buf_release(pSMB);
2435
2436 if (rc == -EAGAIN)
2437 goto QInfRetry;
2438
2439 return rc;
2440}
2441
2442
2443
2444
2168int 2445int
2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2446CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName, 2447 const unsigned char *searchName,
@@ -2396,7 +2673,7 @@ findUniqueRetry:
2396 if (rc) { 2673 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2674 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2675 } else { /* decode response */
2399 2676 cifs_stats_inc(&tcon->num_ffirst);
2400 /* BB fill in */ 2677 /* BB fill in */
2401 } 2678 }
2402 2679
@@ -2414,7 +2691,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2691 const char *searchName,
2415 const struct nls_table *nls_codepage, 2692 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2693 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2694 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2695{
2419/* level 257 SMB_ */ 2696/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2697 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2718,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2718 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2719 directory name instead of a wildcard */
2443 name_len *= 2; 2720 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2721 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2722 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2723 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2724 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2732,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2732 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2733 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2734 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2735 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2736 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2737 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2738 name_len += 3;
@@ -2496,6 +2773,7 @@ findFirstRetry:
2496 2773
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2776 cifs_stats_inc(&tcon->num_ffirst);
2499 2777
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2778 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 */ 2779 /* BB Add code to handle unsupported level rc */
@@ -2617,7 +2895,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2617 2895
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 2898 cifs_stats_inc(&tcon->num_fnext);
2621 if (rc) { 2899 if (rc) {
2622 if (rc == -EBADF) { 2900 if (rc == -EBADF) {
2623 psrch_inf->endOfSearch = TRUE; 2901 psrch_inf->endOfSearch = TRUE;
@@ -2694,6 +2972,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2972 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2973 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2974 }
2975 cifs_stats_inc(&tcon->num_fclose);
2697 cifs_small_buf_release(pSMB); 2976 cifs_small_buf_release(pSMB);
2698 2977
2699 /* Since session is dead, search handle closed on server already */ 2978 /* Since session is dead, search handle closed on server already */
@@ -2827,7 +3106,10 @@ getDFSRetry:
2827 (void **) &pSMBr); 3106 (void **) &pSMBr);
2828 if (rc) 3107 if (rc)
2829 return rc; 3108 return rc;
2830 3109
3110 /* server pointer checked in called function,
3111 but should never be null here anyway */
3112 pSMB->hdr.Mid = GetNextMid(ses->server);
2831 pSMB->hdr.Tid = ses->ipc_tid; 3113 pSMB->hdr.Tid = ses->ipc_tid;
2832 pSMB->hdr.Uid = ses->Suid; 3114 pSMB->hdr.Uid = ses->Suid;
2833 if (ses->capabilities & CAP_STATUS32) { 3115 if (ses->capabilities & CAP_STATUS32) {
@@ -3257,6 +3539,77 @@ QFSUnixRetry:
3257 return rc; 3539 return rc;
3258} 3540}
3259 3541
3542int
3543CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3544{
3545/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3546 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3547 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3548 int rc = 0;
3549 int bytes_returned = 0;
3550 __u16 params, param_offset, offset, byte_count;
3551
3552 cFYI(1, ("In SETFSUnixInfo"));
3553SETFSUnixRetry:
3554 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3555 (void **) &pSMBr);
3556 if (rc)
3557 return rc;
3558
3559 params = 4; /* 2 bytes zero followed by info level. */
3560 pSMB->MaxSetupCount = 0;
3561 pSMB->Reserved = 0;
3562 pSMB->Flags = 0;
3563 pSMB->Timeout = 0;
3564 pSMB->Reserved2 = 0;
3565 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3566 offset = param_offset + params;
3567
3568 pSMB->MaxParameterCount = cpu_to_le16(4);
3569 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3570 pSMB->SetupCount = 1;
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3573 byte_count = 1 /* pad */ + params + 12;
3574
3575 pSMB->DataCount = cpu_to_le16(12);
3576 pSMB->ParameterCount = cpu_to_le16(params);
3577 pSMB->TotalDataCount = pSMB->DataCount;
3578 pSMB->TotalParameterCount = pSMB->ParameterCount;
3579 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3580 pSMB->DataOffset = cpu_to_le16(offset);
3581
3582 /* Params. */
3583 pSMB->FileNum = 0;
3584 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3585
3586 /* Data. */
3587 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3588 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3589 pSMB->ClientUnixCap = cpu_to_le64(cap);
3590
3591 pSMB->hdr.smb_buf_length += byte_count;
3592 pSMB->ByteCount = cpu_to_le16(byte_count);
3593
3594 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3595 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3596 if (rc) {
3597 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3598 } else { /* decode response */
3599 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3600 if (rc) {
3601 rc = -EIO; /* bad smb */
3602 }
3603 }
3604 cifs_buf_release(pSMB);
3605
3606 if (rc == -EAGAIN)
3607 goto SETFSUnixRetry;
3608
3609 return rc;
3610}
3611
3612
3260 3613
3261int 3614int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3615CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3839,12 +4192,14 @@ setPermsRetry:
3839} 4192}
3840 4193
3841int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 4194int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3842 const int notify_subdirs, const __u16 netfid, 4195 const int notify_subdirs, const __u16 netfid,
3843 __u32 filter, const struct nls_table *nls_codepage) 4196 __u32 filter, struct file * pfile, int multishot,
4197 const struct nls_table *nls_codepage)
3844{ 4198{
3845 int rc = 0; 4199 int rc = 0;
3846 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4200 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3847 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4201 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4202 struct dir_notify_req *dnotify_req;
3848 int bytes_returned; 4203 int bytes_returned;
3849 4204
3850 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); 4205 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
@@ -3877,6 +4232,22 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, -1); 4232 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3878 if (rc) { 4233 if (rc) {
3879 cFYI(1, ("Error in Notify = %d", rc)); 4234 cFYI(1, ("Error in Notify = %d", rc));
4235 } else {
4236 /* Add file to outstanding requests */
4237 dnotify_req = (struct dir_notify_req *) kmalloc(
4238 sizeof(struct dir_notify_req), GFP_KERNEL);
4239 dnotify_req->Pid = pSMB->hdr.Pid;
4240 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4241 dnotify_req->Mid = pSMB->hdr.Mid;
4242 dnotify_req->Tid = pSMB->hdr.Tid;
4243 dnotify_req->Uid = pSMB->hdr.Uid;
4244 dnotify_req->netfid = netfid;
4245 dnotify_req->pfile = pfile;
4246 dnotify_req->filter = filter;
4247 dnotify_req->multishot = multishot;
4248 spin_lock(&GlobalMid_Lock);
4249 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4250 spin_unlock(&GlobalMid_Lock);
3880 } 4251 }
3881 cifs_buf_release(pSMB); 4252 cifs_buf_release(pSMB);
3882 return rc; 4253 return rc;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc47a7f9..c75bae1242dc 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,
@@ -674,7 +685,7 @@ multi_t2_fnd:
674 msleep(125); 685 msleep(125);
675 } 686 }
676 687
677 if (list_empty(&server->pending_mid_q)) { 688 if (!list_empty(&server->pending_mid_q)) {
678 /* mpx threads have not exited yet give them 689 /* mpx threads have not exited yet give them
679 at least the smb send timeout time for long ops */ 690 at least the smb send timeout time for long ops */
680 /* due to delays on oplock break requests, we need 691 /* due to delays on oplock break requests, we need
@@ -711,7 +722,7 @@ multi_t2_fnd:
711 GFP_KERNEL); 722 GFP_KERNEL);
712 } 723 }
713 724
714 msleep(250); 725 complete_and_exit(&cifsd_complete, 0);
715 return 0; 726 return 0;
716} 727}
717 728
@@ -735,7 +746,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
735 toupper(system_utsname.nodename[i]); 746 toupper(system_utsname.nodename[i]);
736 } 747 }
737 vol->source_rfc1001_name[15] = 0; 748 vol->source_rfc1001_name[15] = 0;
738 749 /* null target name indicates to use *SMBSERVR default called name
750 if we end up sending RFC1001 session initialize */
751 vol->target_rfc1001_name[0] = 0;
739 vol->linux_uid = current->uid; /* current->euid instead? */ 752 vol->linux_uid = current->uid; /* current->euid instead? */
740 vol->linux_gid = current->gid; 753 vol->linux_gid = current->gid;
741 vol->dir_mode = S_IRWXUGO; 754 vol->dir_mode = S_IRWXUGO;
@@ -745,6 +758,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) */ 758 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
746 vol->rw = TRUE; 759 vol->rw = TRUE;
747 760
761 /* default is always to request posix paths. */
762 vol->posix_paths = 1;
763
748 if (!options) 764 if (!options)
749 return 1; 765 return 1;
750 766
@@ -985,7 +1001,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
985 /* The string has 16th byte zero still from 1001 /* The string has 16th byte zero still from
986 set at top of the function */ 1002 set at top of the function */
987 if((i==15) && (value[i] != 0)) 1003 if((i==15) && (value[i] != 0))
988 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); 1004 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1005 }
1006 } else if (strnicmp(data, "servern", 7) == 0) {
1007 /* servernetbiosname specified override *SMBSERVER */
1008 if (!value || !*value || (*value == ' ')) {
1009 cFYI(1,("empty server netbiosname specified"));
1010 } else {
1011 /* last byte, type, is 0x20 for servr type */
1012 memset(vol->target_rfc1001_name,0x20,16);
1013
1014 for(i=0;i<15;i++) {
1015 /* BB are there cases in which a comma can be
1016 valid in this workstation netbios name (and need
1017 special handling)? */
1018
1019 /* user or mount helper must uppercase netbiosname */
1020 if (value[i]==0)
1021 break;
1022 else
1023 vol->target_rfc1001_name[i] = value[i];
1024 }
1025 /* The string has 16th byte zero still from
1026 set at top of the function */
1027 if((i==15) && (value[i] != 0))
1028 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
989 } 1029 }
990 } else if (strnicmp(data, "credentials", 4) == 0) { 1030 } else if (strnicmp(data, "credentials", 4) == 0) {
991 /* ignore */ 1031 /* ignore */
@@ -1023,6 +1063,26 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1023 vol->remap = 1; 1063 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1064 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0; 1065 vol->remap = 0;
1066 } else if (strnicmp(data, "sfu", 3) == 0) {
1067 vol->sfu_emul = 1;
1068 } else if (strnicmp(data, "nosfu", 5) == 0) {
1069 vol->sfu_emul = 0;
1070 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1071 vol->posix_paths = 1;
1072 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1073 vol->posix_paths = 0;
1074 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1075 (strnicmp(data, "ignorecase", 10) == 0)) {
1076 vol->nocase = 1;
1077 } else if (strnicmp(data, "brl", 3) == 0) {
1078 vol->nobrl = 0;
1079 } else if (strnicmp(data, "nobrl", 5) == 0) {
1080 vol->nobrl = 1;
1081 /* turn off mandatory locking in mode
1082 if remote locking is turned off since the
1083 local vfs will do advisory */
1084 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1085 vol->file_mode = S_IALLUGO;
1026 } else if (strnicmp(data, "setuids", 7) == 0) { 1086 } else if (strnicmp(data, "setuids", 7) == 0) {
1027 vol->setuids = 1; 1087 vol->setuids = 1;
1028 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1088 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1242,7 +1302,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length)
1242 1302
1243static int 1303static int
1244ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, 1304ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1245 char * netbios_name) 1305 char * netbios_name, char * target_name)
1246{ 1306{
1247 int rc = 0; 1307 int rc = 0;
1248 int connected = 0; 1308 int connected = 0;
@@ -1320,8 +1380,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1320 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); 1380 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1321 if(ses_init_buf) { 1381 if(ses_init_buf) {
1322 ses_init_buf->trailer.session_req.called_len = 32; 1382 ses_init_buf->trailer.session_req.called_len = 32;
1323 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1383 if(target_name && (target_name[0] != 0)) {
1324 DEFAULT_CIFS_CALLED_NAME,16); 1384 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1385 target_name, 16);
1386 } else {
1387 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1388 DEFAULT_CIFS_CALLED_NAME,16);
1389 }
1390
1325 ses_init_buf->trailer.session_req.calling_len = 32; 1391 ses_init_buf->trailer.session_req.calling_len = 32;
1326 /* calling name ends in null (byte 16) from old smb 1392 /* calling name ends in null (byte 16) from old smb
1327 convention. */ 1393 convention. */
@@ -1554,7 +1620,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1554 sin_server.sin_port = htons(volume_info.port); 1620 sin_server.sin_port = htons(volume_info.port);
1555 else 1621 else
1556 sin_server.sin_port = 0; 1622 sin_server.sin_port = 0;
1557 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); 1623 rc = ipv4_connect(&sin_server,&csocket,
1624 volume_info.source_rfc1001_name,
1625 volume_info.target_rfc1001_name);
1558 if (rc < 0) { 1626 if (rc < 0) {
1559 cERROR(1, 1627 cERROR(1,
1560 ("Error connecting to IPv4 socket. Aborting operation")); 1628 ("Error connecting to IPv4 socket. Aborting operation"));
@@ -1604,9 +1672,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1604 kfree(volume_info.password); 1672 kfree(volume_info.password);
1605 FreeXid(xid); 1673 FreeXid(xid);
1606 return rc; 1674 return rc;
1607 } else 1675 }
1608 rc = 0; 1676 wait_for_completion(&cifsd_complete);
1677 rc = 0;
1609 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1678 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1679 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1610 srvTcp->sequence_number = 0; 1680 srvTcp->sequence_number = 0;
1611 } 1681 }
1612 } 1682 }
@@ -1660,8 +1730,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1660 else 1730 else
1661 cifs_sb->wsize = CIFSMaxBufSize; /* default */ 1731 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1662 if(cifs_sb->rsize < PAGE_CACHE_SIZE) { 1732 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1663 cifs_sb->rsize = PAGE_CACHE_SIZE; 1733 cifs_sb->rsize = PAGE_CACHE_SIZE;
1664 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); 1734 /* Windows ME does this */
1735 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1665 } 1736 }
1666 cifs_sb->mnt_uid = volume_info.linux_uid; 1737 cifs_sb->mnt_uid = volume_info.linux_uid;
1667 cifs_sb->mnt_gid = volume_info.linux_gid; 1738 cifs_sb->mnt_gid = volume_info.linux_gid;
@@ -1679,8 +1750,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 1750 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1680 if(volume_info.no_xattr) 1751 if(volume_info.no_xattr)
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1752 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1753 if(volume_info.sfu_emul)
1754 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1755 if(volume_info.nobrl)
1756 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1757
1682 if(volume_info.direct_io) { 1758 if(volume_info.direct_io) {
1683 cERROR(1,("mounting share using direct i/o")); 1759 cFYI(1,("mounting share using direct i/o"));
1684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 1760 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1685 } 1761 }
1686 1762
@@ -1694,6 +1770,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1694 to the same server share the last value passed in 1770 to the same server share the last value passed in
1695 for the retry flag is used */ 1771 for the retry flag is used */
1696 tcon->retry = volume_info.retry; 1772 tcon->retry = volume_info.retry;
1773 tcon->nocase = volume_info.nocase;
1697 } else { 1774 } else {
1698 tcon = tconInfoAlloc(); 1775 tcon = tconInfoAlloc();
1699 if (tcon == NULL) 1776 if (tcon == NULL)
@@ -1722,6 +1799,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1722 if (!rc) { 1799 if (!rc) {
1723 atomic_inc(&pSesInfo->inUse); 1800 atomic_inc(&pSesInfo->inUse);
1724 tcon->retry = volume_info.retry; 1801 tcon->retry = volume_info.retry;
1802 tcon->nocase = volume_info.nocase;
1725 } 1803 }
1726 } 1804 }
1727 } 1805 }
@@ -1743,8 +1821,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1743 spin_lock(&GlobalMid_Lock); 1821 spin_lock(&GlobalMid_Lock);
1744 srvTcp->tcpStatus = CifsExiting; 1822 srvTcp->tcpStatus = CifsExiting;
1745 spin_unlock(&GlobalMid_Lock); 1823 spin_unlock(&GlobalMid_Lock);
1746 if(srvTcp->tsk) 1824 if(srvTcp->tsk) {
1747 send_sig(SIGKILL,srvTcp->tsk,1); 1825 send_sig(SIGKILL,srvTcp->tsk,1);
1826 wait_for_completion(&cifsd_complete);
1827 }
1748 } 1828 }
1749 /* If find_unc succeeded then rc == 0 so we can not end */ 1829 /* If find_unc succeeded then rc == 0 so we can not end */
1750 if (tcon) /* up accidently freeing someone elses tcon struct */ 1830 if (tcon) /* up accidently freeing someone elses tcon struct */
@@ -1757,8 +1837,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1757 temp_rc = CIFSSMBLogoff(xid, pSesInfo); 1837 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1758 /* if the socketUseCount is now zero */ 1838 /* if the socketUseCount is now zero */
1759 if((temp_rc == -ESHUTDOWN) && 1839 if((temp_rc == -ESHUTDOWN) &&
1760 (pSesInfo->server->tsk)) 1840 (pSesInfo->server->tsk)) {
1761 send_sig(SIGKILL,pSesInfo->server->tsk,1); 1841 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1842 wait_for_completion(&cifsd_complete);
1843 }
1762 } else 1844 } else
1763 cFYI(1, ("No session or bad tcon")); 1845 cFYI(1, ("No session or bad tcon"));
1764 sesInfoFree(pSesInfo); 1846 sesInfoFree(pSesInfo);
@@ -1781,6 +1863,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1781 cFYI(1,("server negotiated posix acl support")); 1863 cFYI(1,("server negotiated posix acl support"));
1782 sb->s_flags |= MS_POSIXACL; 1864 sb->s_flags |= MS_POSIXACL;
1783 } 1865 }
1866
1867 /* Try and negotiate POSIX pathnames if we can. */
1868 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1869 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1870 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1871 cFYI(1,("negotiated posix pathnames support"));
1872 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1873 } else {
1874 cFYI(1,("posix pathnames support requested but not supported"));
1875 }
1876 }
1784 } 1877 }
1785 } 1878 }
1786 } 1879 }
@@ -1830,6 +1923,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1830 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 1923 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1831 NULL /* no tCon exists yet */ , 13 /* wct */ ); 1924 NULL /* no tCon exists yet */ , 13 /* wct */ );
1832 1925
1926 smb_buffer->Mid = GetNextMid(ses->server);
1833 pSMB->req_no_secext.AndXCommand = 0xFF; 1927 pSMB->req_no_secext.AndXCommand = 0xFF;
1834 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 1928 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1835 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 1929 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
@@ -2105,6 +2199,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2105 /* send SMBsessionSetup here */ 2199 /* send SMBsessionSetup here */
2106 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2200 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2107 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2201 NULL /* no tCon exists yet */ , 12 /* wct */ );
2202
2203 smb_buffer->Mid = GetNextMid(ses->server);
2108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2204 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2109 pSMB->req.AndXCommand = 0xFF; 2205 pSMB->req.AndXCommand = 0xFF;
2110 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 2206 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
@@ -2371,6 +2467,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2371 /* send SMBsessionSetup here */ 2467 /* send SMBsessionSetup here */
2372 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2468 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2373 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2469 NULL /* no tCon exists yet */ , 12 /* wct */ );
2470
2471 smb_buffer->Mid = GetNextMid(ses->server);
2374 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2472 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2375 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2473 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2376 2474
@@ -2713,6 +2811,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2713 /* send SMBsessionSetup here */ 2811 /* send SMBsessionSetup here */
2714 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2812 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2715 NULL /* no tCon exists yet */ , 12 /* wct */ ); 2813 NULL /* no tCon exists yet */ , 12 /* wct */ );
2814
2815 smb_buffer->Mid = GetNextMid(ses->server);
2716 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); 2816 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2717 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 2817 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2718 pSMB->req.AndXCommand = 0xFF; 2818 pSMB->req.AndXCommand = 0xFF;
@@ -3084,6 +3184,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3084 3184
3085 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, 3185 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3086 NULL /*no tid */ , 4 /*wct */ ); 3186 NULL /*no tid */ , 4 /*wct */ );
3187
3188 smb_buffer->Mid = GetNextMid(ses->server);
3087 smb_buffer->Uid = ses->Suid; 3189 smb_buffer->Uid = ses->Suid;
3088 pSMB = (TCONX_REQ *) smb_buffer; 3190 pSMB = (TCONX_REQ *) smb_buffer;
3089 pSMBr = (TCONX_RSP *) smb_buffer_response; 3191 pSMBr = (TCONX_RSP *) smb_buffer_response;
@@ -3205,8 +3307,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3205 return 0; 3307 return 0;
3206 } else if (rc == -ESHUTDOWN) { 3308 } else if (rc == -ESHUTDOWN) {
3207 cFYI(1,("Waking up socket by sending it signal")); 3309 cFYI(1,("Waking up socket by sending it signal"));
3208 if(cifsd_task) 3310 if(cifsd_task) {
3209 send_sig(SIGKILL,cifsd_task,1); 3311 send_sig(SIGKILL,cifsd_task,1);
3312 wait_for_completion(&cifsd_complete);
3313 }
3210 rc = 0; 3314 rc = 0;
3211 } /* else - we have an smb session 3315 } /* else - we have an smb session
3212 left on this socket do not kill cifsd */ 3316 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..ef455dda0473 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) {
@@ -1212,7 +1217,12 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1212 open_file->netfid, 1217 open_file->netfid,
1213 current_read_size, *poffset, 1218 current_read_size, *poffset,
1214 &bytes_read, &smb_read_data); 1219 &bytes_read, &smb_read_data);
1215 1220 if(rc == -EINVAL) {
1221 rc = SMBLegacyRead(xid, pTcon,
1222 open_file->netfid,
1223 current_read_size, *poffset,
1224 &bytes_read, &smb_read_data);
1225 }
1216 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1226 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1217 if (copy_to_user(current_offset, 1227 if (copy_to_user(current_offset,
1218 smb_read_data + 4 /* RFC1001 hdr */ 1228 smb_read_data + 4 /* RFC1001 hdr */
@@ -1235,12 +1245,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1235 return rc; 1245 return rc;
1236 } 1246 }
1237 } else { 1247 } else {
1238#ifdef CONFIG_CIFS_STATS 1248 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; 1249 *poffset += bytes_read;
1245 } 1250 }
1246 } 1251 }
@@ -1294,6 +1299,12 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1294 open_file->netfid, 1299 open_file->netfid,
1295 current_read_size, *poffset, 1300 current_read_size, *poffset,
1296 &bytes_read, &current_offset); 1301 &bytes_read, &current_offset);
1302 if(rc == -EINVAL) {
1303 rc = SMBLegacyRead(xid, pTcon,
1304 open_file->netfid,
1305 current_read_size, *poffset,
1306 &bytes_read, &current_offset);
1307 }
1297 } 1308 }
1298 if (rc || (bytes_read == 0)) { 1309 if (rc || (bytes_read == 0)) {
1299 if (total_read) { 1310 if (total_read) {
@@ -1303,12 +1314,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1303 return rc; 1314 return rc;
1304 } 1315 }
1305 } else { 1316 } else {
1306#ifdef CONFIG_CIFS_STATS 1317 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; 1318 *poffset += bytes_read;
1313 } 1319 }
1314 } 1320 }
@@ -1455,7 +1461,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1455 open_file->netfid, 1461 open_file->netfid,
1456 read_size, offset, 1462 read_size, offset,
1457 &bytes_read, &smb_read_data); 1463 &bytes_read, &smb_read_data);
1458 /* BB need to check return code here */ 1464 if (rc == -EINVAL) {
1465 rc = SMBLegacyRead(xid, pTcon,
1466 open_file->netfid,
1467 read_size, offset,
1468 &bytes_read, &smb_read_data);
1469 }
1470
1471 /* BB more RC checks ? */
1459 if (rc== -EAGAIN) { 1472 if (rc== -EAGAIN) {
1460 if (smb_read_data) { 1473 if (smb_read_data) {
1461 cifs_buf_release(smb_read_data); 1474 cifs_buf_release(smb_read_data);
@@ -1480,12 +1493,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1480 le16_to_cpu(pSMBr->DataOffset), &lru_pvec); 1493 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1481 1494
1482 i += bytes_read >> PAGE_CACHE_SHIFT; 1495 i += bytes_read >> PAGE_CACHE_SHIFT;
1483#ifdef CONFIG_CIFS_STATS 1496 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) { 1497 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1490 i++; /* account for partial page */ 1498 i++; /* account for partial page */
1491 1499
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..0485c6d6ecd5 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -166,6 +166,8 @@ 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;
170 } else if (S_ISDIR(inode->i_mode)) { 172 } else if (S_ISDIR(inode->i_mode)) {
171 cFYI(1, (" Directory inode")); 173 cFYI(1, (" Directory inode"));
@@ -213,8 +215,18 @@ int cifs_get_inode_info(struct inode **pinode,
213 pfindData = (FILE_ALL_INFO *)buf; 215 pfindData = (FILE_ALL_INFO *)buf;
214 /* could do find first instead but this returns more info */ 216 /* could do find first instead but this returns more info */
215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 217 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 218 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR); 219 CIFS_MOUNT_MAP_SPECIAL_CHR);
220 /* BB optimize code so we do not make the above call
221 when server claims no NT SMB support and the above call
222 failed at least once - set flag in tcon or mount */
223 if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
224 rc = SMBQueryInformation(xid, pTcon, search_path,
225 pfindData, cifs_sb->local_nls,
226 cifs_sb->mnt_cifs_flags &
227 CIFS_MOUNT_MAP_SPECIAL_CHR);
228 }
229
218 } 230 }
219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 231 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
220 if (rc) { 232 if (rc) {
@@ -320,6 +332,16 @@ int cifs_get_inode_info(struct inode **pinode,
320 on dirs */ 332 on dirs */
321 inode->i_mode = cifs_sb->mnt_dir_mode; 333 inode->i_mode = cifs_sb->mnt_dir_mode;
322 inode->i_mode |= S_IFDIR; 334 inode->i_mode |= S_IFDIR;
335 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
336 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
337 /* No need to le64 convert size of zero */
338 (pfindData->EndOfFile == 0)) {
339 inode->i_mode = cifs_sb->mnt_file_mode;
340 inode->i_mode |= S_IFIFO;
341/* BB Finish for SFU style symlinks and devies */
342/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
343 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
344
323 } else { 345 } else {
324 inode->i_mode |= S_IFREG; 346 inode->i_mode |= S_IFREG;
325 /* treat the dos attribute of read-only as read-only 347 /* treat the dos attribute of read-only as read-only
@@ -359,6 +381,8 @@ int cifs_get_inode_info(struct inode **pinode,
359 inode->i_fop = &cifs_file_direct_ops; 381 inode->i_fop = &cifs_file_direct_ops;
360 else 382 else
361 inode->i_fop = &cifs_file_ops; 383 inode->i_fop = &cifs_file_ops;
384 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
385 inode->i_fop->lock = NULL;
362 inode->i_data.a_ops = &cifs_addr_ops; 386 inode->i_data.a_ops = &cifs_addr_ops;
363 } else if (S_ISDIR(inode->i_mode)) { 387 } else if (S_ISDIR(inode->i_mode)) {
364 cFYI(1, (" Directory inode ")); 388 cFYI(1, (" Directory inode "));
@@ -577,7 +601,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 rc = cifs_get_inode_info(&newinode, full_path, NULL, 601 rc = cifs_get_inode_info(&newinode, full_path, NULL,
578 inode->i_sb,xid); 602 inode->i_sb,xid);
579 603
580 direntry->d_op = &cifs_dentry_ops; 604 if (pTcon->nocase)
605 direntry->d_op = &cifs_ci_dentry_ops;
606 else
607 direntry->d_op = &cifs_dentry_ops;
581 d_instantiate(direntry, newinode); 608 d_instantiate(direntry, newinode);
582 if (direntry->d_inode) 609 if (direntry->d_inode)
583 direntry->d_inode->i_nlink = 2; 610 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..9780f4ee7f12 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,14 @@ 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
192 if(isNewInode) 204 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we 205 return; /* No sense invalidating pages for new inode
194 have not started caching readahead file data yet */ 206 since have not started caching readahead file
207 data yet */
195 208
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 209 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) { 210 (local_size == tmp_inode->i_size)) {
@@ -290,6 +303,8 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
290 tmp_inode->i_fop = &cifs_file_direct_ops; 303 tmp_inode->i_fop = &cifs_file_direct_ops;
291 else 304 else
292 tmp_inode->i_fop = &cifs_file_ops; 305 tmp_inode->i_fop = &cifs_file_ops;
306 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
307 tmp_inode->i_fop->lock = NULL;
293 tmp_inode->i_data.a_ops = &cifs_addr_ops; 308 tmp_inode->i_data.a_ops = &cifs_addr_ops;
294 309
295 if(isNewInode) 310 if(isNewInode)
@@ -374,7 +389,7 @@ ffirst_retry:
374 389
375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 390 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
376 &cifsFile->netfid, &cifsFile->srch_inf, 391 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 392 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
378 if(rc == 0) 393 if(rc == 0)
379 cifsFile->invalidHandle = FALSE; 394 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) && 395 if((rc == -EOPNOTSUPP) &&
@@ -536,7 +551,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
536 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 551 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
537 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ 552 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
538 cFYI(1,("calling findnext2")); 553 cFYI(1,("calling findnext2"));
539 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); 554 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
555 &cifsFile->srch_inf);
540 if(rc) 556 if(rc)
541 return -ENOENT; 557 return -ENOENT;
542 } 558 }
@@ -548,14 +564,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
548 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 564 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
549 smbCalcSize((struct smb_hdr *) 565 smbCalcSize((struct smb_hdr *)
550 cifsFile->srch_inf.ntwrk_buf_start); 566 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 567 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
553 - cifsFile->srch_inf.entries_in_buffer; 568 - cifsFile->srch_inf.entries_in_buffer;
554 pos_in_buf = index_to_find - first_entry_in_buffer; 569 pos_in_buf = index_to_find - first_entry_in_buffer;
555 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 570 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
556 current_entry = cifsFile->srch_inf.srch_entries_start; 571 current_entry = cifsFile->srch_inf.srch_entries_start;
557 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 572 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 */ 573 /* go entry by entry figuring out which is first */
559 /* if( . or ..) 574 /* if( . or ..)
560 skip */ 575 skip */
561 rc = cifs_entry_is_dot(current_entry,cifsFile); 576 rc = cifs_entry_is_dot(current_entry,cifsFile);
@@ -586,7 +601,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
586 *num_to_ret = 0; 601 *num_to_ret = 0;
587 } else 602 } else
588 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; 603 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
589/* dump_cifs_file_struct(file, "end fce ");*/
590 604
591 return rc; 605 return rc;
592} 606}
@@ -721,7 +735,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 735 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
722 } 736 }
723 737
724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 738 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
739 tmp_inode->i_ino,obj_type);
725 if(rc) { 740 if(rc) {
726 cFYI(1,("filldir rc = %d",rc)); 741 cFYI(1,("filldir rc = %d",rc));
727 } 742 }
@@ -805,14 +820,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
805 FreeXid(xid); 820 FreeXid(xid);
806 return -EIO; 821 return -EIO;
807 } 822 }
808/* dump_cifs_file_struct(file, "Begin rdir "); */
809 823
810 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 824 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
811 pTcon = cifs_sb->tcon; 825 pTcon = cifs_sb->tcon;
812 if(pTcon == NULL) 826 if(pTcon == NULL)
813 return -EINVAL; 827 return -EINVAL;
814 828
815/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
816 829
817 switch ((int) file->f_pos) { 830 switch ((int) file->f_pos) {
818 case 0: 831 case 0:
@@ -866,7 +879,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
866 cifsFile->search_resume_name = NULL; */ 879 cifsFile->search_resume_name = NULL; */
867 880
868 /* BB account for . and .. in f_pos as special case */ 881 /* BB account for . and .. in f_pos as special case */
869 /* dump_cifs_file_struct(file, "rdir after default ");*/
870 882
871 rc = find_cifs_entry(xid,pTcon, file, 883 rc = find_cifs_entry(xid,pTcon, file,
872 &current_entry,&num_to_fill); 884 &current_entry,&num_to_fill);
@@ -906,14 +918,14 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
906 cifs_save_resume_key(current_entry,cifsFile); 918 cifs_save_resume_key(current_entry,cifsFile);
907 break; 919 break;
908 } else 920 } else
909 current_entry = nxt_dir_entry(current_entry,end_of_smb); 921 current_entry = nxt_dir_entry(current_entry,
922 end_of_smb);
910 } 923 }
911 kfree(tmp_buf); 924 kfree(tmp_buf);
912 break; 925 break;
913 } /* end switch */ 926 } /* end switch */
914 927
915rddir2_exit: 928rddir2_exit:
916 /* dump_cifs_file_struct(file, "end rdir "); */
917 FreeXid(xid); 929 FreeXid(xid);
918 return rc; 930 return rc;
919} 931}
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: