diff options
-rw-r--r-- | fs/cifs/AUTHORS | 4 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 32 | ||||
-rw-r--r-- | fs/cifs/README | 7 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 38 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 38 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 85 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 166 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 29 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 505 | ||||
-rw-r--r-- | fs/cifs/connect.c | 143 | ||||
-rw-r--r-- | fs/cifs/dir.c | 108 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 8 | ||||
-rw-r--r-- | fs/cifs/file.c | 90 | ||||
-rw-r--r-- | fs/cifs/inode.c | 38 | ||||
-rw-r--r-- | fs/cifs/link.c | 5 | ||||
-rw-r--r-- | fs/cifs/misc.c | 90 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 49 | ||||
-rw-r--r-- | fs/cifs/transport.c | 227 |
21 files changed, 1378 insertions, 294 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 72fdc10dfdd7..8848e4dfa026 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS | |||
@@ -32,6 +32,10 @@ Domen Puncer | |||
32 | Jesper Juhl (in particular for lots of whitespace/formatting cleanup) | 32 | Jesper Juhl (in particular for lots of whitespace/formatting cleanup) |
33 | Vince Negri and Dave Stahl (for finding an important caching bug) | 33 | Vince Negri and Dave Stahl (for finding an important caching bug) |
34 | Adrian Bunk (kcalloc cleanups) | 34 | Adrian Bunk (kcalloc cleanups) |
35 | Miklos Szeredi | ||
36 | Kazeon team for various fixes especially for 2.4 version. | ||
37 | Asser Ferno (Change Notify support) | ||
38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup | ||
35 | 39 | ||
36 | Test case and Bug Report contributors | 40 | Test case and Bug Report contributors |
37 | ------------------------------------- | 41 | ------------------------------------- |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3196d4c4eed3..6c73f020ef40 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,8 +1,24 @@ | |||
1 | Version 1.36 | ||
2 | ------------ | ||
3 | Add support for mounting to older pre-CIFS servers such as Windows9x and ME. | ||
4 | For these older servers, add option for passing netbios name of server in | ||
5 | on mount (servernetbiosname). Add suspend support for power management, to | ||
6 | avoid cifsd thread preventing software suspend from working. | ||
7 | Add mount option for disabling the default behavior of sending byte range lock | ||
8 | requests to the server (necessary for certain applications which break with | ||
9 | mandatory lock behavior such as Evolution), and also mount option for | ||
10 | requesting case insensitive matching for path based requests (requesting | ||
11 | case sensitive is the default). | ||
12 | |||
1 | Version 1.35 | 13 | Version 1.35 |
2 | ------------ | 14 | ------------ |
3 | Add writepage performance improvements. Fix path name conversions | 15 | Add writepage performance improvements. Fix path name conversions |
4 | for long filenames on mounts which were done with "mapchars" mount option | 16 | for long filenames on mounts which were done with "mapchars" mount option |
5 | specified. | 17 | specified. Ensure multiplex ids do not collide. Fix case in which |
18 | rmmod can oops if done soon after last unmount. Fix truncated | ||
19 | search (readdir) output when resume filename was a long filename. | ||
20 | Fix filename conversion when mapchars mount option was specified and | ||
21 | filename was a long filename. | ||
6 | 22 | ||
7 | Version 1.34 | 23 | Version 1.34 |
8 | ------------ | 24 | ------------ |
@@ -11,7 +27,7 @@ Do not oops if root user kills cifs oplock kernel thread or | |||
11 | kills the cifsd thread (NB: killing the cifs kernel threads is not | 27 | kills the cifsd thread (NB: killing the cifs kernel threads is not |
12 | recommended, unmount and rmmod cifs will kill them when they are | 28 | recommended, unmount and rmmod cifs will kill them when they are |
13 | no longer needed). Fix readdir to ASCII servers (ie older servers | 29 | no longer needed). Fix readdir to ASCII servers (ie older servers |
14 | which do not support Unicode) and also require asterik. | 30 | which do not support Unicode) and also require asterisk. |
15 | Fix out of memory case in which data could be written one page | 31 | Fix out of memory case in which data could be written one page |
16 | off in the page cache. | 32 | off in the page cache. |
17 | 33 | ||
@@ -101,7 +117,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call. | |||
101 | 117 | ||
102 | Version 1.25 | 118 | Version 1.25 |
103 | ------------ | 119 | ------------ |
104 | Fix internationlization problem in cifs readdir with filenames that map to | 120 | Fix internationalization problem in cifs readdir with filenames that map to |
105 | longer UTF8 strings than the string on the wire was in Unicode. Add workaround | 121 | longer UTF8 strings than the string on the wire was in Unicode. Add workaround |
106 | for readdir to netapp servers. Fix search rewind (seek into readdir to return | 122 | for readdir to netapp servers. Fix search rewind (seek into readdir to return |
107 | non-consecutive entries). Do not do readdir when server negotiates | 123 | non-consecutive entries). Do not do readdir when server negotiates |
@@ -276,7 +292,7 @@ Fix caching problem when files opened by multiple clients in which | |||
276 | page cache could contain stale data, and write through did | 292 | page cache could contain stale data, and write through did |
277 | not occur often enough while file was still open when read ahead | 293 | not occur often enough while file was still open when read ahead |
278 | (read oplock) not allowed. Treat "sep=" when first mount option | 294 | (read oplock) not allowed. Treat "sep=" when first mount option |
279 | as an overrride of comma as the default separator between mount | 295 | as an override of comma as the default separator between mount |
280 | options. | 296 | options. |
281 | 297 | ||
282 | Version 1.01 | 298 | Version 1.01 |
@@ -286,7 +302,7 @@ Allow passwords longer than 16 bytes. Allow null password string. | |||
286 | Version 1.00 | 302 | Version 1.00 |
287 | ------------ | 303 | ------------ |
288 | Gracefully clean up failed mounts when attempting to mount to servers such as | 304 | Gracefully clean up failed mounts when attempting to mount to servers such as |
289 | Windows 98 that terminate tcp sessions during prototocol negotiation. Handle | 305 | Windows 98 that terminate tcp sessions during protocol negotiation. Handle |
290 | embedded commas in mount parsing of passwords. | 306 | embedded commas in mount parsing of passwords. |
291 | 307 | ||
292 | Version 0.99 | 308 | Version 0.99 |
@@ -295,7 +311,7 @@ Invalidate local inode cached pages on oplock break and when last file | |||
295 | instance is closed so that the client does not continue using stale local | 311 | instance is closed so that the client does not continue using stale local |
296 | copy rather than later modified server copy of file. Do not reconnect | 312 | copy rather than later modified server copy of file. Do not reconnect |
297 | when server drops the tcp session prematurely before negotiate | 313 | when server drops the tcp session prematurely before negotiate |
298 | protocol response. Fix oops in roepen_file when dentry freed. Allow | 314 | protocol response. Fix oops in reopen_file when dentry freed. Allow |
299 | the support for CIFS Unix Extensions to be disabled via proc interface. | 315 | the support for CIFS Unix Extensions to be disabled via proc interface. |
300 | 316 | ||
301 | Version 0.98 | 317 | Version 0.98 |
@@ -637,7 +653,7 @@ versions of 2.4 kernel (now builds and works again on kernels at least as early | |||
637 | Version 0.41 | 653 | Version 0.41 |
638 | ------------ | 654 | ------------ |
639 | Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked | 655 | Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked |
640 | files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked. | 656 | files now return the correct number of links on fstat as they are repeatedly linked and unlinked. |
641 | 657 | ||
642 | Version 0.40 | 658 | Version 0.40 |
643 | ------------ | 659 | ------------ |
@@ -704,7 +720,7 @@ session) | |||
704 | and cleaned them up and made them more consistent with other cifs functions. | 720 | and cleaned them up and made them more consistent with other cifs functions. |
705 | 721 | ||
706 | 7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways | 722 | 7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways |
707 | (with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed, | 723 | (with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed, |
708 | nor is the symlink support using the Unix extensions | 724 | nor is the symlink support using the Unix extensions |
709 | 725 | ||
710 | 8) Started adding the readlink and follow_link code | 726 | 8) 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 | ||
28 | struct cifs_sb_info { | 31 | struct cifs_sb_info { |
29 | struct cifsTconInfo *tcon; /* primary mount */ | 32 | struct cifsTconInfo *tcon; /* primary mount */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8cc23e7d0d5d..43fb2aafa528 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -59,6 +59,8 @@ unsigned int ntlmv2_support = 0; | |||
59 | unsigned int sign_CIFS_PDUs = 1; | 59 | unsigned int sign_CIFS_PDUs = 1; |
60 | extern struct task_struct * oplockThread; /* remove sparse warning */ | 60 | extern struct task_struct * oplockThread; /* remove sparse warning */ |
61 | struct task_struct * oplockThread = NULL; | 61 | struct task_struct * oplockThread = NULL; |
62 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ | ||
63 | struct task_struct * dnotifyThread = NULL; | ||
62 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 64 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
63 | module_param(CIFSMaxBufSize, int, 0); | 65 | module_param(CIFSMaxBufSize, int, 0); |
64 | MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); | 66 | MODULE_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); | |||
73 | MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); | 75 | MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); |
74 | 76 | ||
75 | static DECLARE_COMPLETION(cifs_oplock_exited); | 77 | static DECLARE_COMPLETION(cifs_oplock_exited); |
78 | static DECLARE_COMPLETION(cifs_dnotify_exited); | ||
76 | 79 | ||
77 | extern mempool_t *cifs_sm_req_poolp; | 80 | extern mempool_t *cifs_sm_req_poolp; |
78 | extern mempool_t *cifs_req_poolp; | 81 | extern mempool_t *cifs_req_poolp; |
@@ -781,6 +784,8 @@ static int cifs_oplock_thread(void * dummyarg) | |||
781 | 784 | ||
782 | oplockThread = current; | 785 | oplockThread = current; |
783 | do { | 786 | do { |
787 | if(try_to_freeze()) | ||
788 | continue; | ||
784 | set_current_state(TASK_INTERRUPTIBLE); | 789 | set_current_state(TASK_INTERRUPTIBLE); |
785 | 790 | ||
786 | schedule_timeout(1*HZ); | 791 | schedule_timeout(1*HZ); |
@@ -834,8 +839,23 @@ static int cifs_oplock_thread(void * dummyarg) | |||
834 | spin_unlock(&GlobalMid_Lock); | 839 | spin_unlock(&GlobalMid_Lock); |
835 | } | 840 | } |
836 | } while(!signal_pending(current)); | 841 | } while(!signal_pending(current)); |
837 | complete_and_exit (&cifs_oplock_exited, 0); | ||
838 | oplockThread = NULL; | 842 | oplockThread = NULL; |
843 | complete_and_exit (&cifs_oplock_exited, 0); | ||
844 | } | ||
845 | |||
846 | static int cifs_dnotify_thread(void * dummyarg) | ||
847 | { | ||
848 | daemonize("cifsdnotifyd"); | ||
849 | allow_signal(SIGTERM); | ||
850 | |||
851 | dnotifyThread = current; | ||
852 | do { | ||
853 | if(try_to_freeze()) | ||
854 | continue; | ||
855 | set_current_state(TASK_INTERRUPTIBLE); | ||
856 | schedule_timeout(39*HZ); | ||
857 | } while(!signal_pending(current)); | ||
858 | complete_and_exit (&cifs_dnotify_exited, 0); | ||
839 | } | 859 | } |
840 | 860 | ||
841 | static int __init | 861 | static int __init |
@@ -884,10 +904,16 @@ init_cifs(void) | |||
884 | if (!rc) { | 904 | if (!rc) { |
885 | rc = (int)kernel_thread(cifs_oplock_thread, NULL, | 905 | rc = (int)kernel_thread(cifs_oplock_thread, NULL, |
886 | CLONE_FS | CLONE_FILES | CLONE_VM); | 906 | CLONE_FS | CLONE_FILES | CLONE_VM); |
887 | if(rc > 0) | 907 | if(rc > 0) { |
888 | return 0; | 908 | rc = (int)kernel_thread(cifs_dnotify_thread, NULL, |
889 | else | 909 | CLONE_FS | CLONE_FILES | CLONE_VM); |
910 | if(rc > 0) | ||
911 | return 0; | ||
912 | else | ||
913 | cERROR(1,("error %d create dnotify thread", rc)); | ||
914 | } else { | ||
890 | cERROR(1,("error %d create oplock thread",rc)); | 915 | cERROR(1,("error %d create oplock thread",rc)); |
916 | } | ||
891 | } | 917 | } |
892 | cifs_destroy_request_bufs(); | 918 | cifs_destroy_request_bufs(); |
893 | } | 919 | } |
@@ -916,6 +942,10 @@ exit_cifs(void) | |||
916 | send_sig(SIGTERM, oplockThread, 1); | 942 | send_sig(SIGTERM, oplockThread, 1); |
917 | wait_for_completion(&cifs_oplock_exited); | 943 | wait_for_completion(&cifs_oplock_exited); |
918 | } | 944 | } |
945 | if(dnotifyThread) { | ||
946 | send_sig(SIGTERM, dnotifyThread, 1); | ||
947 | wait_for_completion(&cifs_dnotify_exited); | ||
948 | } | ||
919 | } | 949 | } |
920 | 950 | ||
921 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); | 951 | MODULE_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 */ |
83 | extern struct dentry_operations cifs_dentry_ops; | 83 | extern struct dentry_operations cifs_dentry_ops; |
84 | extern struct dentry_operations cifs_ci_dentry_ops; | ||
84 | 85 | ||
85 | /* Functions related to symlinks */ | 86 | /* Functions related to symlinks */ |
86 | extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); | 87 | extern 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); | |||
96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 97 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
97 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 98 | extern 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 | ||
112 | struct TCP_Server_Info { | 112 | struct 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 | ||
334 | static 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 | |||
345 | static 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 | |||
355 | static 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 */ |
311 | struct mid_q_entry { | 371 | struct 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 */ | ||
395 | struct 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 | ||
400 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; | 474 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; |
401 | 475 | ||
476 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ | ||
477 | GLOBAL_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 */ | ||
686 | typedef 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 | |||
704 | typedef 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 */ | ||
723 | typedef 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 | |||
672 | typedef struct smb_com_write_req { | 741 | typedef 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 */ | ||
773 | typedef 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 | |||
703 | typedef struct smb_com_read_req { | 787 | typedef 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 | ||
963 | typedef 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 | |||
970 | typedef 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 | |||
879 | typedef struct smb_com_setattr_req { | 979 | typedef 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 | ||
1517 | typedef 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 | |||
1544 | typedef 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 | |||
1414 | typedef struct smb_com_transaction2_get_dfs_refer_req { | 1551 | typedef 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 | |||
1560 | typedef struct { | 1705 | typedef struct { |
1561 | /* For undefined recommended transfer size return -1 in that field */ | 1706 | /* For undefined recommended transfer size return -1 in that field */ |
1562 | __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ | 1707 | __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ |
@@ -1907,18 +2052,17 @@ struct data_blob { | |||
1907 | perhaps add a CreateDevice - to create Pipes and other special .inodes | 2052 | perhaps add a CreateDevice - to create Pipes and other special .inodes |
1908 | Also note POSIX open flags | 2053 | Also note POSIX open flags |
1909 | 2) Close - to return the last write time to do cache across close more safely | 2054 | 2) Close - to return the last write time to do cache across close more safely |
1910 | 3) PosixQFSInfo - to return statfs info | 2055 | 3) FindFirst return unique inode number - what about resume key, two |
1911 | 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes) | 2056 | forms short (matches readdir) and full (enough info to cache inodes) |
1912 | 5) Mkdir - set mode | 2057 | 4) Mkdir - set mode |
1913 | 2058 | ||
1914 | And under consideration: | 2059 | And under consideration: |
1915 | 6) FindClose2 (return nanosecond timestamp ??) | 2060 | 5) FindClose2 (return nanosecond timestamp ??) |
1916 | 7) Use nanosecond timestamps throughout all time fields if | 2061 | 6) Use nanosecond timestamps throughout all time fields if |
1917 | corresponding attribute flag is set | 2062 | corresponding attribute flag is set |
1918 | 8) sendfile - handle based copy | 2063 | 7) sendfile - handle based copy |
1919 | 9) Direct i/o | 2064 | 8) Direct i/o |
1920 | 10) "POSIX ACL" support | 2065 | 9) Misc fcntls? |
1921 | 11) Misc fcntls? | ||
1922 | 2066 | ||
1923 | what about fixing 64 bit alignment | 2067 | what about fixing 64 bit alignment |
1924 | 2068 | ||
@@ -1974,7 +2118,7 @@ struct data_blob { | |||
1974 | 2118 | ||
1975 | */ | 2119 | */ |
1976 | 2120 | ||
1977 | /* xsymlink is a symlink format that can be used | 2121 | /* xsymlink is a symlink format (used by MacOS) that can be used |
1978 | to save symlink info in a regular file when | 2122 | to save symlink info in a regular file when |
1979 | mounted to operating systems that do not | 2123 | mounted to operating systems that do not |
1980 | support the cifs Unix extensions or EAs (for xattr | 2124 | support the cifs Unix extensions or EAs (for xattr |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index ea239dea571e..6943f7c6de08 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -47,6 +47,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | |||
47 | struct smb_hdr * /* input */ , | 47 | struct smb_hdr * /* input */ , |
48 | struct smb_hdr * /* out */ , | 48 | struct smb_hdr * /* out */ , |
49 | int * /* bytes returned */ , const int long_op); | 49 | int * /* bytes returned */ , const int long_op); |
50 | extern 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); | ||
50 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); | 54 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); |
51 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); | 55 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); |
52 | extern int is_valid_oplock_break(struct smb_hdr *smb); | 56 | extern int is_valid_oplock_break(struct smb_hdr *smb); |
@@ -57,9 +61,9 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length, | |||
57 | extern int cifs_inet_pton(int, char * source, void *dst); | 61 | extern int cifs_inet_pton(int, char * source, void *dst); |
58 | extern int map_smb_to_linux_error(struct smb_hdr *smb); | 62 | extern int map_smb_to_linux_error(struct smb_hdr *smb); |
59 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 63 | extern 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 | ); | 66 | extern __u16 GetNextMid(struct TCP_Server_Info *server); |
63 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, | 67 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, |
64 | struct cifsTconInfo *); | 68 | struct cifsTconInfo *); |
65 | extern void DeleteOplockQEntry(struct oplock_q_entry *); | 69 | extern void DeleteOplockQEntry(struct oplock_q_entry *); |
@@ -89,7 +93,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
89 | 93 | ||
90 | extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 94 | extern 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 | ||
94 | extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 98 | extern 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); |
108 | extern 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 | ||
105 | extern int CIFSSMBUnixQPathInfo(const int xid, | 113 | extern 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); |
126 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 134 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
127 | struct kstatfs *FSData); | 135 | struct kstatfs *FSData); |
136 | extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | ||
137 | __u64 cap); | ||
138 | |||
128 | extern int CIFSSMBQFSAttributeInfo(const int xid, | 139 | extern int CIFSSMBQFSAttributeInfo(const int xid, |
129 | struct cifsTconInfo *tcon); | 140 | struct cifsTconInfo *tcon); |
130 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); | 141 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); |
@@ -207,6 +218,11 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | |||
207 | const int access_flags, const int omode, | 218 | const int access_flags, const int omode, |
208 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 219 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, |
209 | const struct nls_table *nls_codepage, int remap); | 220 | const struct nls_table *nls_codepage, int remap); |
221 | extern 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); | ||
210 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, | 226 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, |
211 | const int smb_file_id); | 227 | const int smb_file_id); |
212 | 228 | ||
@@ -222,7 +238,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
222 | extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 238 | extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, |
223 | const int netfid, const unsigned int count, | 239 | const int netfid, const unsigned int count, |
224 | const __u64 offset, unsigned int *nbytes, | 240 | const __u64 offset, unsigned int *nbytes, |
225 | const char __user *buf,const int long_op); | 241 | const char *buf,const int long_op); |
226 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 242 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
227 | const unsigned char *searchName, __u64 * inode_number, | 243 | const unsigned char *searchName, __u64 * inode_number, |
228 | const struct nls_table *nls_codepage, | 244 | const struct nls_table *nls_codepage, |
@@ -264,7 +280,8 @@ extern int CIFSSMBCopy(int xid, | |||
264 | int remap_special_chars); | 280 | int remap_special_chars); |
265 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 281 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, |
266 | const int notify_subdirs,const __u16 netfid, | 282 | const int notify_subdirs,const __u16 netfid, |
267 | __u32 filter, const struct nls_table *nls_codepage); | 283 | __u32 filter, struct file * file, int multishot, |
284 | const struct nls_table *nls_codepage); | ||
268 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 285 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, |
269 | const unsigned char *searchName, char * EAData, | 286 | const unsigned char *searchName, char * EAData, |
270 | size_t bufsize, const struct nls_table *nls_codepage, | 287 | size_t bufsize, const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0db0b313d715..b8830118f09a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -166,11 +166,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
166 | 166 | ||
167 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); | 167 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); |
168 | 168 | ||
169 | #ifdef CONFIG_CIFS_STATS | 169 | if(tcon != NULL) |
170 | if(tcon != NULL) { | 170 | cifs_stats_inc(&tcon->num_smbs_sent); |
171 | atomic_inc(&tcon->num_smbs_sent); | 171 | |
172 | } | ||
173 | #endif /* CONFIG_CIFS_STATS */ | ||
174 | return rc; | 172 | return rc; |
175 | } | 173 | } |
176 | 174 | ||
@@ -269,11 +267,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
269 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, | 267 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, |
270 | wct /*wct */ ); | 268 | wct /*wct */ ); |
271 | 269 | ||
272 | #ifdef CONFIG_CIFS_STATS | 270 | if(tcon != NULL) |
273 | if(tcon != NULL) { | 271 | cifs_stats_inc(&tcon->num_smbs_sent); |
274 | atomic_inc(&tcon->num_smbs_sent); | 272 | |
275 | } | ||
276 | #endif /* CONFIG_CIFS_STATS */ | ||
277 | return rc; | 273 | return rc; |
278 | } | 274 | } |
279 | 275 | ||
@@ -330,7 +326,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
330 | (void **) &pSMB, (void **) &pSMBr); | 326 | (void **) &pSMB, (void **) &pSMBr); |
331 | if (rc) | 327 | if (rc) |
332 | return rc; | 328 | return rc; |
333 | 329 | pSMB->hdr.Mid = GetNextMid(server); | |
334 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; | 330 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; |
335 | if (extended_security) | 331 | if (extended_security) |
336 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 332 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
@@ -422,8 +418,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
422 | } | 418 | } |
423 | 419 | ||
424 | } | 420 | } |
425 | if (pSMB) | 421 | |
426 | cifs_buf_release(pSMB); | 422 | cifs_buf_release(pSMB); |
427 | return rc; | 423 | return rc; |
428 | } | 424 | } |
429 | 425 | ||
@@ -518,6 +514,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
518 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ | 514 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ |
519 | 515 | ||
520 | if(ses->server) { | 516 | if(ses->server) { |
517 | pSMB->hdr.Mid = GetNextMid(ses->server); | ||
518 | |||
521 | if(ses->server->secMode & | 519 | if(ses->server->secMode & |
522 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 520 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
523 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 521 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
@@ -537,9 +535,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
537 | rc = -ESHUTDOWN; | 535 | rc = -ESHUTDOWN; |
538 | } | 536 | } |
539 | } | 537 | } |
540 | if (pSMB) | ||
541 | cifs_small_buf_release(pSMB); | ||
542 | up(&ses->sesSem); | 538 | up(&ses->sesSem); |
539 | cifs_small_buf_release(pSMB); | ||
543 | 540 | ||
544 | /* if session dead then we do not need to do ulogoff, | 541 | /* if session dead then we do not need to do ulogoff, |
545 | since server closed smb session, no sense reporting | 542 | since server closed smb session, no sense reporting |
@@ -583,14 +580,10 @@ DelFileRetry: | |||
583 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 580 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
584 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 581 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
585 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 582 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
583 | cifs_stats_inc(&tcon->num_deletes); | ||
586 | if (rc) { | 584 | if (rc) { |
587 | cFYI(1, ("Error in RMFile = %d", rc)); | 585 | cFYI(1, ("Error in RMFile = %d", rc)); |
588 | } | 586 | } |
589 | #ifdef CONFIG_CIFS_STATS | ||
590 | else { | ||
591 | atomic_inc(&tcon->num_deletes); | ||
592 | } | ||
593 | #endif | ||
594 | 587 | ||
595 | cifs_buf_release(pSMB); | 588 | cifs_buf_release(pSMB); |
596 | if (rc == -EAGAIN) | 589 | if (rc == -EAGAIN) |
@@ -632,14 +625,10 @@ RmDirRetry: | |||
632 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 625 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
633 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 626 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
634 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 627 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
628 | cifs_stats_inc(&tcon->num_rmdirs); | ||
635 | if (rc) { | 629 | if (rc) { |
636 | cFYI(1, ("Error in RMDir = %d", rc)); | 630 | cFYI(1, ("Error in RMDir = %d", rc)); |
637 | } | 631 | } |
638 | #ifdef CONFIG_CIFS_STATS | ||
639 | else { | ||
640 | atomic_inc(&tcon->num_rmdirs); | ||
641 | } | ||
642 | #endif | ||
643 | 632 | ||
644 | cifs_buf_release(pSMB); | 633 | cifs_buf_release(pSMB); |
645 | if (rc == -EAGAIN) | 634 | if (rc == -EAGAIN) |
@@ -680,20 +669,157 @@ MkDirRetry: | |||
680 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 669 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
681 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 670 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
682 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 671 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
672 | cifs_stats_inc(&tcon->num_mkdirs); | ||
683 | if (rc) { | 673 | if (rc) { |
684 | cFYI(1, ("Error in Mkdir = %d", rc)); | 674 | cFYI(1, ("Error in Mkdir = %d", rc)); |
685 | } | 675 | } |
686 | #ifdef CONFIG_CIFS_STATS | 676 | |
687 | else { | ||
688 | atomic_inc(&tcon->num_mkdirs); | ||
689 | } | ||
690 | #endif | ||
691 | cifs_buf_release(pSMB); | 677 | cifs_buf_release(pSMB); |
692 | if (rc == -EAGAIN) | 678 | if (rc == -EAGAIN) |
693 | goto MkDirRetry; | 679 | goto MkDirRetry; |
694 | return rc; | 680 | return rc; |
695 | } | 681 | } |
696 | 682 | ||
683 | static __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 | |||
713 | int | ||
714 | SMBLegacyOpen(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 | |||
727 | OldOpenRetry: | ||
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 | |||
697 | int | 823 | int |
698 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 824 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
699 | const char *fileName, const int openDisposition, | 825 | const char *fileName, const int openDisposition, |
@@ -738,7 +864,13 @@ openRetry: | |||
738 | } | 864 | } |
739 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 865 | pSMB->DesiredAccess = cpu_to_le32(access_flags); |
740 | pSMB->AllocationSize = 0; | 866 | pSMB->AllocationSize = 0; |
741 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | 867 | /* set file as system file if special file such |
868 | as fifo and server expecting SFU style and | ||
869 | no Unix extensions */ | ||
870 | if(create_options & CREATE_OPTION_SPECIAL) | ||
871 | pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); | ||
872 | else | ||
873 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | ||
742 | /* XP does not handle ATTR_POSIX_SEMANTICS */ | 874 | /* XP does not handle ATTR_POSIX_SEMANTICS */ |
743 | /* but it helps speed up case sensitive checks for other | 875 | /* but it helps speed up case sensitive checks for other |
744 | servers such as Samba */ | 876 | servers such as Samba */ |
@@ -752,7 +884,7 @@ openRetry: | |||
752 | being created */ | 884 | being created */ |
753 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | 885 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); |
754 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); | 886 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); |
755 | pSMB->CreateOptions = cpu_to_le32(create_options); | 887 | pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); |
756 | /* BB Expirement with various impersonation levels and verify */ | 888 | /* BB Expirement with various impersonation levels and verify */ |
757 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); | 889 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); |
758 | pSMB->SecurityFlags = | 890 | pSMB->SecurityFlags = |
@@ -765,6 +897,7 @@ openRetry: | |||
765 | /* long_op set to 1 to allow for oplock break timeouts */ | 897 | /* long_op set to 1 to allow for oplock break timeouts */ |
766 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 898 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
767 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 899 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); |
900 | cifs_stats_inc(&tcon->num_opens); | ||
768 | if (rc) { | 901 | if (rc) { |
769 | cFYI(1, ("Error in Open = %d", rc)); | 902 | cFYI(1, ("Error in Open = %d", rc)); |
770 | } else { | 903 | } else { |
@@ -782,11 +915,8 @@ openRetry: | |||
782 | pfile_info->EndOfFile = pSMBr->EndOfFile; | 915 | pfile_info->EndOfFile = pSMBr->EndOfFile; |
783 | pfile_info->NumberOfLinks = cpu_to_le32(1); | 916 | pfile_info->NumberOfLinks = cpu_to_le32(1); |
784 | } | 917 | } |
785 | |||
786 | #ifdef CONFIG_CIFS_STATS | ||
787 | atomic_inc(&tcon->num_opens); | ||
788 | #endif | ||
789 | } | 918 | } |
919 | |||
790 | cifs_buf_release(pSMB); | 920 | cifs_buf_release(pSMB); |
791 | if (rc == -EAGAIN) | 921 | if (rc == -EAGAIN) |
792 | goto openRetry; | 922 | goto openRetry; |
@@ -807,11 +937,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | |||
807 | READ_RSP *pSMBr = NULL; | 937 | READ_RSP *pSMBr = NULL; |
808 | char *pReadData = NULL; | 938 | char *pReadData = NULL; |
809 | int bytes_returned; | 939 | int bytes_returned; |
940 | int wct; | ||
810 | 941 | ||
811 | cFYI(1,("Reading %d bytes on fid %d",count,netfid)); | 942 | cFYI(1,("Reading %d bytes on fid %d",count,netfid)); |
943 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
944 | wct = 12; | ||
945 | else | ||
946 | wct = 10; /* old style read */ | ||
812 | 947 | ||
813 | *nbytes = 0; | 948 | *nbytes = 0; |
814 | rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, | 949 | rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, |
815 | (void **) &pSMBr); | 950 | (void **) &pSMBr); |
816 | if (rc) | 951 | if (rc) |
817 | return rc; | 952 | return rc; |
@@ -823,14 +958,26 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | |||
823 | pSMB->AndXCommand = 0xFF; /* none */ | 958 | pSMB->AndXCommand = 0xFF; /* none */ |
824 | pSMB->Fid = netfid; | 959 | pSMB->Fid = netfid; |
825 | pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); | 960 | pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); |
826 | pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); | 961 | if(wct == 12) |
962 | pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); | ||
963 | else if((lseek >> 32) > 0) /* can not handle this big offset for old */ | ||
964 | return -EIO; | ||
965 | |||
827 | pSMB->Remaining = 0; | 966 | pSMB->Remaining = 0; |
828 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); | 967 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); |
829 | pSMB->MaxCountHigh = cpu_to_le32(count >> 16); | 968 | pSMB->MaxCountHigh = cpu_to_le32(count >> 16); |
830 | pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ | 969 | if(wct == 12) |
831 | 970 | pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ | |
971 | else { | ||
972 | /* old style read */ | ||
973 | struct smb_com_readx_req * pSMBW = | ||
974 | (struct smb_com_readx_req *)pSMB; | ||
975 | pSMBW->ByteCount = 0; | ||
976 | } | ||
977 | |||
832 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 978 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
833 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 979 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
980 | cifs_stats_inc(&tcon->num_reads); | ||
834 | if (rc) { | 981 | if (rc) { |
835 | cERROR(1, ("Send error in read = %d", rc)); | 982 | cERROR(1, ("Send error in read = %d", rc)); |
836 | } else { | 983 | } else { |
@@ -876,12 +1023,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
876 | int rc = -EACCES; | 1023 | int rc = -EACCES; |
877 | WRITE_REQ *pSMB = NULL; | 1024 | WRITE_REQ *pSMB = NULL; |
878 | WRITE_RSP *pSMBr = NULL; | 1025 | WRITE_RSP *pSMBr = NULL; |
879 | int bytes_returned; | 1026 | int bytes_returned, wct; |
880 | __u32 bytes_sent; | 1027 | __u32 bytes_sent; |
881 | __u16 byte_count; | 1028 | __u16 byte_count; |
882 | 1029 | ||
883 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ | 1030 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ |
884 | rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, | 1031 | if(tcon->ses == NULL) |
1032 | return -ECONNABORTED; | ||
1033 | |||
1034 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
1035 | wct = 14; | ||
1036 | else | ||
1037 | wct = 12; | ||
1038 | |||
1039 | rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB, | ||
885 | (void **) &pSMBr); | 1040 | (void **) &pSMBr); |
886 | if (rc) | 1041 | if (rc) |
887 | return rc; | 1042 | return rc; |
@@ -892,7 +1047,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
892 | pSMB->AndXCommand = 0xFF; /* none */ | 1047 | pSMB->AndXCommand = 0xFF; /* none */ |
893 | pSMB->Fid = netfid; | 1048 | pSMB->Fid = netfid; |
894 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 1049 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
895 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 1050 | if(wct == 14) |
1051 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | ||
1052 | else if((offset >> 32) > 0) /* can not handle this big offset for old */ | ||
1053 | return -EIO; | ||
1054 | |||
896 | pSMB->Reserved = 0xFFFFFFFF; | 1055 | pSMB->Reserved = 0xFFFFFFFF; |
897 | pSMB->WriteMode = 0; | 1056 | pSMB->WriteMode = 0; |
898 | pSMB->Remaining = 0; | 1057 | pSMB->Remaining = 0; |
@@ -929,10 +1088,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
929 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1088 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
930 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1089 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
931 | pSMB->hdr.smb_buf_length += bytes_sent+1; | 1090 | pSMB->hdr.smb_buf_length += bytes_sent+1; |
932 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1091 | |
1092 | if(wct == 14) | ||
1093 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
1094 | else { /* old style write has byte count 4 bytes earlier */ | ||
1095 | struct smb_com_writex_req * pSMBW = | ||
1096 | (struct smb_com_writex_req *)pSMB; | ||
1097 | pSMBW->ByteCount = cpu_to_le16(byte_count); | ||
1098 | } | ||
933 | 1099 | ||
934 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1100 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
935 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); | 1101 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); |
1102 | cifs_stats_inc(&tcon->num_writes); | ||
936 | if (rc) { | 1103 | if (rc) { |
937 | cFYI(1, ("Send error in write = %d", rc)); | 1104 | cFYI(1, ("Send error in write = %d", rc)); |
938 | *nbytes = 0; | 1105 | *nbytes = 0; |
@@ -951,56 +1118,70 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
951 | } | 1118 | } |
952 | 1119 | ||
953 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1120 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
954 | int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1121 | int |
1122 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | ||
955 | const int netfid, const unsigned int count, | 1123 | const int netfid, const unsigned int count, |
956 | const __u64 offset, unsigned int *nbytes, const char __user *buf, | 1124 | const __u64 offset, unsigned int *nbytes, const char *buf, |
957 | const int long_op) | 1125 | const int long_op) |
958 | { | 1126 | { |
959 | int rc = -EACCES; | 1127 | int rc = -EACCES; |
960 | WRITE_REQ *pSMB = NULL; | 1128 | WRITE_REQ *pSMB = NULL; |
961 | WRITE_RSP *pSMBr = NULL; | 1129 | int bytes_returned; |
962 | /*int bytes_returned;*/ | 1130 | int smb_hdr_len; |
963 | unsigned bytes_sent; | 1131 | __u32 bytes_sent; |
964 | __u16 byte_count; | 1132 | __u16 byte_count; |
965 | 1133 | ||
1134 | cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */ | ||
966 | rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); | 1135 | rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); |
967 | |||
968 | if (rc) | 1136 | if (rc) |
969 | return rc; | 1137 | return rc; |
970 | |||
971 | pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */ | ||
972 | |||
973 | /* tcon and ses pointer are checked in smb_init */ | 1138 | /* tcon and ses pointer are checked in smb_init */ |
974 | if (tcon->ses->server == NULL) | 1139 | if (tcon->ses->server == NULL) |
975 | return -ECONNABORTED; | 1140 | return -ECONNABORTED; |
976 | 1141 | ||
977 | pSMB->AndXCommand = 0xFF; /* none */ | 1142 | pSMB->AndXCommand = 0xFF; /* none */ |
978 | pSMB->Fid = netfid; | 1143 | pSMB->Fid = netfid; |
979 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 1144 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
980 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 1145 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); |
981 | pSMB->Reserved = 0xFFFFFFFF; | 1146 | pSMB->Reserved = 0xFFFFFFFF; |
982 | pSMB->WriteMode = 0; | 1147 | pSMB->WriteMode = 0; |
983 | pSMB->Remaining = 0; | 1148 | pSMB->Remaining = 0; |
984 | bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; | 1149 | |
1150 | /* Can increase buffer size if buffer is big enough in some cases - ie | ||
1151 | can send more if LARGE_WRITE_X capability returned by the server and if | ||
1152 | our buffer is big enough or if we convert to iovecs on socket writes | ||
1153 | and eliminate the copy to the CIFS buffer */ | ||
1154 | if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) { | ||
1155 | bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count); | ||
1156 | } else { | ||
1157 | bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) | ||
1158 | & ~0xFF; | ||
1159 | } | ||
1160 | |||
985 | if (bytes_sent > count) | 1161 | if (bytes_sent > count) |
986 | bytes_sent = count; | 1162 | bytes_sent = count; |
987 | pSMB->DataLengthHigh = 0; | ||
988 | pSMB->DataOffset = | 1163 | pSMB->DataOffset = |
989 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); | 1164 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); |
990 | 1165 | ||
991 | byte_count = bytes_sent + 1 /* pad */ ; | 1166 | byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */ |
992 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent); | 1167 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
993 | pSMB->DataLengthHigh = 0; | 1168 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
994 | pSMB->hdr.smb_buf_length += byte_count; | 1169 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ |
1170 | pSMB->hdr.smb_buf_length += bytes_sent+1; | ||
995 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1171 | pSMB->ByteCount = cpu_to_le16(byte_count); |
996 | 1172 | ||
997 | /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1173 | rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len, |
998 | (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ | 1174 | buf, bytes_sent, &bytes_returned, long_op); |
1175 | cifs_stats_inc(&tcon->num_writes); | ||
999 | if (rc) { | 1176 | if (rc) { |
1000 | cFYI(1, ("Send error in write2 (large write) = %d", rc)); | 1177 | cFYI(1, ("Send error in write = %d", rc)); |
1001 | *nbytes = 0; | 1178 | *nbytes = 0; |
1002 | } else | 1179 | } else { |
1003 | *nbytes = le16_to_cpu(pSMBr->Count); | 1180 | WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; |
1181 | *nbytes = le16_to_cpu(pSMBr->CountHigh); | ||
1182 | *nbytes = (*nbytes) << 16; | ||
1183 | *nbytes += le16_to_cpu(pSMBr->Count); | ||
1184 | } | ||
1004 | 1185 | ||
1005 | cifs_small_buf_release(pSMB); | 1186 | cifs_small_buf_release(pSMB); |
1006 | 1187 | ||
@@ -1009,6 +1190,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1009 | 1190 | ||
1010 | return rc; | 1191 | return rc; |
1011 | } | 1192 | } |
1193 | |||
1194 | |||
1012 | #endif /* CIFS_EXPERIMENTAL */ | 1195 | #endif /* CIFS_EXPERIMENTAL */ |
1013 | 1196 | ||
1014 | int | 1197 | int |
@@ -1065,7 +1248,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1065 | 1248 | ||
1066 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1249 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1067 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1250 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); |
1068 | 1251 | cifs_stats_inc(&tcon->num_locks); | |
1069 | if (rc) { | 1252 | if (rc) { |
1070 | cFYI(1, ("Send error in Lock = %d", rc)); | 1253 | cFYI(1, ("Send error in Lock = %d", rc)); |
1071 | } | 1254 | } |
@@ -1099,6 +1282,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1099 | pSMB->ByteCount = 0; | 1282 | pSMB->ByteCount = 0; |
1100 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1283 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1101 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1284 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1285 | cifs_stats_inc(&tcon->num_closes); | ||
1102 | if (rc) { | 1286 | if (rc) { |
1103 | if(rc!=-EINTR) { | 1287 | if(rc!=-EINTR) { |
1104 | /* EINTR is expected when user ctl-c to kill app */ | 1288 | /* EINTR is expected when user ctl-c to kill app */ |
@@ -1171,16 +1355,11 @@ renameRetry: | |||
1171 | 1355 | ||
1172 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1356 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1173 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1357 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1358 | cifs_stats_inc(&tcon->num_renames); | ||
1174 | if (rc) { | 1359 | if (rc) { |
1175 | cFYI(1, ("Send error in rename = %d", rc)); | 1360 | cFYI(1, ("Send error in rename = %d", rc)); |
1176 | } | 1361 | } |
1177 | 1362 | ||
1178 | #ifdef CONFIG_CIFS_STATS | ||
1179 | else { | ||
1180 | atomic_inc(&tcon->num_renames); | ||
1181 | } | ||
1182 | #endif | ||
1183 | |||
1184 | cifs_buf_release(pSMB); | 1363 | cifs_buf_release(pSMB); |
1185 | 1364 | ||
1186 | if (rc == -EAGAIN) | 1365 | if (rc == -EAGAIN) |
@@ -1255,14 +1434,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | |||
1255 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1434 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1256 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 1435 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
1257 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1436 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1437 | cifs_stats_inc(&pTcon->num_t2renames); | ||
1258 | if (rc) { | 1438 | if (rc) { |
1259 | cFYI(1,("Send error in Rename (by file handle) = %d", rc)); | 1439 | cFYI(1,("Send error in Rename (by file handle) = %d", rc)); |
1260 | } | 1440 | } |
1261 | #ifdef CONFIG_CIFS_STATS | 1441 | |
1262 | else { | ||
1263 | atomic_inc(&pTcon->num_t2renames); | ||
1264 | } | ||
1265 | #endif | ||
1266 | cifs_buf_release(pSMB); | 1442 | cifs_buf_release(pSMB); |
1267 | 1443 | ||
1268 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1444 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
@@ -1416,6 +1592,7 @@ createSymLinkRetry: | |||
1416 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1592 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1417 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1593 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1418 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1594 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1595 | cifs_stats_inc(&tcon->num_symlinks); | ||
1419 | if (rc) { | 1596 | if (rc) { |
1420 | cFYI(1, | 1597 | cFYI(1, |
1421 | ("Send error in SetPathInfo (create symlink) = %d", | 1598 | ("Send error in SetPathInfo (create symlink) = %d", |
@@ -1505,6 +1682,7 @@ createHardLinkRetry: | |||
1505 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1682 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1506 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1683 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1507 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1684 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1685 | cifs_stats_inc(&tcon->num_hardlinks); | ||
1508 | if (rc) { | 1686 | if (rc) { |
1509 | cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); | 1687 | cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); |
1510 | } | 1688 | } |
@@ -1575,6 +1753,7 @@ winCreateHardLinkRetry: | |||
1575 | 1753 | ||
1576 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1754 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1577 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1755 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1756 | cifs_stats_inc(&tcon->num_hardlinks); | ||
1578 | if (rc) { | 1757 | if (rc) { |
1579 | cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); | 1758 | cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); |
1580 | } | 1759 | } |
@@ -1775,8 +1954,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1775 | } | 1954 | } |
1776 | } | 1955 | } |
1777 | qreparse_out: | 1956 | qreparse_out: |
1778 | if (pSMB) | 1957 | cifs_buf_release(pSMB); |
1779 | cifs_buf_release(pSMB); | ||
1780 | 1958 | ||
1781 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1959 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1782 | since file handle passed in no longer valid */ | 1960 | since file handle passed in no longer valid */ |
@@ -2165,6 +2343,65 @@ GetExtAttrOut: | |||
2165 | 2343 | ||
2166 | #endif /* CONFIG_POSIX */ | 2344 | #endif /* CONFIG_POSIX */ |
2167 | 2345 | ||
2346 | /* Legacy Query Path Information call for lookup to old servers such | ||
2347 | as Win9x/WinME */ | ||
2348 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | ||
2349 | const unsigned char *searchName, | ||
2350 | FILE_ALL_INFO * pFinfo, | ||
2351 | const struct nls_table *nls_codepage, int remap) | ||
2352 | { | ||
2353 | QUERY_INFORMATION_REQ * pSMB; | ||
2354 | QUERY_INFORMATION_RSP * pSMBr; | ||
2355 | int rc = 0; | ||
2356 | int bytes_returned; | ||
2357 | int name_len; | ||
2358 | |||
2359 | cFYI(1, ("In SMBQPath path %s", searchName)); | ||
2360 | QInfRetry: | ||
2361 | rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, | ||
2362 | (void **) &pSMBr); | ||
2363 | if (rc) | ||
2364 | return rc; | ||
2365 | |||
2366 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
2367 | name_len = | ||
2368 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, | ||
2369 | PATH_MAX, nls_codepage, remap); | ||
2370 | name_len++; /* trailing null */ | ||
2371 | name_len *= 2; | ||
2372 | } else { | ||
2373 | name_len = strnlen(searchName, PATH_MAX); | ||
2374 | name_len++; /* trailing null */ | ||
2375 | strncpy(pSMB->FileName, searchName, name_len); | ||
2376 | } | ||
2377 | pSMB->BufferFormat = 0x04; | ||
2378 | name_len++; /* account for buffer type byte */ | ||
2379 | pSMB->hdr.smb_buf_length += (__u16) name_len; | ||
2380 | pSMB->ByteCount = cpu_to_le16(name_len); | ||
2381 | |||
2382 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
2383 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
2384 | if (rc) { | ||
2385 | cFYI(1, ("Send error in QueryInfo = %d", rc)); | ||
2386 | } else if (pFinfo) { /* decode response */ | ||
2387 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); | ||
2388 | pFinfo->AllocationSize = (__le64) pSMBr->size; | ||
2389 | pFinfo->EndOfFile = (__le64) pSMBr->size; | ||
2390 | pFinfo->Attributes = (__le32) pSMBr->attr; | ||
2391 | } else | ||
2392 | rc = -EIO; /* bad buffer passed in */ | ||
2393 | |||
2394 | cifs_buf_release(pSMB); | ||
2395 | |||
2396 | if (rc == -EAGAIN) | ||
2397 | goto QInfRetry; | ||
2398 | |||
2399 | return rc; | ||
2400 | } | ||
2401 | |||
2402 | |||
2403 | |||
2404 | |||
2168 | int | 2405 | int |
2169 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2406 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
2170 | const unsigned char *searchName, | 2407 | const unsigned char *searchName, |
@@ -2396,7 +2633,7 @@ findUniqueRetry: | |||
2396 | if (rc) { | 2633 | if (rc) { |
2397 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); | 2634 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); |
2398 | } else { /* decode response */ | 2635 | } else { /* decode response */ |
2399 | 2636 | cifs_stats_inc(&tcon->num_ffirst); | |
2400 | /* BB fill in */ | 2637 | /* BB fill in */ |
2401 | } | 2638 | } |
2402 | 2639 | ||
@@ -2414,7 +2651,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | |||
2414 | const char *searchName, | 2651 | const char *searchName, |
2415 | const struct nls_table *nls_codepage, | 2652 | const struct nls_table *nls_codepage, |
2416 | __u16 * pnetfid, | 2653 | __u16 * pnetfid, |
2417 | struct cifs_search_info * psrch_inf, int remap) | 2654 | struct cifs_search_info * psrch_inf, int remap, const char dirsep) |
2418 | { | 2655 | { |
2419 | /* level 257 SMB_ */ | 2656 | /* level 257 SMB_ */ |
2420 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; | 2657 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; |
@@ -2441,7 +2678,7 @@ findFirstRetry: | |||
2441 | it got remapped to 0xF03A as if it were part of the | 2678 | it got remapped to 0xF03A as if it were part of the |
2442 | directory name instead of a wildcard */ | 2679 | directory name instead of a wildcard */ |
2443 | name_len *= 2; | 2680 | name_len *= 2; |
2444 | pSMB->FileName[name_len] = '\\'; | 2681 | pSMB->FileName[name_len] = dirsep; |
2445 | pSMB->FileName[name_len+1] = 0; | 2682 | pSMB->FileName[name_len+1] = 0; |
2446 | pSMB->FileName[name_len+2] = '*'; | 2683 | pSMB->FileName[name_len+2] = '*'; |
2447 | pSMB->FileName[name_len+3] = 0; | 2684 | pSMB->FileName[name_len+3] = 0; |
@@ -2455,7 +2692,7 @@ findFirstRetry: | |||
2455 | if(name_len > buffersize-header) | 2692 | if(name_len > buffersize-header) |
2456 | free buffer exit; BB */ | 2693 | free buffer exit; BB */ |
2457 | strncpy(pSMB->FileName, searchName, name_len); | 2694 | strncpy(pSMB->FileName, searchName, name_len); |
2458 | pSMB->FileName[name_len] = '\\'; | 2695 | pSMB->FileName[name_len] = dirsep; |
2459 | pSMB->FileName[name_len+1] = '*'; | 2696 | pSMB->FileName[name_len+1] = '*'; |
2460 | pSMB->FileName[name_len+2] = 0; | 2697 | pSMB->FileName[name_len+2] = 0; |
2461 | name_len += 3; | 2698 | name_len += 3; |
@@ -2496,6 +2733,7 @@ findFirstRetry: | |||
2496 | 2733 | ||
2497 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2734 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2498 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2735 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
2736 | cifs_stats_inc(&tcon->num_ffirst); | ||
2499 | 2737 | ||
2500 | if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ | 2738 | if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ |
2501 | /* BB Add code to handle unsupported level rc */ | 2739 | /* BB Add code to handle unsupported level rc */ |
@@ -2617,7 +2855,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
2617 | 2855 | ||
2618 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2856 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2619 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2857 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
2620 | 2858 | cifs_stats_inc(&tcon->num_fnext); | |
2621 | if (rc) { | 2859 | if (rc) { |
2622 | if (rc == -EBADF) { | 2860 | if (rc == -EBADF) { |
2623 | psrch_inf->endOfSearch = TRUE; | 2861 | psrch_inf->endOfSearch = TRUE; |
@@ -2694,6 +2932,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle | |||
2694 | if (rc) { | 2932 | if (rc) { |
2695 | cERROR(1, ("Send error in FindClose = %d", rc)); | 2933 | cERROR(1, ("Send error in FindClose = %d", rc)); |
2696 | } | 2934 | } |
2935 | cifs_stats_inc(&tcon->num_fclose); | ||
2697 | cifs_small_buf_release(pSMB); | 2936 | cifs_small_buf_release(pSMB); |
2698 | 2937 | ||
2699 | /* Since session is dead, search handle closed on server already */ | 2938 | /* Since session is dead, search handle closed on server already */ |
@@ -2827,7 +3066,10 @@ getDFSRetry: | |||
2827 | (void **) &pSMBr); | 3066 | (void **) &pSMBr); |
2828 | if (rc) | 3067 | if (rc) |
2829 | return rc; | 3068 | return rc; |
2830 | 3069 | ||
3070 | /* server pointer checked in called function, | ||
3071 | but should never be null here anyway */ | ||
3072 | pSMB->hdr.Mid = GetNextMid(ses->server); | ||
2831 | pSMB->hdr.Tid = ses->ipc_tid; | 3073 | pSMB->hdr.Tid = ses->ipc_tid; |
2832 | pSMB->hdr.Uid = ses->Suid; | 3074 | pSMB->hdr.Uid = ses->Suid; |
2833 | if (ses->capabilities & CAP_STATUS32) { | 3075 | if (ses->capabilities & CAP_STATUS32) { |
@@ -3257,6 +3499,77 @@ QFSUnixRetry: | |||
3257 | return rc; | 3499 | return rc; |
3258 | } | 3500 | } |
3259 | 3501 | ||
3502 | int | ||
3503 | CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | ||
3504 | { | ||
3505 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ | ||
3506 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; | ||
3507 | TRANSACTION2_SETFSI_RSP *pSMBr = NULL; | ||
3508 | int rc = 0; | ||
3509 | int bytes_returned = 0; | ||
3510 | __u16 params, param_offset, offset, byte_count; | ||
3511 | |||
3512 | cFYI(1, ("In SETFSUnixInfo")); | ||
3513 | SETFSUnixRetry: | ||
3514 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3515 | (void **) &pSMBr); | ||
3516 | if (rc) | ||
3517 | return rc; | ||
3518 | |||
3519 | params = 4; /* 2 bytes zero followed by info level. */ | ||
3520 | pSMB->MaxSetupCount = 0; | ||
3521 | pSMB->Reserved = 0; | ||
3522 | pSMB->Flags = 0; | ||
3523 | pSMB->Timeout = 0; | ||
3524 | pSMB->Reserved2 = 0; | ||
3525 | param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4; | ||
3526 | offset = param_offset + params; | ||
3527 | |||
3528 | pSMB->MaxParameterCount = cpu_to_le16(4); | ||
3529 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | ||
3530 | pSMB->SetupCount = 1; | ||
3531 | pSMB->Reserved3 = 0; | ||
3532 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | ||
3533 | byte_count = 1 /* pad */ + params + 12; | ||
3534 | |||
3535 | pSMB->DataCount = cpu_to_le16(12); | ||
3536 | pSMB->ParameterCount = cpu_to_le16(params); | ||
3537 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3538 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3539 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
3540 | pSMB->DataOffset = cpu_to_le16(offset); | ||
3541 | |||
3542 | /* Params. */ | ||
3543 | pSMB->FileNum = 0; | ||
3544 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO); | ||
3545 | |||
3546 | /* Data. */ | ||
3547 | pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION); | ||
3548 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | ||
3549 | pSMB->ClientUnixCap = cpu_to_le64(cap); | ||
3550 | |||
3551 | pSMB->hdr.smb_buf_length += byte_count; | ||
3552 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3553 | |||
3554 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3555 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3556 | if (rc) { | ||
3557 | cERROR(1, ("Send error in SETFSUnixInfo = %d", rc)); | ||
3558 | } else { /* decode response */ | ||
3559 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3560 | if (rc) { | ||
3561 | rc = -EIO; /* bad smb */ | ||
3562 | } | ||
3563 | } | ||
3564 | cifs_buf_release(pSMB); | ||
3565 | |||
3566 | if (rc == -EAGAIN) | ||
3567 | goto SETFSUnixRetry; | ||
3568 | |||
3569 | return rc; | ||
3570 | } | ||
3571 | |||
3572 | |||
3260 | 3573 | ||
3261 | int | 3574 | int |
3262 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3575 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |
@@ -3839,12 +4152,14 @@ setPermsRetry: | |||
3839 | } | 4152 | } |
3840 | 4153 | ||
3841 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 4154 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, |
3842 | const int notify_subdirs, const __u16 netfid, | 4155 | const int notify_subdirs, const __u16 netfid, |
3843 | __u32 filter, const struct nls_table *nls_codepage) | 4156 | __u32 filter, struct file * pfile, int multishot, |
4157 | const struct nls_table *nls_codepage) | ||
3844 | { | 4158 | { |
3845 | int rc = 0; | 4159 | int rc = 0; |
3846 | struct smb_com_transaction_change_notify_req * pSMB = NULL; | 4160 | struct smb_com_transaction_change_notify_req * pSMB = NULL; |
3847 | struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; | 4161 | struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; |
4162 | struct dir_notify_req *dnotify_req; | ||
3848 | int bytes_returned; | 4163 | int bytes_returned; |
3849 | 4164 | ||
3850 | cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); | 4165 | cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); |
@@ -3877,6 +4192,22 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
3877 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); | 4192 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); |
3878 | if (rc) { | 4193 | if (rc) { |
3879 | cFYI(1, ("Error in Notify = %d", rc)); | 4194 | cFYI(1, ("Error in Notify = %d", rc)); |
4195 | } else { | ||
4196 | /* Add file to outstanding requests */ | ||
4197 | dnotify_req = (struct dir_notify_req *) kmalloc( | ||
4198 | sizeof(struct dir_notify_req), GFP_KERNEL); | ||
4199 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
4200 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
4201 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
4202 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
4203 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
4204 | dnotify_req->netfid = netfid; | ||
4205 | dnotify_req->pfile = pfile; | ||
4206 | dnotify_req->filter = filter; | ||
4207 | dnotify_req->multishot = multishot; | ||
4208 | spin_lock(&GlobalMid_Lock); | ||
4209 | list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList); | ||
4210 | spin_unlock(&GlobalMid_Lock); | ||
3880 | } | 4211 | } |
3881 | cifs_buf_release(pSMB); | 4212 | cifs_buf_release(pSMB); |
3882 | return rc; | 4213 | return rc; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e568cc47a7f9..196976049c00 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/mempool.h> | 30 | #include <linux/mempool.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/completion.h> | ||
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
34 | #include "cifspdu.h" | 35 | #include "cifspdu.h" |
@@ -44,6 +45,8 @@ | |||
44 | #define CIFS_PORT 445 | 45 | #define CIFS_PORT 445 |
45 | #define RFC1001_PORT 139 | 46 | #define RFC1001_PORT 139 |
46 | 47 | ||
48 | static DECLARE_COMPLETION(cifsd_complete); | ||
49 | |||
47 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | 50 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, |
48 | unsigned char *p24); | 51 | unsigned char *p24); |
49 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 52 | extern 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 | ||
83 | static int ipv4_connect(struct sockaddr_in *psin_server, | 91 | static 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); | ||
86 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 95 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
87 | struct socket **csocket); | 96 | struct socket **csocket); |
88 | 97 | ||
@@ -175,7 +184,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
175 | } else { | 184 | } else { |
176 | rc = ipv4_connect(&server->addr.sockAddr, | 185 | rc = ipv4_connect(&server->addr.sockAddr, |
177 | &server->ssocket, | 186 | &server->ssocket, |
178 | server->workstation_RFC1001_name); | 187 | server->workstation_RFC1001_name, |
188 | server->server_RFC1001_name); | ||
179 | } | 189 | } |
180 | if(rc) { | 190 | if(rc) { |
181 | msleep(3000); | 191 | msleep(3000); |
@@ -337,6 +347,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
337 | atomic_inc(&tcpSesAllocCount); | 347 | atomic_inc(&tcpSesAllocCount); |
338 | length = tcpSesAllocCount.counter; | 348 | length = tcpSesAllocCount.counter; |
339 | write_unlock(&GlobalSMBSeslock); | 349 | write_unlock(&GlobalSMBSeslock); |
350 | complete(&cifsd_complete); | ||
340 | if(length > 1) { | 351 | if(length > 1) { |
341 | mempool_resize(cifs_req_poolp, | 352 | mempool_resize(cifs_req_poolp, |
342 | length + cifs_min_rcv, | 353 | length + cifs_min_rcv, |
@@ -344,6 +355,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
344 | } | 355 | } |
345 | 356 | ||
346 | while (server->tcpStatus != CifsExiting) { | 357 | while (server->tcpStatus != CifsExiting) { |
358 | if(try_to_freeze()) | ||
359 | continue; | ||
347 | if (bigbuf == NULL) { | 360 | if (bigbuf == NULL) { |
348 | bigbuf = cifs_buf_get(); | 361 | bigbuf = cifs_buf_get(); |
349 | if(bigbuf == NULL) { | 362 | if(bigbuf == NULL) { |
@@ -674,7 +687,7 @@ multi_t2_fnd: | |||
674 | msleep(125); | 687 | msleep(125); |
675 | } | 688 | } |
676 | 689 | ||
677 | if (list_empty(&server->pending_mid_q)) { | 690 | if (!list_empty(&server->pending_mid_q)) { |
678 | /* mpx threads have not exited yet give them | 691 | /* mpx threads have not exited yet give them |
679 | at least the smb send timeout time for long ops */ | 692 | at least the smb send timeout time for long ops */ |
680 | /* due to delays on oplock break requests, we need | 693 | /* due to delays on oplock break requests, we need |
@@ -711,7 +724,7 @@ multi_t2_fnd: | |||
711 | GFP_KERNEL); | 724 | GFP_KERNEL); |
712 | } | 725 | } |
713 | 726 | ||
714 | msleep(250); | 727 | complete_and_exit(&cifsd_complete, 0); |
715 | return 0; | 728 | return 0; |
716 | } | 729 | } |
717 | 730 | ||
@@ -735,7 +748,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
735 | toupper(system_utsname.nodename[i]); | 748 | toupper(system_utsname.nodename[i]); |
736 | } | 749 | } |
737 | vol->source_rfc1001_name[15] = 0; | 750 | vol->source_rfc1001_name[15] = 0; |
738 | 751 | /* null target name indicates to use *SMBSERVR default called name | |
752 | if we end up sending RFC1001 session initialize */ | ||
753 | vol->target_rfc1001_name[0] = 0; | ||
739 | vol->linux_uid = current->uid; /* current->euid instead? */ | 754 | vol->linux_uid = current->uid; /* current->euid instead? */ |
740 | vol->linux_gid = current->gid; | 755 | vol->linux_gid = current->gid; |
741 | vol->dir_mode = S_IRWXUGO; | 756 | vol->dir_mode = S_IRWXUGO; |
@@ -745,6 +760,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
745 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 760 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
746 | vol->rw = TRUE; | 761 | vol->rw = TRUE; |
747 | 762 | ||
763 | /* default is always to request posix paths. */ | ||
764 | vol->posix_paths = 1; | ||
765 | |||
748 | if (!options) | 766 | if (!options) |
749 | return 1; | 767 | return 1; |
750 | 768 | ||
@@ -985,7 +1003,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
985 | /* The string has 16th byte zero still from | 1003 | /* The string has 16th byte zero still from |
986 | set at top of the function */ | 1004 | set at top of the function */ |
987 | if((i==15) && (value[i] != 0)) | 1005 | if((i==15) && (value[i] != 0)) |
988 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); | 1006 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n"); |
1007 | } | ||
1008 | } else if (strnicmp(data, "servern", 7) == 0) { | ||
1009 | /* servernetbiosname specified override *SMBSERVER */ | ||
1010 | if (!value || !*value || (*value == ' ')) { | ||
1011 | cFYI(1,("empty server netbiosname specified")); | ||
1012 | } else { | ||
1013 | /* last byte, type, is 0x20 for servr type */ | ||
1014 | memset(vol->target_rfc1001_name,0x20,16); | ||
1015 | |||
1016 | for(i=0;i<15;i++) { | ||
1017 | /* BB are there cases in which a comma can be | ||
1018 | valid in this workstation netbios name (and need | ||
1019 | special handling)? */ | ||
1020 | |||
1021 | /* user or mount helper must uppercase netbiosname */ | ||
1022 | if (value[i]==0) | ||
1023 | break; | ||
1024 | else | ||
1025 | vol->target_rfc1001_name[i] = value[i]; | ||
1026 | } | ||
1027 | /* The string has 16th byte zero still from | ||
1028 | set at top of the function */ | ||
1029 | if((i==15) && (value[i] != 0)) | ||
1030 | printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n"); | ||
989 | } | 1031 | } |
990 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1032 | } else if (strnicmp(data, "credentials", 4) == 0) { |
991 | /* ignore */ | 1033 | /* ignore */ |
@@ -1023,6 +1065,27 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1023 | vol->remap = 1; | 1065 | vol->remap = 1; |
1024 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | 1066 | } else if (strnicmp(data, "nomapchars", 10) == 0) { |
1025 | vol->remap = 0; | 1067 | vol->remap = 0; |
1068 | } else if (strnicmp(data, "sfu", 3) == 0) { | ||
1069 | vol->sfu_emul = 1; | ||
1070 | } else if (strnicmp(data, "nosfu", 5) == 0) { | ||
1071 | vol->sfu_emul = 0; | ||
1072 | } else if (strnicmp(data, "posixpaths", 10) == 0) { | ||
1073 | vol->posix_paths = 1; | ||
1074 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { | ||
1075 | vol->posix_paths = 0; | ||
1076 | } else if ((strnicmp(data, "nocase", 6) == 0) || | ||
1077 | (strnicmp(data, "ignorecase", 10) == 0)) { | ||
1078 | vol->nocase = 1; | ||
1079 | } else if (strnicmp(data, "brl", 3) == 0) { | ||
1080 | vol->nobrl = 0; | ||
1081 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | ||
1082 | (strnicmp(data, "nolock", 6) == 0)) { | ||
1083 | vol->nobrl = 1; | ||
1084 | /* turn off mandatory locking in mode | ||
1085 | if remote locking is turned off since the | ||
1086 | local vfs will do advisory */ | ||
1087 | if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP))) | ||
1088 | vol->file_mode = S_IALLUGO; | ||
1026 | } else if (strnicmp(data, "setuids", 7) == 0) { | 1089 | } else if (strnicmp(data, "setuids", 7) == 0) { |
1027 | vol->setuids = 1; | 1090 | vol->setuids = 1; |
1028 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1091 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
@@ -1242,7 +1305,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length) | |||
1242 | 1305 | ||
1243 | static int | 1306 | static int |
1244 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1307 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
1245 | char * netbios_name) | 1308 | char * netbios_name, char * target_name) |
1246 | { | 1309 | { |
1247 | int rc = 0; | 1310 | int rc = 0; |
1248 | int connected = 0; | 1311 | int connected = 0; |
@@ -1320,8 +1383,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1320 | ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); | 1383 | ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); |
1321 | if(ses_init_buf) { | 1384 | if(ses_init_buf) { |
1322 | ses_init_buf->trailer.session_req.called_len = 32; | 1385 | ses_init_buf->trailer.session_req.called_len = 32; |
1323 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | 1386 | if(target_name && (target_name[0] != 0)) { |
1324 | DEFAULT_CIFS_CALLED_NAME,16); | 1387 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, |
1388 | target_name, 16); | ||
1389 | } else { | ||
1390 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | ||
1391 | DEFAULT_CIFS_CALLED_NAME,16); | ||
1392 | } | ||
1393 | |||
1325 | ses_init_buf->trailer.session_req.calling_len = 32; | 1394 | ses_init_buf->trailer.session_req.calling_len = 32; |
1326 | /* calling name ends in null (byte 16) from old smb | 1395 | /* calling name ends in null (byte 16) from old smb |
1327 | convention. */ | 1396 | convention. */ |
@@ -1554,7 +1623,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1554 | sin_server.sin_port = htons(volume_info.port); | 1623 | sin_server.sin_port = htons(volume_info.port); |
1555 | else | 1624 | else |
1556 | sin_server.sin_port = 0; | 1625 | sin_server.sin_port = 0; |
1557 | rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); | 1626 | rc = ipv4_connect(&sin_server,&csocket, |
1627 | volume_info.source_rfc1001_name, | ||
1628 | volume_info.target_rfc1001_name); | ||
1558 | if (rc < 0) { | 1629 | if (rc < 0) { |
1559 | cERROR(1, | 1630 | cERROR(1, |
1560 | ("Error connecting to IPv4 socket. Aborting operation")); | 1631 | ("Error connecting to IPv4 socket. Aborting operation")); |
@@ -1604,9 +1675,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1604 | kfree(volume_info.password); | 1675 | kfree(volume_info.password); |
1605 | FreeXid(xid); | 1676 | FreeXid(xid); |
1606 | return rc; | 1677 | return rc; |
1607 | } else | 1678 | } |
1608 | rc = 0; | 1679 | wait_for_completion(&cifsd_complete); |
1680 | rc = 0; | ||
1609 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1681 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
1682 | memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16); | ||
1610 | srvTcp->sequence_number = 0; | 1683 | srvTcp->sequence_number = 0; |
1611 | } | 1684 | } |
1612 | } | 1685 | } |
@@ -1660,8 +1733,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1660 | else | 1733 | else |
1661 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ | 1734 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ |
1662 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { | 1735 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { |
1663 | cifs_sb->rsize = PAGE_CACHE_SIZE; | 1736 | cifs_sb->rsize = PAGE_CACHE_SIZE; |
1664 | cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); | 1737 | /* Windows ME does this */ |
1738 | cFYI(1,("Attempt to set readsize for mount to less than one page (4096)")); | ||
1665 | } | 1739 | } |
1666 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1740 | cifs_sb->mnt_uid = volume_info.linux_uid; |
1667 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1741 | cifs_sb->mnt_gid = volume_info.linux_gid; |
@@ -1679,8 +1753,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1679 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | 1753 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; |
1680 | if(volume_info.no_xattr) | 1754 | if(volume_info.no_xattr) |
1681 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 1755 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
1756 | if(volume_info.sfu_emul) | ||
1757 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | ||
1758 | if(volume_info.nobrl) | ||
1759 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | ||
1760 | |||
1682 | if(volume_info.direct_io) { | 1761 | if(volume_info.direct_io) { |
1683 | cERROR(1,("mounting share using direct i/o")); | 1762 | cFYI(1,("mounting share using direct i/o")); |
1684 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 1763 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
1685 | } | 1764 | } |
1686 | 1765 | ||
@@ -1694,6 +1773,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1694 | to the same server share the last value passed in | 1773 | to the same server share the last value passed in |
1695 | for the retry flag is used */ | 1774 | for the retry flag is used */ |
1696 | tcon->retry = volume_info.retry; | 1775 | tcon->retry = volume_info.retry; |
1776 | tcon->nocase = volume_info.nocase; | ||
1697 | } else { | 1777 | } else { |
1698 | tcon = tconInfoAlloc(); | 1778 | tcon = tconInfoAlloc(); |
1699 | if (tcon == NULL) | 1779 | if (tcon == NULL) |
@@ -1722,6 +1802,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1722 | if (!rc) { | 1802 | if (!rc) { |
1723 | atomic_inc(&pSesInfo->inUse); | 1803 | atomic_inc(&pSesInfo->inUse); |
1724 | tcon->retry = volume_info.retry; | 1804 | tcon->retry = volume_info.retry; |
1805 | tcon->nocase = volume_info.nocase; | ||
1725 | } | 1806 | } |
1726 | } | 1807 | } |
1727 | } | 1808 | } |
@@ -1743,8 +1824,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1743 | spin_lock(&GlobalMid_Lock); | 1824 | spin_lock(&GlobalMid_Lock); |
1744 | srvTcp->tcpStatus = CifsExiting; | 1825 | srvTcp->tcpStatus = CifsExiting; |
1745 | spin_unlock(&GlobalMid_Lock); | 1826 | spin_unlock(&GlobalMid_Lock); |
1746 | if(srvTcp->tsk) | 1827 | if(srvTcp->tsk) { |
1747 | send_sig(SIGKILL,srvTcp->tsk,1); | 1828 | send_sig(SIGKILL,srvTcp->tsk,1); |
1829 | wait_for_completion(&cifsd_complete); | ||
1830 | } | ||
1748 | } | 1831 | } |
1749 | /* If find_unc succeeded then rc == 0 so we can not end */ | 1832 | /* If find_unc succeeded then rc == 0 so we can not end */ |
1750 | if (tcon) /* up accidently freeing someone elses tcon struct */ | 1833 | if (tcon) /* up accidently freeing someone elses tcon struct */ |
@@ -1757,8 +1840,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1757 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 1840 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); |
1758 | /* if the socketUseCount is now zero */ | 1841 | /* if the socketUseCount is now zero */ |
1759 | if((temp_rc == -ESHUTDOWN) && | 1842 | if((temp_rc == -ESHUTDOWN) && |
1760 | (pSesInfo->server->tsk)) | 1843 | (pSesInfo->server->tsk)) { |
1761 | send_sig(SIGKILL,pSesInfo->server->tsk,1); | 1844 | send_sig(SIGKILL,pSesInfo->server->tsk,1); |
1845 | wait_for_completion(&cifsd_complete); | ||
1846 | } | ||
1762 | } else | 1847 | } else |
1763 | cFYI(1, ("No session or bad tcon")); | 1848 | cFYI(1, ("No session or bad tcon")); |
1764 | sesInfoFree(pSesInfo); | 1849 | sesInfoFree(pSesInfo); |
@@ -1781,6 +1866,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1781 | cFYI(1,("server negotiated posix acl support")); | 1866 | cFYI(1,("server negotiated posix acl support")); |
1782 | sb->s_flags |= MS_POSIXACL; | 1867 | sb->s_flags |= MS_POSIXACL; |
1783 | } | 1868 | } |
1869 | |||
1870 | /* Try and negotiate POSIX pathnames if we can. */ | ||
1871 | if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & | ||
1872 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | ||
1873 | if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { | ||
1874 | cFYI(1,("negotiated posix pathnames support")); | ||
1875 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | ||
1876 | } else { | ||
1877 | cFYI(1,("posix pathnames support requested but not supported")); | ||
1878 | } | ||
1879 | } | ||
1784 | } | 1880 | } |
1785 | } | 1881 | } |
1786 | } | 1882 | } |
@@ -1830,6 +1926,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1830 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 1926 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
1831 | NULL /* no tCon exists yet */ , 13 /* wct */ ); | 1927 | NULL /* no tCon exists yet */ , 13 /* wct */ ); |
1832 | 1928 | ||
1929 | smb_buffer->Mid = GetNextMid(ses->server); | ||
1833 | pSMB->req_no_secext.AndXCommand = 0xFF; | 1930 | pSMB->req_no_secext.AndXCommand = 0xFF; |
1834 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 1931 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
1835 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 1932 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
@@ -2105,6 +2202,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2105 | /* send SMBsessionSetup here */ | 2202 | /* send SMBsessionSetup here */ |
2106 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2203 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2107 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2204 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2205 | |||
2206 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2108 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2207 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2109 | pSMB->req.AndXCommand = 0xFF; | 2208 | pSMB->req.AndXCommand = 0xFF; |
2110 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 2209 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
@@ -2371,6 +2470,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2371 | /* send SMBsessionSetup here */ | 2470 | /* send SMBsessionSetup here */ |
2372 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2471 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2373 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2472 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2473 | |||
2474 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2374 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2475 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2375 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2476 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
2376 | 2477 | ||
@@ -2713,6 +2814,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2713 | /* send SMBsessionSetup here */ | 2814 | /* send SMBsessionSetup here */ |
2714 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2815 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2715 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2816 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2817 | |||
2818 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2716 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2819 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
2717 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2820 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2718 | pSMB->req.AndXCommand = 0xFF; | 2821 | pSMB->req.AndXCommand = 0xFF; |
@@ -3084,6 +3187,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3084 | 3187 | ||
3085 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, | 3188 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, |
3086 | NULL /*no tid */ , 4 /*wct */ ); | 3189 | NULL /*no tid */ , 4 /*wct */ ); |
3190 | |||
3191 | smb_buffer->Mid = GetNextMid(ses->server); | ||
3087 | smb_buffer->Uid = ses->Suid; | 3192 | smb_buffer->Uid = ses->Suid; |
3088 | pSMB = (TCONX_REQ *) smb_buffer; | 3193 | pSMB = (TCONX_REQ *) smb_buffer; |
3089 | pSMBr = (TCONX_RSP *) smb_buffer_response; | 3194 | pSMBr = (TCONX_RSP *) smb_buffer_response; |
@@ -3205,8 +3310,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3205 | return 0; | 3310 | return 0; |
3206 | } else if (rc == -ESHUTDOWN) { | 3311 | } else if (rc == -ESHUTDOWN) { |
3207 | cFYI(1,("Waking up socket by sending it signal")); | 3312 | cFYI(1,("Waking up socket by sending it signal")); |
3208 | if(cifsd_task) | 3313 | if(cifsd_task) { |
3209 | send_sig(SIGKILL,cifsd_task,1); | 3314 | send_sig(SIGKILL,cifsd_task,1); |
3315 | wait_for_completion(&cifsd_complete); | ||
3316 | } | ||
3210 | rc = 0; | 3317 | rc = 0; |
3211 | } /* else - we have an smb session | 3318 | } /* else - we have an smb session |
3212 | left on this socket do not kill cifsd */ | 3319 | left on this socket do not kill cifsd */ |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 3f3538d4a1fa..cf90c9ad2c87 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -48,6 +48,7 @@ build_path_from_dentry(struct dentry *direntry) | |||
48 | struct dentry *temp; | 48 | struct dentry *temp; |
49 | int namelen = 0; | 49 | int namelen = 0; |
50 | char *full_path; | 50 | char *full_path; |
51 | char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | ||
51 | 52 | ||
52 | if(direntry == NULL) | 53 | if(direntry == NULL) |
53 | return NULL; /* not much we can do if dentry is freed and | 54 | return NULL; /* not much we can do if dentry is freed and |
@@ -74,7 +75,7 @@ cifs_bp_rename_retry: | |||
74 | if (namelen < 0) { | 75 | if (namelen < 0) { |
75 | break; | 76 | break; |
76 | } else { | 77 | } else { |
77 | full_path[namelen] = '\\'; | 78 | full_path[namelen] = dirsep; |
78 | strncpy(full_path + namelen + 1, temp->d_name.name, | 79 | strncpy(full_path + namelen + 1, temp->d_name.name, |
79 | temp->d_name.len); | 80 | temp->d_name.len); |
80 | cFYI(0, (" name: %s ", full_path + namelen)); | 81 | cFYI(0, (" name: %s ", full_path + namelen)); |
@@ -184,6 +185,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
184 | desiredAccess, CREATE_NOT_DIR, | 185 | desiredAccess, CREATE_NOT_DIR, |
185 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 186 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
186 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 187 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
188 | if(rc == -EIO) { | ||
189 | /* old server, retry the open legacy style */ | ||
190 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | ||
191 | desiredAccess, CREATE_NOT_DIR, | ||
192 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | ||
193 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
194 | } | ||
187 | if (rc) { | 195 | if (rc) { |
188 | cFYI(1, ("cifs_create returned 0x%x ", rc)); | 196 | cFYI(1, ("cifs_create returned 0x%x ", rc)); |
189 | } else { | 197 | } else { |
@@ -209,7 +217,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
209 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 217 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
210 | } | 218 | } |
211 | else { | 219 | else { |
212 | /* BB implement via Windows security descriptors */ | 220 | /* BB implement mode setting via Windows security descriptors */ |
213 | /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ | 221 | /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ |
214 | /* could set r/o dos attribute if mode & 0222 == 0 */ | 222 | /* could set r/o dos attribute if mode & 0222 == 0 */ |
215 | } | 223 | } |
@@ -226,10 +234,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
226 | } | 234 | } |
227 | 235 | ||
228 | if (rc != 0) { | 236 | if (rc != 0) { |
229 | cFYI(1,("Create worked but get_inode_info failed with rc = %d", | 237 | cFYI(1, |
238 | ("Create worked but get_inode_info failed rc = %d", | ||
230 | rc)); | 239 | rc)); |
231 | } else { | 240 | } else { |
232 | direntry->d_op = &cifs_dentry_ops; | 241 | if (pTcon->nocase) |
242 | direntry->d_op = &cifs_ci_dentry_ops; | ||
243 | else | ||
244 | direntry->d_op = &cifs_dentry_ops; | ||
233 | d_instantiate(direntry, newinode); | 245 | d_instantiate(direntry, newinode); |
234 | } | 246 | } |
235 | if((nd->flags & LOOKUP_OPEN) == FALSE) { | 247 | if((nd->flags & LOOKUP_OPEN) == FALSE) { |
@@ -303,8 +315,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev | |||
303 | up(&direntry->d_sb->s_vfs_rename_sem); | 315 | up(&direntry->d_sb->s_vfs_rename_sem); |
304 | if(full_path == NULL) | 316 | if(full_path == NULL) |
305 | rc = -ENOMEM; | 317 | rc = -ENOMEM; |
306 | 318 | else if (pTcon->ses->capabilities & CAP_UNIX) { | |
307 | if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) { | ||
308 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 319 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
309 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 320 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
310 | mode,(__u64)current->euid,(__u64)current->egid, | 321 | mode,(__u64)current->euid,(__u64)current->egid, |
@@ -322,10 +333,49 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev | |||
322 | if(!rc) { | 333 | if(!rc) { |
323 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 334 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
324 | inode->i_sb,xid); | 335 | inode->i_sb,xid); |
325 | direntry->d_op = &cifs_dentry_ops; | 336 | if (pTcon->nocase) |
337 | direntry->d_op = &cifs_ci_dentry_ops; | ||
338 | else | ||
339 | direntry->d_op = &cifs_dentry_ops; | ||
326 | if(rc == 0) | 340 | if(rc == 0) |
327 | d_instantiate(direntry, newinode); | 341 | d_instantiate(direntry, newinode); |
328 | } | 342 | } |
343 | } else { | ||
344 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
345 | int oplock = 0; | ||
346 | u16 fileHandle; | ||
347 | FILE_ALL_INFO * buf; | ||
348 | |||
349 | cFYI(1,("sfu compat create special file")); | ||
350 | |||
351 | buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); | ||
352 | if(buf == NULL) { | ||
353 | kfree(full_path); | ||
354 | FreeXid(xid); | ||
355 | return -ENOMEM; | ||
356 | } | ||
357 | |||
358 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
359 | FILE_CREATE, /* fail if exists */ | ||
360 | GENERIC_WRITE /* BB would | ||
361 | WRITE_OWNER | WRITE_DAC be better? */, | ||
362 | /* Create a file and set the | ||
363 | file attribute to SYSTEM */ | ||
364 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | ||
365 | &fileHandle, &oplock, buf, | ||
366 | cifs_sb->local_nls, | ||
367 | cifs_sb->mnt_cifs_flags & | ||
368 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
369 | |||
370 | if(!rc) { | ||
371 | /* BB Do not bother to decode buf since no | ||
372 | local inode yet to put timestamps in */ | ||
373 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
374 | d_drop(direntry); | ||
375 | } | ||
376 | kfree(buf); | ||
377 | /* add code here to set EAs */ | ||
378 | } | ||
329 | } | 379 | } |
330 | 380 | ||
331 | kfree(full_path); | 381 | kfree(full_path); |
@@ -382,7 +432,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
382 | parent_dir_inode->i_sb,xid); | 432 | parent_dir_inode->i_sb,xid); |
383 | 433 | ||
384 | if ((rc == 0) && (newInode != NULL)) { | 434 | if ((rc == 0) && (newInode != NULL)) { |
385 | direntry->d_op = &cifs_dentry_ops; | 435 | if (pTcon->nocase) |
436 | direntry->d_op = &cifs_ci_dentry_ops; | ||
437 | else | ||
438 | direntry->d_op = &cifs_dentry_ops; | ||
386 | d_add(direntry, newInode); | 439 | d_add(direntry, newInode); |
387 | 440 | ||
388 | /* since paths are not looked up by component - the parent directories are presumed to be good here */ | 441 | /* since paths are not looked up by component - the parent directories are presumed to be good here */ |
@@ -441,3 +494,42 @@ struct dentry_operations cifs_dentry_ops = { | |||
441 | /* d_delete: cifs_d_delete, *//* not needed except for debugging */ | 494 | /* d_delete: cifs_d_delete, *//* not needed except for debugging */ |
442 | /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ | 495 | /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ |
443 | }; | 496 | }; |
497 | |||
498 | static 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 | |||
513 | static 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 | |||
531 | struct dentry_operations cifs_ci_dentry_ops = { | ||
532 | .d_revalidate = cifs_d_revalidate, | ||
533 | .d_hash = cifs_ci_hash, | ||
534 | .d_compare = cifs_ci_compare, | ||
535 | }; | ||
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index 7d2a9202c39a..d527e2c76073 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c | |||
@@ -100,8 +100,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg) | |||
100 | } else { | 100 | } else { |
101 | filter = convert_to_cifs_notify_flags(arg); | 101 | filter = convert_to_cifs_notify_flags(arg); |
102 | if(filter != 0) { | 102 | if(filter != 0) { |
103 | rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, | 103 | rc = CIFSSMBNotify(xid, pTcon, |
104 | filter, cifs_sb->local_nls); | 104 | 0 /* no subdirs */, netfid, |
105 | filter, file, arg & DN_MULTISHOT, | ||
106 | cifs_sb->local_nls); | ||
105 | } else { | 107 | } else { |
106 | rc = -EINVAL; | 108 | rc = -EINVAL; |
107 | } | 109 | } |
@@ -109,7 +111,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg) | |||
109 | it would close automatically but may be a way | 111 | it would close automatically but may be a way |
110 | to do it easily when inode freed or when | 112 | to do it easily when inode freed or when |
111 | notify info is cleared/changed */ | 113 | notify info is cleared/changed */ |
112 | cERROR(1,("notify rc %d",rc)); | 114 | cFYI(1,("notify rc %d",rc)); |
113 | } | 115 | } |
114 | } | 116 | } |
115 | 117 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 3497125189df..5ecda554f913 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -256,6 +256,13 @@ int cifs_open(struct inode *inode, struct file *file) | |||
256 | CREATE_NOT_DIR, &netfid, &oplock, buf, | 256 | CREATE_NOT_DIR, &netfid, &oplock, buf, |
257 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | 257 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags |
258 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 258 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
259 | if (rc == -EIO) { | ||
260 | /* Old server, try legacy style OpenX */ | ||
261 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | ||
262 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
263 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
264 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
265 | } | ||
259 | if (rc) { | 266 | if (rc) { |
260 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 267 | cFYI(1, ("cifs_open returned 0x%x ", rc)); |
261 | goto out; | 268 | goto out; |
@@ -744,14 +751,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
744 | 15 seconds is plenty */ | 751 | 15 seconds is plenty */ |
745 | } | 752 | } |
746 | 753 | ||
747 | #ifdef CONFIG_CIFS_STATS | 754 | cifs_stats_bytes_written(pTcon, total_written); |
748 | if (total_written > 0) { | ||
749 | atomic_inc(&pTcon->num_writes); | ||
750 | spin_lock(&pTcon->stat_lock); | ||
751 | pTcon->bytes_written += total_written; | ||
752 | spin_unlock(&pTcon->stat_lock); | ||
753 | } | ||
754 | #endif | ||
755 | 755 | ||
756 | /* since the write may have blocked check these pointers again */ | 756 | /* since the write may have blocked check these pointers again */ |
757 | if (file->f_dentry) { | 757 | if (file->f_dentry) { |
@@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
791 | 791 | ||
792 | pTcon = cifs_sb->tcon; | 792 | pTcon = cifs_sb->tcon; |
793 | 793 | ||
794 | /* cFYI(1, | 794 | cFYI(1,(" write %d bytes to offset %lld of %s", write_size, |
795 | (" write %d bytes to offset %lld of %s", write_size, | 795 | *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */ |
796 | *poffset, file->f_dentry->d_name.name)); */ | ||
797 | 796 | ||
798 | if (file->private_data == NULL) | 797 | if (file->private_data == NULL) |
799 | return -EBADF; | 798 | return -EBADF; |
@@ -846,7 +845,20 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
846 | if (rc != 0) | 845 | if (rc != 0) |
847 | break; | 846 | break; |
848 | } | 847 | } |
849 | 848 | #ifdef CONFIG_CIFS_EXPERIMENTAL | |
849 | /* BB FIXME We can not sign across two buffers yet */ | ||
850 | if((experimEnabled) && ((pTcon->ses->server->secMode & | ||
851 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) { | ||
852 | rc = CIFSSMBWrite2(xid, pTcon, | ||
853 | open_file->netfid, | ||
854 | min_t(const int, cifs_sb->wsize, | ||
855 | write_size - total_written), | ||
856 | *poffset, &bytes_written, | ||
857 | write_data + total_written, | ||
858 | long_op); | ||
859 | } else | ||
860 | /* BB FIXME fixup indentation of line below */ | ||
861 | #endif | ||
850 | rc = CIFSSMBWrite(xid, pTcon, | 862 | rc = CIFSSMBWrite(xid, pTcon, |
851 | open_file->netfid, | 863 | open_file->netfid, |
852 | min_t(const int, cifs_sb->wsize, | 864 | min_t(const int, cifs_sb->wsize, |
@@ -867,14 +879,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
867 | 15 seconds is plenty */ | 879 | 15 seconds is plenty */ |
868 | } | 880 | } |
869 | 881 | ||
870 | #ifdef CONFIG_CIFS_STATS | 882 | cifs_stats_bytes_written(pTcon, total_written); |
871 | if (total_written > 0) { | ||
872 | atomic_inc(&pTcon->num_writes); | ||
873 | spin_lock(&pTcon->stat_lock); | ||
874 | pTcon->bytes_written += total_written; | ||
875 | spin_unlock(&pTcon->stat_lock); | ||
876 | } | ||
877 | #endif | ||
878 | 883 | ||
879 | /* since the write may have blocked check these pointers again */ | 884 | /* since the write may have blocked check these pointers again */ |
880 | if (file->f_dentry) { | 885 | if (file->f_dentry) { |
@@ -1207,12 +1212,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1207 | if (rc != 0) | 1212 | if (rc != 0) |
1208 | break; | 1213 | break; |
1209 | } | 1214 | } |
1210 | |||
1211 | rc = CIFSSMBRead(xid, pTcon, | 1215 | rc = CIFSSMBRead(xid, pTcon, |
1212 | open_file->netfid, | 1216 | open_file->netfid, |
1213 | current_read_size, *poffset, | 1217 | current_read_size, *poffset, |
1214 | &bytes_read, &smb_read_data); | 1218 | &bytes_read, &smb_read_data); |
1215 | |||
1216 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1219 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; |
1217 | if (copy_to_user(current_offset, | 1220 | if (copy_to_user(current_offset, |
1218 | smb_read_data + 4 /* RFC1001 hdr */ | 1221 | smb_read_data + 4 /* RFC1001 hdr */ |
@@ -1235,12 +1238,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1235 | return rc; | 1238 | return rc; |
1236 | } | 1239 | } |
1237 | } else { | 1240 | } else { |
1238 | #ifdef CONFIG_CIFS_STATS | 1241 | cifs_stats_bytes_read(pTcon, bytes_read); |
1239 | atomic_inc(&pTcon->num_reads); | ||
1240 | spin_lock(&pTcon->stat_lock); | ||
1241 | pTcon->bytes_read += total_read; | ||
1242 | spin_unlock(&pTcon->stat_lock); | ||
1243 | #endif | ||
1244 | *poffset += bytes_read; | 1242 | *poffset += bytes_read; |
1245 | } | 1243 | } |
1246 | } | 1244 | } |
@@ -1289,11 +1287,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1289 | if (rc != 0) | 1287 | if (rc != 0) |
1290 | break; | 1288 | break; |
1291 | } | 1289 | } |
1292 | |||
1293 | rc = CIFSSMBRead(xid, pTcon, | 1290 | rc = CIFSSMBRead(xid, pTcon, |
1294 | open_file->netfid, | 1291 | open_file->netfid, |
1295 | current_read_size, *poffset, | 1292 | current_read_size, *poffset, |
1296 | &bytes_read, ¤t_offset); | 1293 | &bytes_read, ¤t_offset); |
1297 | } | 1294 | } |
1298 | if (rc || (bytes_read == 0)) { | 1295 | if (rc || (bytes_read == 0)) { |
1299 | if (total_read) { | 1296 | if (total_read) { |
@@ -1303,12 +1300,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1303 | return rc; | 1300 | return rc; |
1304 | } | 1301 | } |
1305 | } else { | 1302 | } else { |
1306 | #ifdef CONFIG_CIFS_STATS | 1303 | cifs_stats_bytes_read(pTcon, total_read); |
1307 | atomic_inc(&pTcon->num_reads); | ||
1308 | spin_lock(&pTcon->stat_lock); | ||
1309 | pTcon->bytes_read += total_read; | ||
1310 | spin_unlock(&pTcon->stat_lock); | ||
1311 | #endif | ||
1312 | *poffset += bytes_read; | 1304 | *poffset += bytes_read; |
1313 | } | 1305 | } |
1314 | } | 1306 | } |
@@ -1452,10 +1444,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1452 | } | 1444 | } |
1453 | 1445 | ||
1454 | rc = CIFSSMBRead(xid, pTcon, | 1446 | rc = CIFSSMBRead(xid, pTcon, |
1455 | open_file->netfid, | 1447 | open_file->netfid, |
1456 | read_size, offset, | 1448 | read_size, offset, |
1457 | &bytes_read, &smb_read_data); | 1449 | &bytes_read, &smb_read_data); |
1458 | /* BB need to check return code here */ | 1450 | |
1451 | /* BB more RC checks ? */ | ||
1459 | if (rc== -EAGAIN) { | 1452 | if (rc== -EAGAIN) { |
1460 | if (smb_read_data) { | 1453 | if (smb_read_data) { |
1461 | cifs_buf_release(smb_read_data); | 1454 | cifs_buf_release(smb_read_data); |
@@ -1480,12 +1473,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1480 | le16_to_cpu(pSMBr->DataOffset), &lru_pvec); | 1473 | le16_to_cpu(pSMBr->DataOffset), &lru_pvec); |
1481 | 1474 | ||
1482 | i += bytes_read >> PAGE_CACHE_SHIFT; | 1475 | i += bytes_read >> PAGE_CACHE_SHIFT; |
1483 | #ifdef CONFIG_CIFS_STATS | 1476 | cifs_stats_bytes_read(pTcon, bytes_read); |
1484 | atomic_inc(&pTcon->num_reads); | ||
1485 | spin_lock(&pTcon->stat_lock); | ||
1486 | pTcon->bytes_read += bytes_read; | ||
1487 | spin_unlock(&pTcon->stat_lock); | ||
1488 | #endif | ||
1489 | if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { | 1477 | if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { |
1490 | i++; /* account for partial page */ | 1478 | i++; /* account for partial page */ |
1491 | 1479 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8d336a900255..0fbe02ebc033 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -166,7 +166,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
166 | inode->i_fop = &cifs_file_direct_ops; | 166 | inode->i_fop = &cifs_file_direct_ops; |
167 | else | 167 | else |
168 | inode->i_fop = &cifs_file_ops; | 168 | inode->i_fop = &cifs_file_ops; |
169 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
170 | inode->i_fop->lock = NULL; | ||
169 | inode->i_data.a_ops = &cifs_addr_ops; | 171 | inode->i_data.a_ops = &cifs_addr_ops; |
172 | /* check if server can support readpages */ | ||
173 | if(pTcon->ses->server->maxBuf < | ||
174 | 4096 + MAX_CIFS_HDR_SIZE) | ||
175 | inode->i_data.a_ops->readpages = NULL; | ||
170 | } else if (S_ISDIR(inode->i_mode)) { | 176 | } else if (S_ISDIR(inode->i_mode)) { |
171 | cFYI(1, (" Directory inode")); | 177 | cFYI(1, (" Directory inode")); |
172 | inode->i_op = &cifs_dir_inode_ops; | 178 | inode->i_op = &cifs_dir_inode_ops; |
@@ -213,8 +219,18 @@ int cifs_get_inode_info(struct inode **pinode, | |||
213 | pfindData = (FILE_ALL_INFO *)buf; | 219 | pfindData = (FILE_ALL_INFO *)buf; |
214 | /* could do find first instead but this returns more info */ | 220 | /* could do find first instead but this returns more info */ |
215 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 221 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, |
216 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 222 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
217 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 223 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
224 | /* BB optimize code so we do not make the above call | ||
225 | when server claims no NT SMB support and the above call | ||
226 | failed at least once - set flag in tcon or mount */ | ||
227 | if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | ||
228 | rc = SMBQueryInformation(xid, pTcon, search_path, | ||
229 | pfindData, cifs_sb->local_nls, | ||
230 | cifs_sb->mnt_cifs_flags & | ||
231 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
232 | } | ||
233 | |||
218 | } | 234 | } |
219 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 235 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
220 | if (rc) { | 236 | if (rc) { |
@@ -320,6 +336,16 @@ int cifs_get_inode_info(struct inode **pinode, | |||
320 | on dirs */ | 336 | on dirs */ |
321 | inode->i_mode = cifs_sb->mnt_dir_mode; | 337 | inode->i_mode = cifs_sb->mnt_dir_mode; |
322 | inode->i_mode |= S_IFDIR; | 338 | inode->i_mode |= S_IFDIR; |
339 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | ||
340 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && | ||
341 | /* No need to le64 convert size of zero */ | ||
342 | (pfindData->EndOfFile == 0)) { | ||
343 | inode->i_mode = cifs_sb->mnt_file_mode; | ||
344 | inode->i_mode |= S_IFIFO; | ||
345 | /* BB Finish for SFU style symlinks and devies */ | ||
346 | /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | ||
347 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ | ||
348 | |||
323 | } else { | 349 | } else { |
324 | inode->i_mode |= S_IFREG; | 350 | inode->i_mode |= S_IFREG; |
325 | /* treat the dos attribute of read-only as read-only | 351 | /* treat the dos attribute of read-only as read-only |
@@ -359,7 +385,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
359 | inode->i_fop = &cifs_file_direct_ops; | 385 | inode->i_fop = &cifs_file_direct_ops; |
360 | else | 386 | else |
361 | inode->i_fop = &cifs_file_ops; | 387 | inode->i_fop = &cifs_file_ops; |
388 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
389 | inode->i_fop->lock = NULL; | ||
362 | inode->i_data.a_ops = &cifs_addr_ops; | 390 | inode->i_data.a_ops = &cifs_addr_ops; |
391 | if(pTcon->ses->server->maxBuf < | ||
392 | 4096 + MAX_CIFS_HDR_SIZE) | ||
393 | inode->i_data.a_ops->readpages = NULL; | ||
363 | } else if (S_ISDIR(inode->i_mode)) { | 394 | } else if (S_ISDIR(inode->i_mode)) { |
364 | cFYI(1, (" Directory inode ")); | 395 | cFYI(1, (" Directory inode ")); |
365 | inode->i_op = &cifs_dir_inode_ops; | 396 | inode->i_op = &cifs_dir_inode_ops; |
@@ -577,7 +608,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
577 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 608 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
578 | inode->i_sb,xid); | 609 | inode->i_sb,xid); |
579 | 610 | ||
580 | direntry->d_op = &cifs_dentry_ops; | 611 | if (pTcon->nocase) |
612 | direntry->d_op = &cifs_ci_dentry_ops; | ||
613 | else | ||
614 | direntry->d_op = &cifs_dentry_ops; | ||
581 | d_instantiate(direntry, newinode); | 615 | d_instantiate(direntry, newinode); |
582 | if (direntry->d_inode) | 616 | if (direntry->d_inode) |
583 | direntry->d_inode->i_nlink = 2; | 617 | direntry->d_inode->i_nlink = 2; |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index ab925ef4f863..b43e071fe110 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -198,7 +198,10 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
198 | ("Create symlink worked but get_inode_info failed with rc = %d ", | 198 | ("Create symlink worked but get_inode_info failed with rc = %d ", |
199 | rc)); | 199 | rc)); |
200 | } else { | 200 | } else { |
201 | direntry->d_op = &cifs_dentry_ops; | 201 | if (pTcon->nocase) |
202 | direntry->d_op = &cifs_ci_dentry_ops; | ||
203 | else | ||
204 | direntry->d_op = &cifs_dentry_ops; | ||
202 | d_instantiate(direntry, newinode); | 205 | d_instantiate(direntry, newinode); |
203 | } | 206 | } |
204 | } | 207 | } |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 20ae4153f791..fafbdbfa63a1 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -34,8 +34,6 @@ extern mempool_t *cifs_sm_req_poolp; | |||
34 | extern mempool_t *cifs_req_poolp; | 34 | extern mempool_t *cifs_req_poolp; |
35 | extern struct task_struct * oplockThread; | 35 | extern struct task_struct * oplockThread; |
36 | 36 | ||
37 | static __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 */ | ||
221 | void | 291 | void |
222 | header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | 292 | header_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[] = { | |||
133 | int | 133 | int |
134 | cifs_inet_pton(int address_family, char *cp,void *dst) | 134 | cifs_inet_pton(int address_family, char *cp,void *dst) |
135 | { | 135 | { |
136 | struct in_addr address; | ||
137 | int value; | 136 | int value; |
138 | int digit; | 137 | int digit; |
139 | int i; | 138 | int i; |
@@ -190,8 +189,7 @@ cifs_inet_pton(int address_family, char *cp,void *dst) | |||
190 | if (value > addr_class_max[end - bytes]) | 189 | if (value > addr_class_max[end - bytes]) |
191 | return 0; | 190 | return 0; |
192 | 191 | ||
193 | address.s_addr = *((__be32 *) bytes) | htonl(value); | 192 | *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value); |
194 | *((__be32 *)dst) = address.s_addr; | ||
195 | return 1; /* success */ | 193 | return 1; /* success */ |
196 | } | 194 | } |
197 | 195 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 22557716f9af..a1e8dc901de4 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -91,7 +91,10 @@ static int construct_dentry(struct qstr *qstring, struct file *file, | |||
91 | } | 91 | } |
92 | 92 | ||
93 | *ptmp_inode = new_inode(file->f_dentry->d_sb); | 93 | *ptmp_inode = new_inode(file->f_dentry->d_sb); |
94 | tmp_dentry->d_op = &cifs_dentry_ops; | 94 | if (pTcon->nocase) |
95 | tmp_dentry->d_op = &cifs_ci_dentry_ops; | ||
96 | else | ||
97 | tmp_dentry->d_op = &cifs_dentry_ops; | ||
95 | if(*ptmp_inode == NULL) | 98 | if(*ptmp_inode == NULL) |
96 | return rc; | 99 | return rc; |
97 | rc = 1; | 100 | rc = 1; |
@@ -148,6 +151,13 @@ static void fill_in_inode(struct inode *tmp_inode, | |||
148 | tmp_inode->i_mode = cifs_sb->mnt_dir_mode; | 151 | tmp_inode->i_mode = cifs_sb->mnt_dir_mode; |
149 | } | 152 | } |
150 | tmp_inode->i_mode |= S_IFDIR; | 153 | tmp_inode->i_mode |= S_IFDIR; |
154 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | ||
155 | (attr & ATTR_SYSTEM) && (end_of_file == 0)) { | ||
156 | *pobject_type = DT_FIFO; | ||
157 | tmp_inode->i_mode |= S_IFIFO; | ||
158 | /* BB Finish for SFU style symlinks and devies */ | ||
159 | /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | ||
160 | (attr & ATTR_SYSTEM) && ) { */ | ||
151 | /* we no longer mark these because we could not follow them */ | 161 | /* we no longer mark these because we could not follow them */ |
152 | /* } else if (attr & ATTR_REPARSE) { | 162 | /* } else if (attr & ATTR_REPARSE) { |
153 | *pobject_type = DT_LNK; | 163 | *pobject_type = DT_LNK; |
@@ -187,11 +197,17 @@ static void fill_in_inode(struct inode *tmp_inode, | |||
187 | tmp_inode->i_fop = &cifs_file_direct_ops; | 197 | tmp_inode->i_fop = &cifs_file_direct_ops; |
188 | else | 198 | else |
189 | tmp_inode->i_fop = &cifs_file_ops; | 199 | tmp_inode->i_fop = &cifs_file_ops; |
200 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
201 | tmp_inode->i_fop->lock = NULL; | ||
190 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | 202 | tmp_inode->i_data.a_ops = &cifs_addr_ops; |
191 | 203 | if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | |
204 | (cifs_sb->tcon->ses->server->maxBuf < | ||
205 | 4096 + MAX_CIFS_HDR_SIZE)) | ||
206 | tmp_inode->i_data.a_ops->readpages = NULL; | ||
192 | if(isNewInode) | 207 | if(isNewInode) |
193 | return; /* No sense invalidating pages for new inode since we | 208 | return; /* No sense invalidating pages for new inode |
194 | have not started caching readahead file data yet */ | 209 | since have not started caching readahead file |
210 | data yet */ | ||
195 | 211 | ||
196 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | 212 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && |
197 | (local_size == tmp_inode->i_size)) { | 213 | (local_size == tmp_inode->i_size)) { |
@@ -290,7 +306,13 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
290 | tmp_inode->i_fop = &cifs_file_direct_ops; | 306 | tmp_inode->i_fop = &cifs_file_direct_ops; |
291 | else | 307 | else |
292 | tmp_inode->i_fop = &cifs_file_ops; | 308 | tmp_inode->i_fop = &cifs_file_ops; |
309 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
310 | tmp_inode->i_fop->lock = NULL; | ||
293 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | 311 | tmp_inode->i_data.a_ops = &cifs_addr_ops; |
312 | if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
313 | (cifs_sb->tcon->ses->server->maxBuf < | ||
314 | 4096 + MAX_CIFS_HDR_SIZE)) | ||
315 | tmp_inode->i_data.a_ops->readpages = NULL; | ||
294 | 316 | ||
295 | if(isNewInode) | 317 | if(isNewInode) |
296 | return; /* No sense invalidating pages for new inode since we | 318 | return; /* No sense invalidating pages for new inode since we |
@@ -374,7 +396,7 @@ ffirst_retry: | |||
374 | 396 | ||
375 | rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, | 397 | rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, |
376 | &cifsFile->netfid, &cifsFile->srch_inf, | 398 | &cifsFile->netfid, &cifsFile->srch_inf, |
377 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 399 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); |
378 | if(rc == 0) | 400 | if(rc == 0) |
379 | cifsFile->invalidHandle = FALSE; | 401 | cifsFile->invalidHandle = FALSE; |
380 | if((rc == -EOPNOTSUPP) && | 402 | if((rc == -EOPNOTSUPP) && |
@@ -536,7 +558,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
536 | while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && | 558 | while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && |
537 | (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ | 559 | (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ |
538 | cFYI(1,("calling findnext2")); | 560 | cFYI(1,("calling findnext2")); |
539 | rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); | 561 | rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, |
562 | &cifsFile->srch_inf); | ||
540 | if(rc) | 563 | if(rc) |
541 | return -ENOENT; | 564 | return -ENOENT; |
542 | } | 565 | } |
@@ -548,14 +571,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
548 | char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + | 571 | char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + |
549 | smbCalcSize((struct smb_hdr *) | 572 | smbCalcSize((struct smb_hdr *) |
550 | cifsFile->srch_inf.ntwrk_buf_start); | 573 | cifsFile->srch_inf.ntwrk_buf_start); |
551 | /* dump_cifs_file_struct(file,"found entry in fce "); */ | ||
552 | first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry | 574 | first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry |
553 | - cifsFile->srch_inf.entries_in_buffer; | 575 | - cifsFile->srch_inf.entries_in_buffer; |
554 | pos_in_buf = index_to_find - first_entry_in_buffer; | 576 | pos_in_buf = index_to_find - first_entry_in_buffer; |
555 | cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); | 577 | cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); |
556 | current_entry = cifsFile->srch_inf.srch_entries_start; | 578 | current_entry = cifsFile->srch_inf.srch_entries_start; |
557 | for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { | 579 | for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { |
558 | /* go entry to next entry figuring out which we need to start with */ | 580 | /* go entry by entry figuring out which is first */ |
559 | /* if( . or ..) | 581 | /* if( . or ..) |
560 | skip */ | 582 | skip */ |
561 | rc = cifs_entry_is_dot(current_entry,cifsFile); | 583 | rc = cifs_entry_is_dot(current_entry,cifsFile); |
@@ -586,7 +608,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
586 | *num_to_ret = 0; | 608 | *num_to_ret = 0; |
587 | } else | 609 | } else |
588 | *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; | 610 | *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; |
589 | /* dump_cifs_file_struct(file, "end fce ");*/ | ||
590 | 611 | ||
591 | return rc; | 612 | return rc; |
592 | } | 613 | } |
@@ -721,7 +742,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
721 | (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); | 742 | (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); |
722 | } | 743 | } |
723 | 744 | ||
724 | rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); | 745 | rc = filldir(direntry,qstring.name,qstring.len,file->f_pos, |
746 | tmp_inode->i_ino,obj_type); | ||
725 | if(rc) { | 747 | if(rc) { |
726 | cFYI(1,("filldir rc = %d",rc)); | 748 | cFYI(1,("filldir rc = %d",rc)); |
727 | } | 749 | } |
@@ -805,14 +827,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
805 | FreeXid(xid); | 827 | FreeXid(xid); |
806 | return -EIO; | 828 | return -EIO; |
807 | } | 829 | } |
808 | /* dump_cifs_file_struct(file, "Begin rdir "); */ | ||
809 | 830 | ||
810 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 831 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
811 | pTcon = cifs_sb->tcon; | 832 | pTcon = cifs_sb->tcon; |
812 | if(pTcon == NULL) | 833 | if(pTcon == NULL) |
813 | return -EINVAL; | 834 | return -EINVAL; |
814 | 835 | ||
815 | /* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */ | ||
816 | 836 | ||
817 | switch ((int) file->f_pos) { | 837 | switch ((int) file->f_pos) { |
818 | case 0: | 838 | case 0: |
@@ -866,7 +886,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
866 | cifsFile->search_resume_name = NULL; */ | 886 | cifsFile->search_resume_name = NULL; */ |
867 | 887 | ||
868 | /* BB account for . and .. in f_pos as special case */ | 888 | /* BB account for . and .. in f_pos as special case */ |
869 | /* dump_cifs_file_struct(file, "rdir after default ");*/ | ||
870 | 889 | ||
871 | rc = find_cifs_entry(xid,pTcon, file, | 890 | rc = find_cifs_entry(xid,pTcon, file, |
872 | ¤t_entry,&num_to_fill); | 891 | ¤t_entry,&num_to_fill); |
@@ -906,14 +925,14 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
906 | cifs_save_resume_key(current_entry,cifsFile); | 925 | cifs_save_resume_key(current_entry,cifsFile); |
907 | break; | 926 | break; |
908 | } else | 927 | } else |
909 | current_entry = nxt_dir_entry(current_entry,end_of_smb); | 928 | current_entry = nxt_dir_entry(current_entry, |
929 | end_of_smb); | ||
910 | } | 930 | } |
911 | kfree(tmp_buf); | 931 | kfree(tmp_buf); |
912 | break; | 932 | break; |
913 | } /* end switch */ | 933 | } /* end switch */ |
914 | 934 | ||
915 | rddir2_exit: | 935 | rddir2_exit: |
916 | /* dump_cifs_file_struct(file, "end rdir "); */ | ||
917 | FreeXid(xid); | 936 | FreeXid(xid); |
918 | return rc; | 937 | return rc; |
919 | } | 938 | } |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 0046c219833d..96f89eb66040 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) | |||
49 | return NULL; | 49 | return NULL; |
50 | } | 50 | } |
51 | 51 | ||
52 | temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS); | 52 | temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp, |
53 | SLAB_KERNEL | SLAB_NOFS); | ||
53 | if (temp == NULL) | 54 | if (temp == NULL) |
54 | return temp; | 55 | return temp; |
55 | else { | 56 | else { |
@@ -179,27 +180,24 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
179 | return rc; | 180 | return rc; |
180 | } | 181 | } |
181 | 182 | ||
182 | #ifdef CIFS_EXPERIMENTAL | 183 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
183 | /* BB finish off this function, adding support for writing set of pages as iovec */ | 184 | static int |
184 | /* and also adding support for operations that need to parse the response smb */ | 185 | smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer, |
185 | 186 | unsigned int smb_hdr_length, const char * data, unsigned int datalen, | |
186 | int | 187 | struct sockaddr *sin) |
187 | smb_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 | |||
250 | int | 261 | int |
251 | CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, | 262 | SendReceive2(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); |
373 | cifs_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 | } | ||
491 | cifs_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 | ||
501 | out_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 | ||
388 | int | 513 | int |
@@ -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 | } |
616 | cifs_no_response_exit: | 741 | cifs_no_response_exit: |