diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-30 19:24:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-30 19:24:38 -0400 |
commit | 10f3cb41d48ab30f5c754b30eea557371892b4c2 (patch) | |
tree | 55db8e4177da00b6184f5428b4529cd59978e885 /fs | |
parent | 919c840167ec93167e00ca817aa4627170419ebf (diff) | |
parent | 867646f246de2dd5c91c480637a4901732ea3151 (diff) |
Merge git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French.
* git://git.samba.org/sfrench/cifs-2.6:
[CIFS] Update CIFS version number to 1.77
CIFS: Add missed forcemand mount option
[CIFS] Fix trivial sparse warning with asyn i/o patch
cifs: handle "sloppy" option appropriately
cifs: use standard token parser for mount options
cifs: remove /proc/fs/cifs/OplockEnabled
cifs: convert cifs_iovec_write to use async writes
cifs: call cifs_update_eof with i_lock held
cifs: abstract out function to marshal up the iovec array for async writes
cifs: fix up get_numpages
cifs: make cifsFileInfo_get return the cifsFileInfo pointer
cifs: fix allocation in cifs_write_allocate_pages
cifs: allow caller to specify completion op when allocating writedata
cifs: add pid field to cifs_writedata
cifs: add new cifsiod_wq workqueue
CIFS: Change mid_q_entry structure fields
CIFS: Expand CurrentMid field
CIFS: Separate protocol-specific code from cifs_readv_receive code
CIFS: Separate protocol-specific code from demultiplex code
CIFS: Separate protocol-specific code from transport routines
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_debug.c | 68 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 13 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 39 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 20 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 126 | ||||
-rw-r--r-- | fs/cifs/connect.c | 1454 | ||||
-rw-r--r-- | fs/cifs/file.c | 271 | ||||
-rw-r--r-- | fs/cifs/misc.c | 100 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 3 | ||||
-rw-r--r-- | fs/cifs/transport.c | 227 |
12 files changed, 1381 insertions, 946 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 573b899b5a5d..270464629416 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -58,15 +58,16 @@ cifs_dump_mem(char *label, void *data, int length) | |||
58 | } | 58 | } |
59 | 59 | ||
60 | #ifdef CONFIG_CIFS_DEBUG2 | 60 | #ifdef CONFIG_CIFS_DEBUG2 |
61 | void cifs_dump_detail(struct smb_hdr *smb) | 61 | void cifs_dump_detail(void *buf) |
62 | { | 62 | { |
63 | struct smb_hdr *smb = (struct smb_hdr *)buf; | ||
64 | |||
63 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", | 65 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", |
64 | smb->Command, smb->Status.CifsError, | 66 | smb->Command, smb->Status.CifsError, |
65 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); | 67 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); |
66 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); | 68 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); |
67 | } | 69 | } |
68 | 70 | ||
69 | |||
70 | void cifs_dump_mids(struct TCP_Server_Info *server) | 71 | void cifs_dump_mids(struct TCP_Server_Info *server) |
71 | { | 72 | { |
72 | struct list_head *tmp; | 73 | struct list_head *tmp; |
@@ -79,15 +80,15 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
79 | spin_lock(&GlobalMid_Lock); | 80 | spin_lock(&GlobalMid_Lock); |
80 | list_for_each(tmp, &server->pending_mid_q) { | 81 | list_for_each(tmp, &server->pending_mid_q) { |
81 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 82 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
82 | cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %d", | 83 | cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu", |
83 | mid_entry->midState, | 84 | mid_entry->mid_state, |
84 | (int)mid_entry->command, | 85 | le16_to_cpu(mid_entry->command), |
85 | mid_entry->pid, | 86 | mid_entry->pid, |
86 | mid_entry->callback_data, | 87 | mid_entry->callback_data, |
87 | mid_entry->mid); | 88 | mid_entry->mid); |
88 | #ifdef CONFIG_CIFS_STATS2 | 89 | #ifdef CONFIG_CIFS_STATS2 |
89 | cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", | 90 | cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", |
90 | mid_entry->largeBuf, | 91 | mid_entry->large_buf, |
91 | mid_entry->resp_buf, | 92 | mid_entry->resp_buf, |
92 | mid_entry->when_received, | 93 | mid_entry->when_received, |
93 | jiffies); | 94 | jiffies); |
@@ -217,12 +218,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
217 | mid_entry = list_entry(tmp3, struct mid_q_entry, | 218 | mid_entry = list_entry(tmp3, struct mid_q_entry, |
218 | qhead); | 219 | qhead); |
219 | seq_printf(m, "\tState: %d com: %d pid:" | 220 | seq_printf(m, "\tState: %d com: %d pid:" |
220 | " %d cbdata: %p mid %d\n", | 221 | " %d cbdata: %p mid %llu\n", |
221 | mid_entry->midState, | 222 | mid_entry->mid_state, |
222 | (int)mid_entry->command, | 223 | le16_to_cpu(mid_entry->command), |
223 | mid_entry->pid, | 224 | mid_entry->pid, |
224 | mid_entry->callback_data, | 225 | mid_entry->callback_data, |
225 | mid_entry->mid); | 226 | mid_entry->mid); |
226 | } | 227 | } |
227 | spin_unlock(&GlobalMid_Lock); | 228 | spin_unlock(&GlobalMid_Lock); |
228 | } | 229 | } |
@@ -417,7 +418,6 @@ static const struct file_operations cifs_stats_proc_fops = { | |||
417 | 418 | ||
418 | static struct proc_dir_entry *proc_fs_cifs; | 419 | static struct proc_dir_entry *proc_fs_cifs; |
419 | static const struct file_operations cifsFYI_proc_fops; | 420 | static const struct file_operations cifsFYI_proc_fops; |
420 | static const struct file_operations cifs_oplock_proc_fops; | ||
421 | static const struct file_operations cifs_lookup_cache_proc_fops; | 421 | static const struct file_operations cifs_lookup_cache_proc_fops; |
422 | static const struct file_operations traceSMB_proc_fops; | 422 | static const struct file_operations traceSMB_proc_fops; |
423 | static const struct file_operations cifs_multiuser_mount_proc_fops; | 423 | static const struct file_operations cifs_multiuser_mount_proc_fops; |
@@ -438,7 +438,6 @@ cifs_proc_init(void) | |||
438 | #endif /* STATS */ | 438 | #endif /* STATS */ |
439 | proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); | 439 | proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); |
440 | proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); | 440 | proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); |
441 | proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops); | ||
442 | proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, | 441 | proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, |
443 | &cifs_linux_ext_proc_fops); | 442 | &cifs_linux_ext_proc_fops); |
444 | proc_create("MultiuserMount", 0, proc_fs_cifs, | 443 | proc_create("MultiuserMount", 0, proc_fs_cifs, |
@@ -462,7 +461,6 @@ cifs_proc_clean(void) | |||
462 | remove_proc_entry("Stats", proc_fs_cifs); | 461 | remove_proc_entry("Stats", proc_fs_cifs); |
463 | #endif | 462 | #endif |
464 | remove_proc_entry("MultiuserMount", proc_fs_cifs); | 463 | remove_proc_entry("MultiuserMount", proc_fs_cifs); |
465 | remove_proc_entry("OplockEnabled", proc_fs_cifs); | ||
466 | remove_proc_entry("SecurityFlags", proc_fs_cifs); | 464 | remove_proc_entry("SecurityFlags", proc_fs_cifs); |
467 | remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); | 465 | remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); |
468 | remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); | 466 | remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); |
@@ -508,46 +506,6 @@ static const struct file_operations cifsFYI_proc_fops = { | |||
508 | .write = cifsFYI_proc_write, | 506 | .write = cifsFYI_proc_write, |
509 | }; | 507 | }; |
510 | 508 | ||
511 | static int cifs_oplock_proc_show(struct seq_file *m, void *v) | ||
512 | { | ||
513 | seq_printf(m, "%d\n", enable_oplocks); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int cifs_oplock_proc_open(struct inode *inode, struct file *file) | ||
518 | { | ||
519 | return single_open(file, cifs_oplock_proc_show, NULL); | ||
520 | } | ||
521 | |||
522 | static ssize_t cifs_oplock_proc_write(struct file *file, | ||
523 | const char __user *buffer, size_t count, loff_t *ppos) | ||
524 | { | ||
525 | char c; | ||
526 | int rc; | ||
527 | |||
528 | printk(KERN_WARNING "CIFS: The /proc/fs/cifs/OplockEnabled interface " | ||
529 | "will be removed in kernel version 3.4. Please migrate to " | ||
530 | "using the 'enable_oplocks' module parameter in cifs.ko.\n"); | ||
531 | rc = get_user(c, buffer); | ||
532 | if (rc) | ||
533 | return rc; | ||
534 | if (c == '0' || c == 'n' || c == 'N') | ||
535 | enable_oplocks = false; | ||
536 | else if (c == '1' || c == 'y' || c == 'Y') | ||
537 | enable_oplocks = true; | ||
538 | |||
539 | return count; | ||
540 | } | ||
541 | |||
542 | static const struct file_operations cifs_oplock_proc_fops = { | ||
543 | .owner = THIS_MODULE, | ||
544 | .open = cifs_oplock_proc_open, | ||
545 | .read = seq_read, | ||
546 | .llseek = seq_lseek, | ||
547 | .release = single_release, | ||
548 | .write = cifs_oplock_proc_write, | ||
549 | }; | ||
550 | |||
551 | static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) | 509 | static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) |
552 | { | 510 | { |
553 | seq_printf(m, "%d\n", linuxExtEnabled); | 511 | seq_printf(m, "%d\n", linuxExtEnabled); |
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 8942b28cf807..566e0ae8dc2c 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h | |||
@@ -26,13 +26,13 @@ | |||
26 | void cifs_dump_mem(char *label, void *data, int length); | 26 | void cifs_dump_mem(char *label, void *data, int length); |
27 | #ifdef CONFIG_CIFS_DEBUG2 | 27 | #ifdef CONFIG_CIFS_DEBUG2 |
28 | #define DBG2 2 | 28 | #define DBG2 2 |
29 | void cifs_dump_detail(struct smb_hdr *); | 29 | void cifs_dump_detail(void *); |
30 | void cifs_dump_mids(struct TCP_Server_Info *); | 30 | void cifs_dump_mids(struct TCP_Server_Info *); |
31 | #else | 31 | #else |
32 | #define DBG2 0 | 32 | #define DBG2 0 |
33 | #endif | 33 | #endif |
34 | extern int traceSMB; /* flag which enables the function below */ | 34 | extern int traceSMB; /* flag which enables the function below */ |
35 | void dump_smb(struct smb_hdr *, int); | 35 | void dump_smb(void *, int); |
36 | #define CIFS_INFO 0x01 | 36 | #define CIFS_INFO 0x01 |
37 | #define CIFS_RC 0x02 | 37 | #define CIFS_RC 0x02 |
38 | #define CIFS_TIMER 0x04 | 38 | #define CIFS_TIMER 0x04 |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index eee522c56ef0..d34212822444 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -85,6 +85,8 @@ extern mempool_t *cifs_sm_req_poolp; | |||
85 | extern mempool_t *cifs_req_poolp; | 85 | extern mempool_t *cifs_req_poolp; |
86 | extern mempool_t *cifs_mid_poolp; | 86 | extern mempool_t *cifs_mid_poolp; |
87 | 87 | ||
88 | struct workqueue_struct *cifsiod_wq; | ||
89 | |||
88 | static int | 90 | static int |
89 | cifs_read_super(struct super_block *sb) | 91 | cifs_read_super(struct super_block *sb) |
90 | { | 92 | { |
@@ -1111,9 +1113,15 @@ init_cifs(void) | |||
1111 | cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ); | 1113 | cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ); |
1112 | } | 1114 | } |
1113 | 1115 | ||
1116 | cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); | ||
1117 | if (!cifsiod_wq) { | ||
1118 | rc = -ENOMEM; | ||
1119 | goto out_clean_proc; | ||
1120 | } | ||
1121 | |||
1114 | rc = cifs_fscache_register(); | 1122 | rc = cifs_fscache_register(); |
1115 | if (rc) | 1123 | if (rc) |
1116 | goto out_clean_proc; | 1124 | goto out_destroy_wq; |
1117 | 1125 | ||
1118 | rc = cifs_init_inodecache(); | 1126 | rc = cifs_init_inodecache(); |
1119 | if (rc) | 1127 | if (rc) |
@@ -1161,6 +1169,8 @@ out_destroy_inodecache: | |||
1161 | cifs_destroy_inodecache(); | 1169 | cifs_destroy_inodecache(); |
1162 | out_unreg_fscache: | 1170 | out_unreg_fscache: |
1163 | cifs_fscache_unregister(); | 1171 | cifs_fscache_unregister(); |
1172 | out_destroy_wq: | ||
1173 | destroy_workqueue(cifsiod_wq); | ||
1164 | out_clean_proc: | 1174 | out_clean_proc: |
1165 | cifs_proc_clean(); | 1175 | cifs_proc_clean(); |
1166 | return rc; | 1176 | return rc; |
@@ -1183,6 +1193,7 @@ exit_cifs(void) | |||
1183 | cifs_destroy_mids(); | 1193 | cifs_destroy_mids(); |
1184 | cifs_destroy_inodecache(); | 1194 | cifs_destroy_inodecache(); |
1185 | cifs_fscache_unregister(); | 1195 | cifs_fscache_unregister(); |
1196 | destroy_workqueue(cifsiod_wq); | ||
1186 | cifs_proc_clean(); | 1197 | cifs_proc_clean(); |
1187 | } | 1198 | } |
1188 | 1199 | ||
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index fe5ecf1b422a..d1389bb33ceb 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -125,5 +125,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
125 | extern const struct export_operations cifs_export_ops; | 125 | extern const struct export_operations cifs_export_ops; |
126 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 126 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
127 | 127 | ||
128 | #define CIFS_VERSION "1.76" | 128 | #define CIFS_VERSION "1.77" |
129 | #endif /* _CIFSFS_H */ | 129 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 339ebe3ebc0d..4ff6313f0a91 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -230,6 +230,12 @@ struct cifs_mnt_data { | |||
230 | int flags; | 230 | int flags; |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static inline unsigned int | ||
234 | get_rfc1002_length(void *buf) | ||
235 | { | ||
236 | return be32_to_cpu(*((__be32 *)buf)); | ||
237 | } | ||
238 | |||
233 | struct TCP_Server_Info { | 239 | struct TCP_Server_Info { |
234 | struct list_head tcp_ses_list; | 240 | struct list_head tcp_ses_list; |
235 | struct list_head smb_ses_list; | 241 | struct list_head smb_ses_list; |
@@ -276,7 +282,7 @@ struct TCP_Server_Info { | |||
276 | vcnumbers */ | 282 | vcnumbers */ |
277 | int capabilities; /* allow selective disabling of caps by smb sess */ | 283 | int capabilities; /* allow selective disabling of caps by smb sess */ |
278 | int timeAdj; /* Adjust for difference in server time zone in sec */ | 284 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
279 | __u16 CurrentMid; /* multiplex id - rotating counter */ | 285 | __u64 CurrentMid; /* multiplex id - rotating counter */ |
280 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ | 286 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ |
281 | /* 16th byte of RFC1001 workstation name is always null */ | 287 | /* 16th byte of RFC1001 workstation name is always null */ |
282 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 288 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
@@ -335,6 +341,18 @@ has_credits(struct TCP_Server_Info *server, int *credits) | |||
335 | return num > 0; | 341 | return num > 0; |
336 | } | 342 | } |
337 | 343 | ||
344 | static inline size_t | ||
345 | header_size(void) | ||
346 | { | ||
347 | return sizeof(struct smb_hdr); | ||
348 | } | ||
349 | |||
350 | static inline size_t | ||
351 | max_header_size(void) | ||
352 | { | ||
353 | return MAX_CIFS_HDR_SIZE; | ||
354 | } | ||
355 | |||
338 | /* | 356 | /* |
339 | * Macros to allow the TCP_Server_Info->net field and related code to drop out | 357 | * Macros to allow the TCP_Server_Info->net field and related code to drop out |
340 | * when CONFIG_NET_NS isn't set. | 358 | * when CONFIG_NET_NS isn't set. |
@@ -583,9 +601,11 @@ struct cifs_io_parms { | |||
583 | * Take a reference on the file private data. Must be called with | 601 | * Take a reference on the file private data. Must be called with |
584 | * cifs_file_list_lock held. | 602 | * cifs_file_list_lock held. |
585 | */ | 603 | */ |
586 | static inline void cifsFileInfo_get(struct cifsFileInfo *cifs_file) | 604 | static inline |
605 | struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) | ||
587 | { | 606 | { |
588 | ++cifs_file->count; | 607 | ++cifs_file->count; |
608 | return cifs_file; | ||
589 | } | 609 | } |
590 | 610 | ||
591 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file); | 611 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file); |
@@ -606,7 +626,7 @@ struct cifsInodeInfo { | |||
606 | bool delete_pending; /* DELETE_ON_CLOSE is set */ | 626 | bool delete_pending; /* DELETE_ON_CLOSE is set */ |
607 | bool invalid_mapping; /* pagecache is invalid */ | 627 | bool invalid_mapping; /* pagecache is invalid */ |
608 | unsigned long time; /* jiffies of last update of inode */ | 628 | unsigned long time; /* jiffies of last update of inode */ |
609 | u64 server_eof; /* current file size on server */ | 629 | u64 server_eof; /* current file size on server -- protected by i_lock */ |
610 | u64 uniqueid; /* server inode number */ | 630 | u64 uniqueid; /* server inode number */ |
611 | u64 createtime; /* creation time on server */ | 631 | u64 createtime; /* creation time on server */ |
612 | #ifdef CONFIG_CIFS_FSCACHE | 632 | #ifdef CONFIG_CIFS_FSCACHE |
@@ -713,8 +733,8 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid); | |||
713 | /* one of these for every pending CIFS request to the server */ | 733 | /* one of these for every pending CIFS request to the server */ |
714 | struct mid_q_entry { | 734 | struct mid_q_entry { |
715 | struct list_head qhead; /* mids waiting on reply from this server */ | 735 | struct list_head qhead; /* mids waiting on reply from this server */ |
716 | __u16 mid; /* multiplex id */ | 736 | __u64 mid; /* multiplex id */ |
717 | __u16 pid; /* process id */ | 737 | __u32 pid; /* process id */ |
718 | __u32 sequence_number; /* for CIFS signing */ | 738 | __u32 sequence_number; /* for CIFS signing */ |
719 | unsigned long when_alloc; /* when mid was created */ | 739 | unsigned long when_alloc; /* when mid was created */ |
720 | #ifdef CONFIG_CIFS_STATS2 | 740 | #ifdef CONFIG_CIFS_STATS2 |
@@ -724,10 +744,10 @@ struct mid_q_entry { | |||
724 | mid_receive_t *receive; /* call receive callback */ | 744 | mid_receive_t *receive; /* call receive callback */ |
725 | mid_callback_t *callback; /* call completion callback */ | 745 | mid_callback_t *callback; /* call completion callback */ |
726 | void *callback_data; /* general purpose pointer for callback */ | 746 | void *callback_data; /* general purpose pointer for callback */ |
727 | struct smb_hdr *resp_buf; /* pointer to received SMB header */ | 747 | void *resp_buf; /* pointer to received SMB header */ |
728 | int midState; /* wish this were enum but can not pass to wait_event */ | 748 | int mid_state; /* wish this were enum but can not pass to wait_event */ |
729 | __u8 command; /* smb command code */ | 749 | __le16 command; /* smb command code */ |
730 | bool largeBuf:1; /* if valid response, is pointer to large buf */ | 750 | bool large_buf:1; /* if valid response, is pointer to large buf */ |
731 | bool multiRsp:1; /* multiple trans2 responses for one request */ | 751 | bool multiRsp:1; /* multiple trans2 responses for one request */ |
732 | bool multiEnd:1; /* both received */ | 752 | bool multiEnd:1; /* both received */ |
733 | }; | 753 | }; |
@@ -1052,5 +1072,6 @@ GLOBAL_EXTERN spinlock_t gidsidlock; | |||
1052 | void cifs_oplock_break(struct work_struct *work); | 1072 | void cifs_oplock_break(struct work_struct *work); |
1053 | 1073 | ||
1054 | extern const struct slow_work_ops cifs_oplock_break_ops; | 1074 | extern const struct slow_work_ops cifs_oplock_break_ops; |
1075 | extern struct workqueue_struct *cifsiod_wq; | ||
1055 | 1076 | ||
1056 | #endif /* _CIFS_GLOB_H */ | 1077 | #endif /* _CIFS_GLOB_H */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 503e73d8bdb7..96192c1e380a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -77,7 +77,7 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, | |||
77 | struct smb_hdr * /* out */ , | 77 | struct smb_hdr * /* out */ , |
78 | int * /* bytes returned */ , const int long_op); | 78 | int * /* bytes returned */ , const int long_op); |
79 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, | 79 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, |
80 | struct smb_hdr *in_buf, int flags); | 80 | char *in_buf, int flags); |
81 | extern int cifs_check_receive(struct mid_q_entry *mid, | 81 | extern int cifs_check_receive(struct mid_q_entry *mid, |
82 | struct TCP_Server_Info *server, bool log_error); | 82 | struct TCP_Server_Info *server, bool log_error); |
83 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, | 83 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, |
@@ -91,9 +91,8 @@ extern int SendReceiveBlockingLock(const unsigned int xid, | |||
91 | extern void cifs_add_credits(struct TCP_Server_Info *server, | 91 | extern void cifs_add_credits(struct TCP_Server_Info *server, |
92 | const unsigned int add); | 92 | const unsigned int add); |
93 | extern void cifs_set_credits(struct TCP_Server_Info *server, const int val); | 93 | extern void cifs_set_credits(struct TCP_Server_Info *server, const int val); |
94 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); | 94 | extern int checkSMB(char *buf, unsigned int length); |
95 | extern bool is_valid_oplock_break(struct smb_hdr *smb, | 95 | extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); |
96 | struct TCP_Server_Info *); | ||
97 | extern bool backup_cred(struct cifs_sb_info *); | 96 | extern bool backup_cred(struct cifs_sb_info *); |
98 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 97 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
99 | extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | 98 | extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, |
@@ -107,7 +106,7 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | |||
107 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); | 106 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); |
108 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 107 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, |
109 | const unsigned short int port); | 108 | const unsigned short int port); |
110 | extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr); | 109 | extern int map_smb_to_linux_error(char *buf, bool logErr); |
111 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 110 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
112 | const struct cifs_tcon *, int /* length of | 111 | const struct cifs_tcon *, int /* length of |
113 | fixed section (word count) in two byte units */); | 112 | fixed section (word count) in two byte units */); |
@@ -116,7 +115,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | |||
116 | void **request_buf); | 115 | void **request_buf); |
117 | extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, | 116 | extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, |
118 | const struct nls_table *nls_cp); | 117 | const struct nls_table *nls_cp); |
119 | extern __u16 GetNextMid(struct TCP_Server_Info *server); | 118 | extern __u64 GetNextMid(struct TCP_Server_Info *server); |
120 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); | 119 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); |
121 | extern u64 cifs_UnixTimeToNT(struct timespec); | 120 | extern u64 cifs_UnixTimeToNT(struct timespec); |
122 | extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | 121 | extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, |
@@ -484,18 +483,25 @@ int cifs_async_readv(struct cifs_readdata *rdata); | |||
484 | /* asynchronous write support */ | 483 | /* asynchronous write support */ |
485 | struct cifs_writedata { | 484 | struct cifs_writedata { |
486 | struct kref refcount; | 485 | struct kref refcount; |
486 | struct list_head list; | ||
487 | struct completion done; | ||
487 | enum writeback_sync_modes sync_mode; | 488 | enum writeback_sync_modes sync_mode; |
488 | struct work_struct work; | 489 | struct work_struct work; |
489 | struct cifsFileInfo *cfile; | 490 | struct cifsFileInfo *cfile; |
490 | __u64 offset; | 491 | __u64 offset; |
492 | pid_t pid; | ||
491 | unsigned int bytes; | 493 | unsigned int bytes; |
492 | int result; | 494 | int result; |
495 | void (*marshal_iov) (struct kvec *iov, | ||
496 | struct cifs_writedata *wdata); | ||
493 | unsigned int nr_pages; | 497 | unsigned int nr_pages; |
494 | struct page *pages[1]; | 498 | struct page *pages[1]; |
495 | }; | 499 | }; |
496 | 500 | ||
497 | int cifs_async_writev(struct cifs_writedata *wdata); | 501 | int cifs_async_writev(struct cifs_writedata *wdata); |
498 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages); | 502 | void cifs_writev_complete(struct work_struct *work); |
503 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | ||
504 | work_func_t complete); | ||
499 | void cifs_writedata_release(struct kref *refcount); | 505 | void cifs_writedata_release(struct kref *refcount); |
500 | 506 | ||
501 | #endif /* _CIFSPROTO_H */ | 507 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 70aac35c398f..8fecc99be344 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -696,7 +696,7 @@ CIFSSMBTDis(const int xid, struct cifs_tcon *tcon) | |||
696 | if (rc) | 696 | if (rc) |
697 | return rc; | 697 | return rc; |
698 | 698 | ||
699 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); | 699 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); |
700 | if (rc) | 700 | if (rc) |
701 | cFYI(1, "Tree disconnect failed %d", rc); | 701 | cFYI(1, "Tree disconnect failed %d", rc); |
702 | 702 | ||
@@ -792,7 +792,7 @@ CIFSSMBLogoff(const int xid, struct cifs_ses *ses) | |||
792 | pSMB->hdr.Uid = ses->Suid; | 792 | pSMB->hdr.Uid = ses->Suid; |
793 | 793 | ||
794 | pSMB->AndXCommand = 0xFF; | 794 | pSMB->AndXCommand = 0xFF; |
795 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 795 | rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); |
796 | session_already_dead: | 796 | session_already_dead: |
797 | mutex_unlock(&ses->session_mutex); | 797 | mutex_unlock(&ses->session_mutex); |
798 | 798 | ||
@@ -1414,8 +1414,7 @@ cifs_readdata_free(struct cifs_readdata *rdata) | |||
1414 | static int | 1414 | static int |
1415 | cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | 1415 | cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) |
1416 | { | 1416 | { |
1417 | READ_RSP *rsp = (READ_RSP *)server->smallbuf; | 1417 | unsigned int rfclen = get_rfc1002_length(server->smallbuf); |
1418 | unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length); | ||
1419 | int remaining = rfclen + 4 - server->total_read; | 1418 | int remaining = rfclen + 4 - server->total_read; |
1420 | struct cifs_readdata *rdata = mid->callback_data; | 1419 | struct cifs_readdata *rdata = mid->callback_data; |
1421 | 1420 | ||
@@ -1424,7 +1423,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1424 | 1423 | ||
1425 | length = cifs_read_from_socket(server, server->bigbuf, | 1424 | length = cifs_read_from_socket(server, server->bigbuf, |
1426 | min_t(unsigned int, remaining, | 1425 | min_t(unsigned int, remaining, |
1427 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)); | 1426 | CIFSMaxBufSize + max_header_size())); |
1428 | if (length < 0) | 1427 | if (length < 0) |
1429 | return length; | 1428 | return length; |
1430 | server->total_read += length; | 1429 | server->total_read += length; |
@@ -1435,19 +1434,40 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1435 | return 0; | 1434 | return 0; |
1436 | } | 1435 | } |
1437 | 1436 | ||
1437 | static inline size_t | ||
1438 | read_rsp_size(void) | ||
1439 | { | ||
1440 | return sizeof(READ_RSP); | ||
1441 | } | ||
1442 | |||
1443 | static inline unsigned int | ||
1444 | read_data_offset(char *buf) | ||
1445 | { | ||
1446 | READ_RSP *rsp = (READ_RSP *)buf; | ||
1447 | return le16_to_cpu(rsp->DataOffset); | ||
1448 | } | ||
1449 | |||
1450 | static inline unsigned int | ||
1451 | read_data_length(char *buf) | ||
1452 | { | ||
1453 | READ_RSP *rsp = (READ_RSP *)buf; | ||
1454 | return (le16_to_cpu(rsp->DataLengthHigh) << 16) + | ||
1455 | le16_to_cpu(rsp->DataLength); | ||
1456 | } | ||
1457 | |||
1438 | static int | 1458 | static int |
1439 | cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | 1459 | cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) |
1440 | { | 1460 | { |
1441 | int length, len; | 1461 | int length, len; |
1442 | unsigned int data_offset, remaining, data_len; | 1462 | unsigned int data_offset, remaining, data_len; |
1443 | struct cifs_readdata *rdata = mid->callback_data; | 1463 | struct cifs_readdata *rdata = mid->callback_data; |
1444 | READ_RSP *rsp = (READ_RSP *)server->smallbuf; | 1464 | char *buf = server->smallbuf; |
1445 | unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4; | 1465 | unsigned int buflen = get_rfc1002_length(buf) + 4; |
1446 | u64 eof; | 1466 | u64 eof; |
1447 | pgoff_t eof_index; | 1467 | pgoff_t eof_index; |
1448 | struct page *page, *tpage; | 1468 | struct page *page, *tpage; |
1449 | 1469 | ||
1450 | cFYI(1, "%s: mid=%u offset=%llu bytes=%u", __func__, | 1470 | cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__, |
1451 | mid->mid, rdata->offset, rdata->bytes); | 1471 | mid->mid, rdata->offset, rdata->bytes); |
1452 | 1472 | ||
1453 | /* | 1473 | /* |
@@ -1455,10 +1475,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1455 | * can if there's not enough data. At this point, we've read down to | 1475 | * can if there's not enough data. At this point, we've read down to |
1456 | * the Mid. | 1476 | * the Mid. |
1457 | */ | 1477 | */ |
1458 | len = min_t(unsigned int, rfclen, sizeof(*rsp)) - | 1478 | len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1; |
1459 | sizeof(struct smb_hdr) + 1; | ||
1460 | 1479 | ||
1461 | rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1; | 1480 | rdata->iov[0].iov_base = buf + header_size() - 1; |
1462 | rdata->iov[0].iov_len = len; | 1481 | rdata->iov[0].iov_len = len; |
1463 | 1482 | ||
1464 | length = cifs_readv_from_socket(server, rdata->iov, 1, len); | 1483 | length = cifs_readv_from_socket(server, rdata->iov, 1, len); |
@@ -1467,7 +1486,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1467 | server->total_read += length; | 1486 | server->total_read += length; |
1468 | 1487 | ||
1469 | /* Was the SMB read successful? */ | 1488 | /* Was the SMB read successful? */ |
1470 | rdata->result = map_smb_to_linux_error(&rsp->hdr, false); | 1489 | rdata->result = map_smb_to_linux_error(buf, false); |
1471 | if (rdata->result != 0) { | 1490 | if (rdata->result != 0) { |
1472 | cFYI(1, "%s: server returned error %d", __func__, | 1491 | cFYI(1, "%s: server returned error %d", __func__, |
1473 | rdata->result); | 1492 | rdata->result); |
@@ -1475,14 +1494,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1475 | } | 1494 | } |
1476 | 1495 | ||
1477 | /* Is there enough to get to the rest of the READ_RSP header? */ | 1496 | /* Is there enough to get to the rest of the READ_RSP header? */ |
1478 | if (server->total_read < sizeof(READ_RSP)) { | 1497 | if (server->total_read < read_rsp_size()) { |
1479 | cFYI(1, "%s: server returned short header. got=%u expected=%zu", | 1498 | cFYI(1, "%s: server returned short header. got=%u expected=%zu", |
1480 | __func__, server->total_read, sizeof(READ_RSP)); | 1499 | __func__, server->total_read, read_rsp_size()); |
1481 | rdata->result = -EIO; | 1500 | rdata->result = -EIO; |
1482 | return cifs_readv_discard(server, mid); | 1501 | return cifs_readv_discard(server, mid); |
1483 | } | 1502 | } |
1484 | 1503 | ||
1485 | data_offset = le16_to_cpu(rsp->DataOffset) + 4; | 1504 | data_offset = read_data_offset(buf) + 4; |
1486 | if (data_offset < server->total_read) { | 1505 | if (data_offset < server->total_read) { |
1487 | /* | 1506 | /* |
1488 | * win2k8 sometimes sends an offset of 0 when the read | 1507 | * win2k8 sometimes sends an offset of 0 when the read |
@@ -1506,7 +1525,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1506 | len = data_offset - server->total_read; | 1525 | len = data_offset - server->total_read; |
1507 | if (len > 0) { | 1526 | if (len > 0) { |
1508 | /* read any junk before data into the rest of smallbuf */ | 1527 | /* read any junk before data into the rest of smallbuf */ |
1509 | rdata->iov[0].iov_base = server->smallbuf + server->total_read; | 1528 | rdata->iov[0].iov_base = buf + server->total_read; |
1510 | rdata->iov[0].iov_len = len; | 1529 | rdata->iov[0].iov_len = len; |
1511 | length = cifs_readv_from_socket(server, rdata->iov, 1, len); | 1530 | length = cifs_readv_from_socket(server, rdata->iov, 1, len); |
1512 | if (length < 0) | 1531 | if (length < 0) |
@@ -1515,15 +1534,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1515 | } | 1534 | } |
1516 | 1535 | ||
1517 | /* set up first iov for signature check */ | 1536 | /* set up first iov for signature check */ |
1518 | rdata->iov[0].iov_base = server->smallbuf; | 1537 | rdata->iov[0].iov_base = buf; |
1519 | rdata->iov[0].iov_len = server->total_read; | 1538 | rdata->iov[0].iov_len = server->total_read; |
1520 | cFYI(1, "0: iov_base=%p iov_len=%zu", | 1539 | cFYI(1, "0: iov_base=%p iov_len=%zu", |
1521 | rdata->iov[0].iov_base, rdata->iov[0].iov_len); | 1540 | rdata->iov[0].iov_base, rdata->iov[0].iov_len); |
1522 | 1541 | ||
1523 | /* how much data is in the response? */ | 1542 | /* how much data is in the response? */ |
1524 | data_len = le16_to_cpu(rsp->DataLengthHigh) << 16; | 1543 | data_len = read_data_length(buf); |
1525 | data_len += le16_to_cpu(rsp->DataLength); | 1544 | if (data_offset + data_len > buflen) { |
1526 | if (data_offset + data_len > rfclen) { | ||
1527 | /* data_len is corrupt -- discard frame */ | 1545 | /* data_len is corrupt -- discard frame */ |
1528 | rdata->result = -EIO; | 1546 | rdata->result = -EIO; |
1529 | return cifs_readv_discard(server, mid); | 1547 | return cifs_readv_discard(server, mid); |
@@ -1602,11 +1620,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1602 | 1620 | ||
1603 | rdata->bytes = length; | 1621 | rdata->bytes = length; |
1604 | 1622 | ||
1605 | cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read, | 1623 | cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, |
1606 | rfclen, remaining); | 1624 | buflen, remaining); |
1607 | 1625 | ||
1608 | /* discard anything left over */ | 1626 | /* discard anything left over */ |
1609 | if (server->total_read < rfclen) | 1627 | if (server->total_read < buflen) |
1610 | return cifs_readv_discard(server, mid); | 1628 | return cifs_readv_discard(server, mid); |
1611 | 1629 | ||
1612 | dequeue_mid(mid, false); | 1630 | dequeue_mid(mid, false); |
@@ -1647,10 +1665,10 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1647 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | 1665 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
1648 | struct TCP_Server_Info *server = tcon->ses->server; | 1666 | struct TCP_Server_Info *server = tcon->ses->server; |
1649 | 1667 | ||
1650 | cFYI(1, "%s: mid=%u state=%d result=%d bytes=%u", __func__, | 1668 | cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, |
1651 | mid->mid, mid->midState, rdata->result, rdata->bytes); | 1669 | mid->mid, mid->mid_state, rdata->result, rdata->bytes); |
1652 | 1670 | ||
1653 | switch (mid->midState) { | 1671 | switch (mid->mid_state) { |
1654 | case MID_RESPONSE_RECEIVED: | 1672 | case MID_RESPONSE_RECEIVED: |
1655 | /* result already set, check signature */ | 1673 | /* result already set, check signature */ |
1656 | if (server->sec_mode & | 1674 | if (server->sec_mode & |
@@ -1671,7 +1689,7 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1671 | rdata->result = -EIO; | 1689 | rdata->result = -EIO; |
1672 | } | 1690 | } |
1673 | 1691 | ||
1674 | queue_work(system_nrt_wq, &rdata->work); | 1692 | queue_work(cifsiod_wq, &rdata->work); |
1675 | DeleteMidQEntry(mid); | 1693 | DeleteMidQEntry(mid); |
1676 | cifs_add_credits(server, 1); | 1694 | cifs_add_credits(server, 1); |
1677 | } | 1695 | } |
@@ -2017,7 +2035,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) | |||
2017 | kref_put(&wdata->refcount, cifs_writedata_release); | 2035 | kref_put(&wdata->refcount, cifs_writedata_release); |
2018 | } | 2036 | } |
2019 | 2037 | ||
2020 | static void | 2038 | void |
2021 | cifs_writev_complete(struct work_struct *work) | 2039 | cifs_writev_complete(struct work_struct *work) |
2022 | { | 2040 | { |
2023 | struct cifs_writedata *wdata = container_of(work, | 2041 | struct cifs_writedata *wdata = container_of(work, |
@@ -2026,7 +2044,9 @@ cifs_writev_complete(struct work_struct *work) | |||
2026 | int i = 0; | 2044 | int i = 0; |
2027 | 2045 | ||
2028 | if (wdata->result == 0) { | 2046 | if (wdata->result == 0) { |
2047 | spin_lock(&inode->i_lock); | ||
2029 | cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); | 2048 | cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); |
2049 | spin_unlock(&inode->i_lock); | ||
2030 | cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), | 2050 | cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), |
2031 | wdata->bytes); | 2051 | wdata->bytes); |
2032 | } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) | 2052 | } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) |
@@ -2047,7 +2067,7 @@ cifs_writev_complete(struct work_struct *work) | |||
2047 | } | 2067 | } |
2048 | 2068 | ||
2049 | struct cifs_writedata * | 2069 | struct cifs_writedata * |
2050 | cifs_writedata_alloc(unsigned int nr_pages) | 2070 | cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) |
2051 | { | 2071 | { |
2052 | struct cifs_writedata *wdata; | 2072 | struct cifs_writedata *wdata; |
2053 | 2073 | ||
@@ -2061,14 +2081,16 @@ cifs_writedata_alloc(unsigned int nr_pages) | |||
2061 | wdata = kzalloc(sizeof(*wdata) + | 2081 | wdata = kzalloc(sizeof(*wdata) + |
2062 | sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); | 2082 | sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); |
2063 | if (wdata != NULL) { | 2083 | if (wdata != NULL) { |
2064 | INIT_WORK(&wdata->work, cifs_writev_complete); | ||
2065 | kref_init(&wdata->refcount); | 2084 | kref_init(&wdata->refcount); |
2085 | INIT_LIST_HEAD(&wdata->list); | ||
2086 | init_completion(&wdata->done); | ||
2087 | INIT_WORK(&wdata->work, complete); | ||
2066 | } | 2088 | } |
2067 | return wdata; | 2089 | return wdata; |
2068 | } | 2090 | } |
2069 | 2091 | ||
2070 | /* | 2092 | /* |
2071 | * Check the midState and signature on received buffer (if any), and queue the | 2093 | * Check the mid_state and signature on received buffer (if any), and queue the |
2072 | * workqueue completion task. | 2094 | * workqueue completion task. |
2073 | */ | 2095 | */ |
2074 | static void | 2096 | static void |
@@ -2079,7 +2101,7 @@ cifs_writev_callback(struct mid_q_entry *mid) | |||
2079 | unsigned int written; | 2101 | unsigned int written; |
2080 | WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; | 2102 | WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; |
2081 | 2103 | ||
2082 | switch (mid->midState) { | 2104 | switch (mid->mid_state) { |
2083 | case MID_RESPONSE_RECEIVED: | 2105 | case MID_RESPONSE_RECEIVED: |
2084 | wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); | 2106 | wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); |
2085 | if (wdata->result != 0) | 2107 | if (wdata->result != 0) |
@@ -2111,7 +2133,7 @@ cifs_writev_callback(struct mid_q_entry *mid) | |||
2111 | break; | 2133 | break; |
2112 | } | 2134 | } |
2113 | 2135 | ||
2114 | queue_work(system_nrt_wq, &wdata->work); | 2136 | queue_work(cifsiod_wq, &wdata->work); |
2115 | DeleteMidQEntry(mid); | 2137 | DeleteMidQEntry(mid); |
2116 | cifs_add_credits(tcon->ses->server, 1); | 2138 | cifs_add_credits(tcon->ses->server, 1); |
2117 | } | 2139 | } |
@@ -2124,7 +2146,6 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
2124 | WRITE_REQ *smb = NULL; | 2146 | WRITE_REQ *smb = NULL; |
2125 | int wct; | 2147 | int wct; |
2126 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | 2148 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
2127 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
2128 | struct kvec *iov = NULL; | 2149 | struct kvec *iov = NULL; |
2129 | 2150 | ||
2130 | if (tcon->ses->capabilities & CAP_LARGE_FILES) { | 2151 | if (tcon->ses->capabilities & CAP_LARGE_FILES) { |
@@ -2148,8 +2169,8 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
2148 | goto async_writev_out; | 2169 | goto async_writev_out; |
2149 | } | 2170 | } |
2150 | 2171 | ||
2151 | smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid); | 2172 | smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); |
2152 | smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16)); | 2173 | smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); |
2153 | 2174 | ||
2154 | smb->AndXCommand = 0xFF; /* none */ | 2175 | smb->AndXCommand = 0xFF; /* none */ |
2155 | smb->Fid = wdata->cfile->netfid; | 2176 | smb->Fid = wdata->cfile->netfid; |
@@ -2167,15 +2188,13 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
2167 | iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; | 2188 | iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; |
2168 | iov[0].iov_base = smb; | 2189 | iov[0].iov_base = smb; |
2169 | 2190 | ||
2170 | /* marshal up the pages into iov array */ | 2191 | /* |
2171 | wdata->bytes = 0; | 2192 | * This function should marshal up the page array into the kvec |
2172 | for (i = 0; i < wdata->nr_pages; i++) { | 2193 | * array, reserving [0] for the header. It should kmap the pages |
2173 | iov[i + 1].iov_len = min(inode->i_size - | 2194 | * and set the iov_len properly for each one. It may also set |
2174 | page_offset(wdata->pages[i]), | 2195 | * wdata->bytes too. |
2175 | (loff_t)PAGE_CACHE_SIZE); | 2196 | */ |
2176 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | 2197 | wdata->marshal_iov(iov, wdata); |
2177 | wdata->bytes += iov[i + 1].iov_len; | ||
2178 | } | ||
2179 | 2198 | ||
2180 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | 2199 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); |
2181 | 2200 | ||
@@ -2420,8 +2439,7 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon, | |||
2420 | (struct smb_hdr *) pSMB, &bytes_returned); | 2439 | (struct smb_hdr *) pSMB, &bytes_returned); |
2421 | cifs_small_buf_release(pSMB); | 2440 | cifs_small_buf_release(pSMB); |
2422 | } else { | 2441 | } else { |
2423 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 2442 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout); |
2424 | timeout); | ||
2425 | /* SMB buffer freed by function above */ | 2443 | /* SMB buffer freed by function above */ |
2426 | } | 2444 | } |
2427 | cifs_stats_inc(&tcon->num_locks); | 2445 | cifs_stats_inc(&tcon->num_locks); |
@@ -2588,7 +2606,7 @@ CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2588 | pSMB->FileID = (__u16) smb_file_id; | 2606 | pSMB->FileID = (__u16) smb_file_id; |
2589 | pSMB->LastWriteTime = 0xFFFFFFFF; | 2607 | pSMB->LastWriteTime = 0xFFFFFFFF; |
2590 | pSMB->ByteCount = 0; | 2608 | pSMB->ByteCount = 0; |
2591 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 2609 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2592 | cifs_stats_inc(&tcon->num_closes); | 2610 | cifs_stats_inc(&tcon->num_closes); |
2593 | if (rc) { | 2611 | if (rc) { |
2594 | if (rc != -EINTR) { | 2612 | if (rc != -EINTR) { |
@@ -2617,7 +2635,7 @@ CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2617 | 2635 | ||
2618 | pSMB->FileID = (__u16) smb_file_id; | 2636 | pSMB->FileID = (__u16) smb_file_id; |
2619 | pSMB->ByteCount = 0; | 2637 | pSMB->ByteCount = 0; |
2620 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 2638 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2621 | cifs_stats_inc(&tcon->num_flushes); | 2639 | cifs_stats_inc(&tcon->num_flushes); |
2622 | if (rc) | 2640 | if (rc) |
2623 | cERROR(1, "Send error in Flush = %d", rc); | 2641 | cERROR(1, "Send error in Flush = %d", rc); |
@@ -4625,7 +4643,7 @@ CIFSFindClose(const int xid, struct cifs_tcon *tcon, | |||
4625 | 4643 | ||
4626 | pSMB->FileID = searchHandle; | 4644 | pSMB->FileID = searchHandle; |
4627 | pSMB->ByteCount = 0; | 4645 | pSMB->ByteCount = 0; |
4628 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 4646 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
4629 | if (rc) | 4647 | if (rc) |
4630 | cERROR(1, "Send error in FindClose = %d", rc); | 4648 | cERROR(1, "Send error in FindClose = %d", rc); |
4631 | 4649 | ||
@@ -5646,7 +5664,7 @@ CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size, | |||
5646 | pSMB->Reserved4 = 0; | 5664 | pSMB->Reserved4 = 0; |
5647 | inc_rfc1001_len(pSMB, byte_count); | 5665 | inc_rfc1001_len(pSMB, byte_count); |
5648 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5666 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5649 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5667 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5650 | if (rc) { | 5668 | if (rc) { |
5651 | cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); | 5669 | cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); |
5652 | } | 5670 | } |
@@ -5715,7 +5733,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, | |||
5715 | inc_rfc1001_len(pSMB, byte_count); | 5733 | inc_rfc1001_len(pSMB, byte_count); |
5716 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5734 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5717 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5735 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5718 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5736 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5719 | if (rc) | 5737 | if (rc) |
5720 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); | 5738 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); |
5721 | 5739 | ||
@@ -5774,7 +5792,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, | |||
5774 | inc_rfc1001_len(pSMB, byte_count); | 5792 | inc_rfc1001_len(pSMB, byte_count); |
5775 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5793 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5776 | *data_offset = delete_file ? 1 : 0; | 5794 | *data_offset = delete_file ? 1 : 0; |
5777 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5795 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5778 | if (rc) | 5796 | if (rc) |
5779 | cFYI(1, "Send error in SetFileDisposition = %d", rc); | 5797 | cFYI(1, "Send error in SetFileDisposition = %d", rc); |
5780 | 5798 | ||
@@ -6006,7 +6024,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, | |||
6006 | 6024 | ||
6007 | cifs_fill_unix_set_info(data_offset, args); | 6025 | cifs_fill_unix_set_info(data_offset, args); |
6008 | 6026 | ||
6009 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 6027 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
6010 | if (rc) | 6028 | if (rc) |
6011 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); | 6029 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); |
6012 | 6030 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5560e1d5e54b..302a15c505a9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <keys/user-type.h> | 41 | #include <keys/user-type.h> |
42 | #include <net/ipv6.h> | 42 | #include <net/ipv6.h> |
43 | #include <linux/parser.h> | ||
44 | |||
43 | #include "cifspdu.h" | 45 | #include "cifspdu.h" |
44 | #include "cifsglob.h" | 46 | #include "cifsglob.h" |
45 | #include "cifsproto.h" | 47 | #include "cifsproto.h" |
@@ -63,6 +65,193 @@ extern mempool_t *cifs_req_poolp; | |||
63 | #define TLINK_ERROR_EXPIRE (1 * HZ) | 65 | #define TLINK_ERROR_EXPIRE (1 * HZ) |
64 | #define TLINK_IDLE_EXPIRE (600 * HZ) | 66 | #define TLINK_IDLE_EXPIRE (600 * HZ) |
65 | 67 | ||
68 | enum { | ||
69 | |||
70 | /* Mount options that take no arguments */ | ||
71 | Opt_user_xattr, Opt_nouser_xattr, | ||
72 | Opt_forceuid, Opt_noforceuid, | ||
73 | Opt_noblocksend, Opt_noautotune, | ||
74 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, | ||
75 | Opt_mapchars, Opt_nomapchars, Opt_sfu, | ||
76 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, | ||
77 | Opt_noposixpaths, Opt_nounix, | ||
78 | Opt_nocase, | ||
79 | Opt_brl, Opt_nobrl, | ||
80 | Opt_forcemandatorylock, Opt_setuids, | ||
81 | Opt_nosetuids, Opt_dynperm, Opt_nodynperm, | ||
82 | Opt_nohard, Opt_nosoft, | ||
83 | Opt_nointr, Opt_intr, | ||
84 | Opt_nostrictsync, Opt_strictsync, | ||
85 | Opt_serverino, Opt_noserverino, | ||
86 | Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, | ||
87 | Opt_acl, Opt_noacl, Opt_locallease, | ||
88 | Opt_sign, Opt_seal, Opt_direct, | ||
89 | Opt_strictcache, Opt_noac, | ||
90 | Opt_fsc, Opt_mfsymlinks, | ||
91 | Opt_multiuser, Opt_sloppy, | ||
92 | |||
93 | /* Mount options which take numeric value */ | ||
94 | Opt_backupuid, Opt_backupgid, Opt_uid, | ||
95 | Opt_cruid, Opt_gid, Opt_file_mode, | ||
96 | Opt_dirmode, Opt_port, | ||
97 | Opt_rsize, Opt_wsize, Opt_actimeo, | ||
98 | |||
99 | /* Mount options which take string value */ | ||
100 | Opt_user, Opt_pass, Opt_ip, | ||
101 | Opt_unc, Opt_domain, | ||
102 | Opt_srcaddr, Opt_prefixpath, | ||
103 | Opt_iocharset, Opt_sockopt, | ||
104 | Opt_netbiosname, Opt_servern, | ||
105 | Opt_ver, Opt_sec, | ||
106 | |||
107 | /* Mount options to be ignored */ | ||
108 | Opt_ignore, | ||
109 | |||
110 | /* Options which could be blank */ | ||
111 | Opt_blank_pass, | ||
112 | |||
113 | Opt_err | ||
114 | }; | ||
115 | |||
116 | static const match_table_t cifs_mount_option_tokens = { | ||
117 | |||
118 | { Opt_user_xattr, "user_xattr" }, | ||
119 | { Opt_nouser_xattr, "nouser_xattr" }, | ||
120 | { Opt_forceuid, "forceuid" }, | ||
121 | { Opt_noforceuid, "noforceuid" }, | ||
122 | { Opt_noblocksend, "noblocksend" }, | ||
123 | { Opt_noautotune, "noautotune" }, | ||
124 | { Opt_hard, "hard" }, | ||
125 | { Opt_soft, "soft" }, | ||
126 | { Opt_perm, "perm" }, | ||
127 | { Opt_noperm, "noperm" }, | ||
128 | { Opt_mapchars, "mapchars" }, | ||
129 | { Opt_nomapchars, "nomapchars" }, | ||
130 | { Opt_sfu, "sfu" }, | ||
131 | { Opt_nosfu, "nosfu" }, | ||
132 | { Opt_nodfs, "nodfs" }, | ||
133 | { Opt_posixpaths, "posixpaths" }, | ||
134 | { Opt_noposixpaths, "noposixpaths" }, | ||
135 | { Opt_nounix, "nounix" }, | ||
136 | { Opt_nounix, "nolinux" }, | ||
137 | { Opt_nocase, "nocase" }, | ||
138 | { Opt_nocase, "ignorecase" }, | ||
139 | { Opt_brl, "brl" }, | ||
140 | { Opt_nobrl, "nobrl" }, | ||
141 | { Opt_nobrl, "nolock" }, | ||
142 | { Opt_forcemandatorylock, "forcemandatorylock" }, | ||
143 | { Opt_forcemandatorylock, "forcemand" }, | ||
144 | { Opt_setuids, "setuids" }, | ||
145 | { Opt_nosetuids, "nosetuids" }, | ||
146 | { Opt_dynperm, "dynperm" }, | ||
147 | { Opt_nodynperm, "nodynperm" }, | ||
148 | { Opt_nohard, "nohard" }, | ||
149 | { Opt_nosoft, "nosoft" }, | ||
150 | { Opt_nointr, "nointr" }, | ||
151 | { Opt_intr, "intr" }, | ||
152 | { Opt_nostrictsync, "nostrictsync" }, | ||
153 | { Opt_strictsync, "strictsync" }, | ||
154 | { Opt_serverino, "serverino" }, | ||
155 | { Opt_noserverino, "noserverino" }, | ||
156 | { Opt_rwpidforward, "rwpidforward" }, | ||
157 | { Opt_cifsacl, "cifsacl" }, | ||
158 | { Opt_nocifsacl, "nocifsacl" }, | ||
159 | { Opt_acl, "acl" }, | ||
160 | { Opt_noacl, "noacl" }, | ||
161 | { Opt_locallease, "locallease" }, | ||
162 | { Opt_sign, "sign" }, | ||
163 | { Opt_seal, "seal" }, | ||
164 | { Opt_direct, "direct" }, | ||
165 | { Opt_direct, "forceddirectio" }, | ||
166 | { Opt_strictcache, "strictcache" }, | ||
167 | { Opt_noac, "noac" }, | ||
168 | { Opt_fsc, "fsc" }, | ||
169 | { Opt_mfsymlinks, "mfsymlinks" }, | ||
170 | { Opt_multiuser, "multiuser" }, | ||
171 | { Opt_sloppy, "sloppy" }, | ||
172 | |||
173 | { Opt_backupuid, "backupuid=%s" }, | ||
174 | { Opt_backupgid, "backupgid=%s" }, | ||
175 | { Opt_uid, "uid=%s" }, | ||
176 | { Opt_cruid, "cruid=%s" }, | ||
177 | { Opt_gid, "gid=%s" }, | ||
178 | { Opt_file_mode, "file_mode=%s" }, | ||
179 | { Opt_dirmode, "dirmode=%s" }, | ||
180 | { Opt_dirmode, "dir_mode=%s" }, | ||
181 | { Opt_port, "port=%s" }, | ||
182 | { Opt_rsize, "rsize=%s" }, | ||
183 | { Opt_wsize, "wsize=%s" }, | ||
184 | { Opt_actimeo, "actimeo=%s" }, | ||
185 | |||
186 | { Opt_user, "user=%s" }, | ||
187 | { Opt_user, "username=%s" }, | ||
188 | { Opt_blank_pass, "pass=" }, | ||
189 | { Opt_pass, "pass=%s" }, | ||
190 | { Opt_pass, "password=%s" }, | ||
191 | { Opt_ip, "ip=%s" }, | ||
192 | { Opt_ip, "addr=%s" }, | ||
193 | { Opt_unc, "unc=%s" }, | ||
194 | { Opt_unc, "target=%s" }, | ||
195 | { Opt_unc, "path=%s" }, | ||
196 | { Opt_domain, "dom=%s" }, | ||
197 | { Opt_domain, "domain=%s" }, | ||
198 | { Opt_domain, "workgroup=%s" }, | ||
199 | { Opt_srcaddr, "srcaddr=%s" }, | ||
200 | { Opt_prefixpath, "prefixpath=%s" }, | ||
201 | { Opt_iocharset, "iocharset=%s" }, | ||
202 | { Opt_sockopt, "sockopt=%s" }, | ||
203 | { Opt_netbiosname, "netbiosname=%s" }, | ||
204 | { Opt_servern, "servern=%s" }, | ||
205 | { Opt_ver, "ver=%s" }, | ||
206 | { Opt_ver, "vers=%s" }, | ||
207 | { Opt_ver, "version=%s" }, | ||
208 | { Opt_sec, "sec=%s" }, | ||
209 | |||
210 | { Opt_ignore, "cred" }, | ||
211 | { Opt_ignore, "credentials" }, | ||
212 | { Opt_ignore, "guest" }, | ||
213 | { Opt_ignore, "rw" }, | ||
214 | { Opt_ignore, "ro" }, | ||
215 | { Opt_ignore, "suid" }, | ||
216 | { Opt_ignore, "nosuid" }, | ||
217 | { Opt_ignore, "exec" }, | ||
218 | { Opt_ignore, "noexec" }, | ||
219 | { Opt_ignore, "nodev" }, | ||
220 | { Opt_ignore, "noauto" }, | ||
221 | { Opt_ignore, "dev" }, | ||
222 | { Opt_ignore, "mand" }, | ||
223 | { Opt_ignore, "nomand" }, | ||
224 | { Opt_ignore, "_netdev" }, | ||
225 | |||
226 | { Opt_err, NULL } | ||
227 | }; | ||
228 | |||
229 | enum { | ||
230 | Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, | ||
231 | Opt_sec_ntlmsspi, Opt_sec_ntlmssp, | ||
232 | Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, | ||
233 | Opt_sec_nontlm, Opt_sec_lanman, | ||
234 | Opt_sec_none, | ||
235 | |||
236 | Opt_sec_err | ||
237 | }; | ||
238 | |||
239 | static const match_table_t cifs_secflavor_tokens = { | ||
240 | { Opt_sec_krb5, "krb5" }, | ||
241 | { Opt_sec_krb5i, "krb5i" }, | ||
242 | { Opt_sec_krb5p, "krb5p" }, | ||
243 | { Opt_sec_ntlmsspi, "ntlmsspi" }, | ||
244 | { Opt_sec_ntlmssp, "ntlmssp" }, | ||
245 | { Opt_ntlm, "ntlm" }, | ||
246 | { Opt_sec_ntlmi, "ntlmi" }, | ||
247 | { Opt_sec_ntlmv2i, "ntlmv2i" }, | ||
248 | { Opt_sec_nontlm, "nontlm" }, | ||
249 | { Opt_sec_lanman, "lanman" }, | ||
250 | { Opt_sec_none, "none" }, | ||
251 | |||
252 | { Opt_sec_err, NULL } | ||
253 | }; | ||
254 | |||
66 | static int ip_connect(struct TCP_Server_Info *server); | 255 | static int ip_connect(struct TCP_Server_Info *server); |
67 | static int generic_ip_connect(struct TCP_Server_Info *server); | 256 | static int generic_ip_connect(struct TCP_Server_Info *server); |
68 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); | 257 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); |
@@ -143,8 +332,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
143 | spin_lock(&GlobalMid_Lock); | 332 | spin_lock(&GlobalMid_Lock); |
144 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { | 333 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
145 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 334 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
146 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) | 335 | if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) |
147 | mid_entry->midState = MID_RETRY_NEEDED; | 336 | mid_entry->mid_state = MID_RETRY_NEEDED; |
148 | list_move(&mid_entry->qhead, &retry_list); | 337 | list_move(&mid_entry->qhead, &retry_list); |
149 | } | 338 | } |
150 | spin_unlock(&GlobalMid_Lock); | 339 | spin_unlock(&GlobalMid_Lock); |
@@ -183,8 +372,9 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
183 | -EINVAL = invalid transact2 | 372 | -EINVAL = invalid transact2 |
184 | 373 | ||
185 | */ | 374 | */ |
186 | static int check2ndT2(struct smb_hdr *pSMB) | 375 | static int check2ndT2(char *buf) |
187 | { | 376 | { |
377 | struct smb_hdr *pSMB = (struct smb_hdr *)buf; | ||
188 | struct smb_t2_rsp *pSMBt; | 378 | struct smb_t2_rsp *pSMBt; |
189 | int remaining; | 379 | int remaining; |
190 | __u16 total_data_size, data_in_this_rsp; | 380 | __u16 total_data_size, data_in_this_rsp; |
@@ -224,10 +414,10 @@ static int check2ndT2(struct smb_hdr *pSMB) | |||
224 | return remaining; | 414 | return remaining; |
225 | } | 415 | } |
226 | 416 | ||
227 | static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | 417 | static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) |
228 | { | 418 | { |
229 | struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond; | 419 | struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf; |
230 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | 420 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr; |
231 | char *data_area_of_tgt; | 421 | char *data_area_of_tgt; |
232 | char *data_area_of_src; | 422 | char *data_area_of_src; |
233 | int remaining; | 423 | int remaining; |
@@ -280,23 +470,23 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
280 | put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); | 470 | put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); |
281 | 471 | ||
282 | /* fix up the BCC */ | 472 | /* fix up the BCC */ |
283 | byte_count = get_bcc(pTargetSMB); | 473 | byte_count = get_bcc(target_hdr); |
284 | byte_count += total_in_src; | 474 | byte_count += total_in_src; |
285 | /* is the result too big for the field? */ | 475 | /* is the result too big for the field? */ |
286 | if (byte_count > USHRT_MAX) { | 476 | if (byte_count > USHRT_MAX) { |
287 | cFYI(1, "coalesced BCC too large (%u)", byte_count); | 477 | cFYI(1, "coalesced BCC too large (%u)", byte_count); |
288 | return -EPROTO; | 478 | return -EPROTO; |
289 | } | 479 | } |
290 | put_bcc(byte_count, pTargetSMB); | 480 | put_bcc(byte_count, target_hdr); |
291 | 481 | ||
292 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 482 | byte_count = be32_to_cpu(target_hdr->smb_buf_length); |
293 | byte_count += total_in_src; | 483 | byte_count += total_in_src; |
294 | /* don't allow buffer to overflow */ | 484 | /* don't allow buffer to overflow */ |
295 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 485 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
296 | cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); | 486 | cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); |
297 | return -ENOBUFS; | 487 | return -ENOBUFS; |
298 | } | 488 | } |
299 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 489 | target_hdr->smb_buf_length = cpu_to_be32(byte_count); |
300 | 490 | ||
301 | /* copy second buffer into end of first buffer */ | 491 | /* copy second buffer into end of first buffer */ |
302 | memcpy(data_area_of_tgt, data_area_of_src, total_in_src); | 492 | memcpy(data_area_of_tgt, data_area_of_src, total_in_src); |
@@ -334,7 +524,7 @@ cifs_echo_request(struct work_struct *work) | |||
334 | server->hostname); | 524 | server->hostname); |
335 | 525 | ||
336 | requeue_echo: | 526 | requeue_echo: |
337 | queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); | 527 | queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL); |
338 | } | 528 | } |
339 | 529 | ||
340 | static bool | 530 | static bool |
@@ -350,7 +540,7 @@ allocate_buffers(struct TCP_Server_Info *server) | |||
350 | } | 540 | } |
351 | } else if (server->large_buf) { | 541 | } else if (server->large_buf) { |
352 | /* we are reusing a dirty large buf, clear its start */ | 542 | /* we are reusing a dirty large buf, clear its start */ |
353 | memset(server->bigbuf, 0, sizeof(struct smb_hdr)); | 543 | memset(server->bigbuf, 0, header_size()); |
354 | } | 544 | } |
355 | 545 | ||
356 | if (!server->smallbuf) { | 546 | if (!server->smallbuf) { |
@@ -364,7 +554,7 @@ allocate_buffers(struct TCP_Server_Info *server) | |||
364 | /* beginning of smb buffer is cleared in our buf_get */ | 554 | /* beginning of smb buffer is cleared in our buf_get */ |
365 | } else { | 555 | } else { |
366 | /* if existing small buf clear beginning */ | 556 | /* if existing small buf clear beginning */ |
367 | memset(server->smallbuf, 0, sizeof(struct smb_hdr)); | 557 | memset(server->smallbuf, 0, header_size()); |
368 | } | 558 | } |
369 | 559 | ||
370 | return true; | 560 | return true; |
@@ -566,15 +756,16 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) | |||
566 | } | 756 | } |
567 | 757 | ||
568 | static struct mid_q_entry * | 758 | static struct mid_q_entry * |
569 | find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf) | 759 | find_mid(struct TCP_Server_Info *server, char *buffer) |
570 | { | 760 | { |
761 | struct smb_hdr *buf = (struct smb_hdr *)buffer; | ||
571 | struct mid_q_entry *mid; | 762 | struct mid_q_entry *mid; |
572 | 763 | ||
573 | spin_lock(&GlobalMid_Lock); | 764 | spin_lock(&GlobalMid_Lock); |
574 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { | 765 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
575 | if (mid->mid == buf->Mid && | 766 | if (mid->mid == buf->Mid && |
576 | mid->midState == MID_REQUEST_SUBMITTED && | 767 | mid->mid_state == MID_REQUEST_SUBMITTED && |
577 | mid->command == buf->Command) { | 768 | le16_to_cpu(mid->command) == buf->Command) { |
578 | spin_unlock(&GlobalMid_Lock); | 769 | spin_unlock(&GlobalMid_Lock); |
579 | return mid; | 770 | return mid; |
580 | } | 771 | } |
@@ -591,16 +782,16 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) | |||
591 | #endif | 782 | #endif |
592 | spin_lock(&GlobalMid_Lock); | 783 | spin_lock(&GlobalMid_Lock); |
593 | if (!malformed) | 784 | if (!malformed) |
594 | mid->midState = MID_RESPONSE_RECEIVED; | 785 | mid->mid_state = MID_RESPONSE_RECEIVED; |
595 | else | 786 | else |
596 | mid->midState = MID_RESPONSE_MALFORMED; | 787 | mid->mid_state = MID_RESPONSE_MALFORMED; |
597 | list_del_init(&mid->qhead); | 788 | list_del_init(&mid->qhead); |
598 | spin_unlock(&GlobalMid_Lock); | 789 | spin_unlock(&GlobalMid_Lock); |
599 | } | 790 | } |
600 | 791 | ||
601 | static void | 792 | static void |
602 | handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, | 793 | handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, |
603 | struct smb_hdr *buf, int malformed) | 794 | char *buf, int malformed) |
604 | { | 795 | { |
605 | if (malformed == 0 && check2ndT2(buf) > 0) { | 796 | if (malformed == 0 && check2ndT2(buf) > 0) { |
606 | mid->multiRsp = true; | 797 | mid->multiRsp = true; |
@@ -620,13 +811,13 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
620 | } else { | 811 | } else { |
621 | /* Have first buffer */ | 812 | /* Have first buffer */ |
622 | mid->resp_buf = buf; | 813 | mid->resp_buf = buf; |
623 | mid->largeBuf = true; | 814 | mid->large_buf = true; |
624 | server->bigbuf = NULL; | 815 | server->bigbuf = NULL; |
625 | } | 816 | } |
626 | return; | 817 | return; |
627 | } | 818 | } |
628 | mid->resp_buf = buf; | 819 | mid->resp_buf = buf; |
629 | mid->largeBuf = server->large_buf; | 820 | mid->large_buf = server->large_buf; |
630 | /* Was previous buf put in mpx struct for multi-rsp? */ | 821 | /* Was previous buf put in mpx struct for multi-rsp? */ |
631 | if (!mid->multiRsp) { | 822 | if (!mid->multiRsp) { |
632 | /* smb buffer will be freed by user thread */ | 823 | /* smb buffer will be freed by user thread */ |
@@ -682,8 +873,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) | |||
682 | spin_lock(&GlobalMid_Lock); | 873 | spin_lock(&GlobalMid_Lock); |
683 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { | 874 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
684 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 875 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
685 | cFYI(1, "Clearing mid 0x%x", mid_entry->mid); | 876 | cFYI(1, "Clearing mid 0x%llx", mid_entry->mid); |
686 | mid_entry->midState = MID_SHUTDOWN; | 877 | mid_entry->mid_state = MID_SHUTDOWN; |
687 | list_move(&mid_entry->qhead, &dispose_list); | 878 | list_move(&mid_entry->qhead, &dispose_list); |
688 | } | 879 | } |
689 | spin_unlock(&GlobalMid_Lock); | 880 | spin_unlock(&GlobalMid_Lock); |
@@ -691,7 +882,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) | |||
691 | /* now walk dispose list and issue callbacks */ | 882 | /* now walk dispose list and issue callbacks */ |
692 | list_for_each_safe(tmp, tmp2, &dispose_list) { | 883 | list_for_each_safe(tmp, tmp2, &dispose_list) { |
693 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 884 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
694 | cFYI(1, "Callback mid 0x%x", mid_entry->mid); | 885 | cFYI(1, "Callback mid 0x%llx", mid_entry->mid); |
695 | list_del_init(&mid_entry->qhead); | 886 | list_del_init(&mid_entry->qhead); |
696 | mid_entry->callback(mid_entry); | 887 | mid_entry->callback(mid_entry); |
697 | } | 888 | } |
@@ -731,11 +922,10 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
731 | { | 922 | { |
732 | int length; | 923 | int length; |
733 | char *buf = server->smallbuf; | 924 | char *buf = server->smallbuf; |
734 | struct smb_hdr *smb_buffer = (struct smb_hdr *)buf; | 925 | unsigned int pdu_length = get_rfc1002_length(buf); |
735 | unsigned int pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); | ||
736 | 926 | ||
737 | /* make sure this will fit in a large buffer */ | 927 | /* make sure this will fit in a large buffer */ |
738 | if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 928 | if (pdu_length > CIFSMaxBufSize + max_header_size() - 4) { |
739 | cERROR(1, "SMB response too long (%u bytes)", | 929 | cERROR(1, "SMB response too long (%u bytes)", |
740 | pdu_length); | 930 | pdu_length); |
741 | cifs_reconnect(server); | 931 | cifs_reconnect(server); |
@@ -746,20 +936,18 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
746 | /* switch to large buffer if too big for a small one */ | 936 | /* switch to large buffer if too big for a small one */ |
747 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { | 937 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |
748 | server->large_buf = true; | 938 | server->large_buf = true; |
749 | memcpy(server->bigbuf, server->smallbuf, server->total_read); | 939 | memcpy(server->bigbuf, buf, server->total_read); |
750 | buf = server->bigbuf; | 940 | buf = server->bigbuf; |
751 | smb_buffer = (struct smb_hdr *)buf; | ||
752 | } | 941 | } |
753 | 942 | ||
754 | /* now read the rest */ | 943 | /* now read the rest */ |
755 | length = cifs_read_from_socket(server, | 944 | length = cifs_read_from_socket(server, buf + header_size() - 1, |
756 | buf + sizeof(struct smb_hdr) - 1, | 945 | pdu_length - header_size() + 1 + 4); |
757 | pdu_length - sizeof(struct smb_hdr) + 1 + 4); | ||
758 | if (length < 0) | 946 | if (length < 0) |
759 | return length; | 947 | return length; |
760 | server->total_read += length; | 948 | server->total_read += length; |
761 | 949 | ||
762 | dump_smb(smb_buffer, server->total_read); | 950 | dump_smb(buf, server->total_read); |
763 | 951 | ||
764 | /* | 952 | /* |
765 | * We know that we received enough to get to the MID as we | 953 | * We know that we received enough to get to the MID as we |
@@ -770,7 +958,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
770 | * 48 bytes is enough to display the header and a little bit | 958 | * 48 bytes is enough to display the header and a little bit |
771 | * into the payload for debugging purposes. | 959 | * into the payload for debugging purposes. |
772 | */ | 960 | */ |
773 | length = checkSMB(smb_buffer, smb_buffer->Mid, server->total_read); | 961 | length = checkSMB(buf, server->total_read); |
774 | if (length != 0) | 962 | if (length != 0) |
775 | cifs_dump_mem("Bad SMB: ", buf, | 963 | cifs_dump_mem("Bad SMB: ", buf, |
776 | min_t(unsigned int, server->total_read, 48)); | 964 | min_t(unsigned int, server->total_read, 48)); |
@@ -778,7 +966,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
778 | if (!mid) | 966 | if (!mid) |
779 | return length; | 967 | return length; |
780 | 968 | ||
781 | handle_mid(mid, server, smb_buffer, length); | 969 | handle_mid(mid, server, buf, length); |
782 | return 0; | 970 | return 0; |
783 | } | 971 | } |
784 | 972 | ||
@@ -789,7 +977,6 @@ cifs_demultiplex_thread(void *p) | |||
789 | struct TCP_Server_Info *server = p; | 977 | struct TCP_Server_Info *server = p; |
790 | unsigned int pdu_length; | 978 | unsigned int pdu_length; |
791 | char *buf = NULL; | 979 | char *buf = NULL; |
792 | struct smb_hdr *smb_buffer = NULL; | ||
793 | struct task_struct *task_to_wake = NULL; | 980 | struct task_struct *task_to_wake = NULL; |
794 | struct mid_q_entry *mid_entry; | 981 | struct mid_q_entry *mid_entry; |
795 | 982 | ||
@@ -810,7 +997,6 @@ cifs_demultiplex_thread(void *p) | |||
810 | continue; | 997 | continue; |
811 | 998 | ||
812 | server->large_buf = false; | 999 | server->large_buf = false; |
813 | smb_buffer = (struct smb_hdr *)server->smallbuf; | ||
814 | buf = server->smallbuf; | 1000 | buf = server->smallbuf; |
815 | pdu_length = 4; /* enough to get RFC1001 header */ | 1001 | pdu_length = 4; /* enough to get RFC1001 header */ |
816 | 1002 | ||
@@ -823,14 +1009,14 @@ cifs_demultiplex_thread(void *p) | |||
823 | * The right amount was read from socket - 4 bytes, | 1009 | * The right amount was read from socket - 4 bytes, |
824 | * so we can now interpret the length field. | 1010 | * so we can now interpret the length field. |
825 | */ | 1011 | */ |
826 | pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); | 1012 | pdu_length = get_rfc1002_length(buf); |
827 | 1013 | ||
828 | cFYI(1, "RFC1002 header 0x%x", pdu_length); | 1014 | cFYI(1, "RFC1002 header 0x%x", pdu_length); |
829 | if (!is_smb_response(server, buf[0])) | 1015 | if (!is_smb_response(server, buf[0])) |
830 | continue; | 1016 | continue; |
831 | 1017 | ||
832 | /* make sure we have enough to get to the MID */ | 1018 | /* make sure we have enough to get to the MID */ |
833 | if (pdu_length < sizeof(struct smb_hdr) - 1 - 4) { | 1019 | if (pdu_length < header_size() - 1 - 4) { |
834 | cERROR(1, "SMB response too short (%u bytes)", | 1020 | cERROR(1, "SMB response too short (%u bytes)", |
835 | pdu_length); | 1021 | pdu_length); |
836 | cifs_reconnect(server); | 1022 | cifs_reconnect(server); |
@@ -840,12 +1026,12 @@ cifs_demultiplex_thread(void *p) | |||
840 | 1026 | ||
841 | /* read down to the MID */ | 1027 | /* read down to the MID */ |
842 | length = cifs_read_from_socket(server, buf + 4, | 1028 | length = cifs_read_from_socket(server, buf + 4, |
843 | sizeof(struct smb_hdr) - 1 - 4); | 1029 | header_size() - 1 - 4); |
844 | if (length < 0) | 1030 | if (length < 0) |
845 | continue; | 1031 | continue; |
846 | server->total_read += length; | 1032 | server->total_read += length; |
847 | 1033 | ||
848 | mid_entry = find_mid(server, smb_buffer); | 1034 | mid_entry = find_mid(server, buf); |
849 | 1035 | ||
850 | if (!mid_entry || !mid_entry->receive) | 1036 | if (!mid_entry || !mid_entry->receive) |
851 | length = standard_receive3(server, mid_entry); | 1037 | length = standard_receive3(server, mid_entry); |
@@ -855,22 +1041,19 @@ cifs_demultiplex_thread(void *p) | |||
855 | if (length < 0) | 1041 | if (length < 0) |
856 | continue; | 1042 | continue; |
857 | 1043 | ||
858 | if (server->large_buf) { | 1044 | if (server->large_buf) |
859 | buf = server->bigbuf; | 1045 | buf = server->bigbuf; |
860 | smb_buffer = (struct smb_hdr *)buf; | ||
861 | } | ||
862 | 1046 | ||
863 | server->lstrp = jiffies; | 1047 | server->lstrp = jiffies; |
864 | if (mid_entry != NULL) { | 1048 | if (mid_entry != NULL) { |
865 | if (!mid_entry->multiRsp || mid_entry->multiEnd) | 1049 | if (!mid_entry->multiRsp || mid_entry->multiEnd) |
866 | mid_entry->callback(mid_entry); | 1050 | mid_entry->callback(mid_entry); |
867 | } else if (!is_valid_oplock_break(smb_buffer, server)) { | 1051 | } else if (!is_valid_oplock_break(buf, server)) { |
868 | cERROR(1, "No task to wake, unknown frame received! " | 1052 | cERROR(1, "No task to wake, unknown frame received! " |
869 | "NumMids %d", atomic_read(&midCount)); | 1053 | "NumMids %d", atomic_read(&midCount)); |
870 | cifs_dump_mem("Received Data is: ", buf, | 1054 | cifs_dump_mem("Received Data is: ", buf, header_size()); |
871 | sizeof(struct smb_hdr)); | ||
872 | #ifdef CONFIG_CIFS_DEBUG2 | 1055 | #ifdef CONFIG_CIFS_DEBUG2 |
873 | cifs_dump_detail(smb_buffer); | 1056 | cifs_dump_detail(buf); |
874 | cifs_dump_mids(server); | 1057 | cifs_dump_mids(server); |
875 | #endif /* CIFS_DEBUG2 */ | 1058 | #endif /* CIFS_DEBUG2 */ |
876 | 1059 | ||
@@ -926,23 +1109,95 @@ extract_hostname(const char *unc) | |||
926 | return dst; | 1109 | return dst; |
927 | } | 1110 | } |
928 | 1111 | ||
1112 | static int get_option_ul(substring_t args[], unsigned long *option) | ||
1113 | { | ||
1114 | int rc; | ||
1115 | char *string; | ||
1116 | |||
1117 | string = match_strdup(args); | ||
1118 | if (string == NULL) | ||
1119 | return -ENOMEM; | ||
1120 | rc = kstrtoul(string, 10, option); | ||
1121 | kfree(string); | ||
1122 | |||
1123 | return rc; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | static int cifs_parse_security_flavors(char *value, | ||
1128 | struct smb_vol *vol) | ||
1129 | { | ||
1130 | |||
1131 | substring_t args[MAX_OPT_ARGS]; | ||
1132 | |||
1133 | switch (match_token(value, cifs_secflavor_tokens, args)) { | ||
1134 | case Opt_sec_krb5: | ||
1135 | vol->secFlg |= CIFSSEC_MAY_KRB5; | ||
1136 | break; | ||
1137 | case Opt_sec_krb5i: | ||
1138 | vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; | ||
1139 | break; | ||
1140 | case Opt_sec_krb5p: | ||
1141 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ | ||
1142 | cERROR(1, "Krb5 cifs privacy not supported"); | ||
1143 | break; | ||
1144 | case Opt_sec_ntlmssp: | ||
1145 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | ||
1146 | break; | ||
1147 | case Opt_sec_ntlmsspi: | ||
1148 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; | ||
1149 | break; | ||
1150 | case Opt_ntlm: | ||
1151 | /* ntlm is default so can be turned off too */ | ||
1152 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1153 | break; | ||
1154 | case Opt_sec_ntlmi: | ||
1155 | vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; | ||
1156 | break; | ||
1157 | case Opt_sec_nontlm: | ||
1158 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | ||
1159 | break; | ||
1160 | case Opt_sec_ntlmv2i: | ||
1161 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; | ||
1162 | break; | ||
1163 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
1164 | case Opt_sec_lanman: | ||
1165 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | ||
1166 | break; | ||
1167 | #endif | ||
1168 | case Opt_sec_none: | ||
1169 | vol->nullauth = 1; | ||
1170 | break; | ||
1171 | default: | ||
1172 | cERROR(1, "bad security option: %s", value); | ||
1173 | return 1; | ||
1174 | } | ||
1175 | |||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
929 | static int | 1179 | static int |
930 | cifs_parse_mount_options(const char *mountdata, const char *devname, | 1180 | cifs_parse_mount_options(const char *mountdata, const char *devname, |
931 | struct smb_vol *vol) | 1181 | struct smb_vol *vol) |
932 | { | 1182 | { |
933 | char *value, *data, *end; | 1183 | char *data, *end; |
934 | char *mountdata_copy = NULL, *options; | 1184 | char *mountdata_copy = NULL, *options; |
935 | int err; | ||
936 | unsigned int temp_len, i, j; | 1185 | unsigned int temp_len, i, j; |
937 | char separator[2]; | 1186 | char separator[2]; |
938 | short int override_uid = -1; | 1187 | short int override_uid = -1; |
939 | short int override_gid = -1; | 1188 | short int override_gid = -1; |
940 | bool uid_specified = false; | 1189 | bool uid_specified = false; |
941 | bool gid_specified = false; | 1190 | bool gid_specified = false; |
1191 | bool sloppy = false; | ||
1192 | char *invalid = NULL; | ||
942 | char *nodename = utsname()->nodename; | 1193 | char *nodename = utsname()->nodename; |
1194 | char *string = NULL; | ||
1195 | char *tmp_end, *value; | ||
1196 | char delim; | ||
943 | 1197 | ||
944 | separator[0] = ','; | 1198 | separator[0] = ','; |
945 | separator[1] = 0; | 1199 | separator[1] = 0; |
1200 | delim = separator[0]; | ||
946 | 1201 | ||
947 | /* | 1202 | /* |
948 | * does not have to be perfect mapping since field is | 1203 | * does not have to be perfect mapping since field is |
@@ -981,6 +1236,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
981 | 1236 | ||
982 | options = mountdata_copy; | 1237 | options = mountdata_copy; |
983 | end = options + strlen(options); | 1238 | end = options + strlen(options); |
1239 | |||
984 | if (strncmp(options, "sep=", 4) == 0) { | 1240 | if (strncmp(options, "sep=", 4) == 0) { |
985 | if (options[4] != 0) { | 1241 | if (options[4] != 0) { |
986 | separator[0] = options[4]; | 1242 | separator[0] = options[4]; |
@@ -993,609 +1249,652 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
993 | vol->backupgid_specified = false; /* no backup intent for a group */ | 1249 | vol->backupgid_specified = false; /* no backup intent for a group */ |
994 | 1250 | ||
995 | while ((data = strsep(&options, separator)) != NULL) { | 1251 | while ((data = strsep(&options, separator)) != NULL) { |
1252 | substring_t args[MAX_OPT_ARGS]; | ||
1253 | unsigned long option; | ||
1254 | int token; | ||
1255 | |||
996 | if (!*data) | 1256 | if (!*data) |
997 | continue; | 1257 | continue; |
998 | if ((value = strchr(data, '=')) != NULL) | ||
999 | *value++ = '\0'; | ||
1000 | 1258 | ||
1001 | /* Have to parse this before we parse for "user" */ | 1259 | token = match_token(data, cifs_mount_option_tokens, args); |
1002 | if (strnicmp(data, "user_xattr", 10) == 0) { | 1260 | |
1261 | switch (token) { | ||
1262 | |||
1263 | /* Ingnore the following */ | ||
1264 | case Opt_ignore: | ||
1265 | break; | ||
1266 | |||
1267 | /* Boolean values */ | ||
1268 | case Opt_user_xattr: | ||
1003 | vol->no_xattr = 0; | 1269 | vol->no_xattr = 0; |
1004 | } else if (strnicmp(data, "nouser_xattr", 12) == 0) { | 1270 | break; |
1271 | case Opt_nouser_xattr: | ||
1005 | vol->no_xattr = 1; | 1272 | vol->no_xattr = 1; |
1006 | } else if (strnicmp(data, "user", 4) == 0) { | 1273 | break; |
1007 | if (!value) { | 1274 | case Opt_forceuid: |
1008 | printk(KERN_WARNING | ||
1009 | "CIFS: invalid or missing username\n"); | ||
1010 | goto cifs_parse_mount_err; | ||
1011 | } else if (!*value) { | ||
1012 | /* null user, ie anonymous, authentication */ | ||
1013 | vol->nullauth = 1; | ||
1014 | } | ||
1015 | if (strnlen(value, MAX_USERNAME_SIZE) < | ||
1016 | MAX_USERNAME_SIZE) { | ||
1017 | vol->username = kstrdup(value, GFP_KERNEL); | ||
1018 | if (!vol->username) { | ||
1019 | printk(KERN_WARNING "CIFS: no memory " | ||
1020 | "for username\n"); | ||
1021 | goto cifs_parse_mount_err; | ||
1022 | } | ||
1023 | } else { | ||
1024 | printk(KERN_WARNING "CIFS: username too long\n"); | ||
1025 | goto cifs_parse_mount_err; | ||
1026 | } | ||
1027 | } else if (strnicmp(data, "pass", 4) == 0) { | ||
1028 | if (!value) { | ||
1029 | vol->password = NULL; | ||
1030 | continue; | ||
1031 | } else if (value[0] == 0) { | ||
1032 | /* check if string begins with double comma | ||
1033 | since that would mean the password really | ||
1034 | does start with a comma, and would not | ||
1035 | indicate an empty string */ | ||
1036 | if (value[1] != separator[0]) { | ||
1037 | vol->password = NULL; | ||
1038 | continue; | ||
1039 | } | ||
1040 | } | ||
1041 | temp_len = strlen(value); | ||
1042 | /* removed password length check, NTLM passwords | ||
1043 | can be arbitrarily long */ | ||
1044 | |||
1045 | /* if comma in password, the string will be | ||
1046 | prematurely null terminated. Commas in password are | ||
1047 | specified across the cifs mount interface by a double | ||
1048 | comma ie ,, and a comma used as in other cases ie ',' | ||
1049 | as a parameter delimiter/separator is single and due | ||
1050 | to the strsep above is temporarily zeroed. */ | ||
1051 | |||
1052 | /* NB: password legally can have multiple commas and | ||
1053 | the only illegal character in a password is null */ | ||
1054 | |||
1055 | if ((value[temp_len] == 0) && | ||
1056 | (value + temp_len < end) && | ||
1057 | (value[temp_len+1] == separator[0])) { | ||
1058 | /* reinsert comma */ | ||
1059 | value[temp_len] = separator[0]; | ||
1060 | temp_len += 2; /* move after second comma */ | ||
1061 | while (value[temp_len] != 0) { | ||
1062 | if (value[temp_len] == separator[0]) { | ||
1063 | if (value[temp_len+1] == | ||
1064 | separator[0]) { | ||
1065 | /* skip second comma */ | ||
1066 | temp_len++; | ||
1067 | } else { | ||
1068 | /* single comma indicating start | ||
1069 | of next parm */ | ||
1070 | break; | ||
1071 | } | ||
1072 | } | ||
1073 | temp_len++; | ||
1074 | } | ||
1075 | if (value[temp_len] == 0) { | ||
1076 | options = NULL; | ||
1077 | } else { | ||
1078 | value[temp_len] = 0; | ||
1079 | /* point option to start of next parm */ | ||
1080 | options = value + temp_len + 1; | ||
1081 | } | ||
1082 | /* go from value to value + temp_len condensing | ||
1083 | double commas to singles. Note that this ends up | ||
1084 | allocating a few bytes too many, which is ok */ | ||
1085 | vol->password = kzalloc(temp_len, GFP_KERNEL); | ||
1086 | if (vol->password == NULL) { | ||
1087 | printk(KERN_WARNING "CIFS: no memory " | ||
1088 | "for password\n"); | ||
1089 | goto cifs_parse_mount_err; | ||
1090 | } | ||
1091 | for (i = 0, j = 0; i < temp_len; i++, j++) { | ||
1092 | vol->password[j] = value[i]; | ||
1093 | if (value[i] == separator[0] | ||
1094 | && value[i+1] == separator[0]) { | ||
1095 | /* skip second comma */ | ||
1096 | i++; | ||
1097 | } | ||
1098 | } | ||
1099 | vol->password[j] = 0; | ||
1100 | } else { | ||
1101 | vol->password = kzalloc(temp_len+1, GFP_KERNEL); | ||
1102 | if (vol->password == NULL) { | ||
1103 | printk(KERN_WARNING "CIFS: no memory " | ||
1104 | "for password\n"); | ||
1105 | goto cifs_parse_mount_err; | ||
1106 | } | ||
1107 | strcpy(vol->password, value); | ||
1108 | } | ||
1109 | } else if (!strnicmp(data, "ip", 2) || | ||
1110 | !strnicmp(data, "addr", 4)) { | ||
1111 | if (!value || !*value) { | ||
1112 | vol->UNCip = NULL; | ||
1113 | } else if (strnlen(value, INET6_ADDRSTRLEN) < | ||
1114 | INET6_ADDRSTRLEN) { | ||
1115 | vol->UNCip = kstrdup(value, GFP_KERNEL); | ||
1116 | if (!vol->UNCip) { | ||
1117 | printk(KERN_WARNING "CIFS: no memory " | ||
1118 | "for UNC IP\n"); | ||
1119 | goto cifs_parse_mount_err; | ||
1120 | } | ||
1121 | } else { | ||
1122 | printk(KERN_WARNING "CIFS: ip address " | ||
1123 | "too long\n"); | ||
1124 | goto cifs_parse_mount_err; | ||
1125 | } | ||
1126 | } else if (strnicmp(data, "sec", 3) == 0) { | ||
1127 | if (!value || !*value) { | ||
1128 | cERROR(1, "no security value specified"); | ||
1129 | continue; | ||
1130 | } else if (strnicmp(value, "krb5i", 5) == 0) { | ||
1131 | vol->secFlg |= CIFSSEC_MAY_KRB5 | | ||
1132 | CIFSSEC_MUST_SIGN; | ||
1133 | } else if (strnicmp(value, "krb5p", 5) == 0) { | ||
1134 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | | ||
1135 | CIFSSEC_MAY_KRB5; */ | ||
1136 | cERROR(1, "Krb5 cifs privacy not supported"); | ||
1137 | goto cifs_parse_mount_err; | ||
1138 | } else if (strnicmp(value, "krb5", 4) == 0) { | ||
1139 | vol->secFlg |= CIFSSEC_MAY_KRB5; | ||
1140 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { | ||
1141 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | | ||
1142 | CIFSSEC_MUST_SIGN; | ||
1143 | } else if (strnicmp(value, "ntlmssp", 7) == 0) { | ||
1144 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | ||
1145 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { | ||
1146 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | | ||
1147 | CIFSSEC_MUST_SIGN; | ||
1148 | } else if (strnicmp(value, "ntlmv2", 6) == 0) { | ||
1149 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | ||
1150 | } else if (strnicmp(value, "ntlmi", 5) == 0) { | ||
1151 | vol->secFlg |= CIFSSEC_MAY_NTLM | | ||
1152 | CIFSSEC_MUST_SIGN; | ||
1153 | } else if (strnicmp(value, "ntlm", 4) == 0) { | ||
1154 | /* ntlm is default so can be turned off too */ | ||
1155 | vol->secFlg |= CIFSSEC_MAY_NTLM; | ||
1156 | } else if (strnicmp(value, "nontlm", 6) == 0) { | ||
1157 | /* BB is there a better way to do this? */ | ||
1158 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | ||
1159 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
1160 | } else if (strnicmp(value, "lanman", 6) == 0) { | ||
1161 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | ||
1162 | #endif | ||
1163 | } else if (strnicmp(value, "none", 4) == 0) { | ||
1164 | vol->nullauth = 1; | ||
1165 | } else { | ||
1166 | cERROR(1, "bad security option: %s", value); | ||
1167 | goto cifs_parse_mount_err; | ||
1168 | } | ||
1169 | } else if (strnicmp(data, "vers", 3) == 0) { | ||
1170 | if (!value || !*value) { | ||
1171 | cERROR(1, "no protocol version specified" | ||
1172 | " after vers= mount option"); | ||
1173 | } else if ((strnicmp(value, "cifs", 4) == 0) || | ||
1174 | (strnicmp(value, "1", 1) == 0)) { | ||
1175 | /* this is the default */ | ||
1176 | continue; | ||
1177 | } | ||
1178 | } else if ((strnicmp(data, "unc", 3) == 0) | ||
1179 | || (strnicmp(data, "target", 6) == 0) | ||
1180 | || (strnicmp(data, "path", 4) == 0)) { | ||
1181 | if (!value || !*value) { | ||
1182 | printk(KERN_WARNING "CIFS: invalid path to " | ||
1183 | "network resource\n"); | ||
1184 | goto cifs_parse_mount_err; | ||
1185 | } | ||
1186 | if ((temp_len = strnlen(value, 300)) < 300) { | ||
1187 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | ||
1188 | if (vol->UNC == NULL) | ||
1189 | goto cifs_parse_mount_err; | ||
1190 | strcpy(vol->UNC, value); | ||
1191 | if (strncmp(vol->UNC, "//", 2) == 0) { | ||
1192 | vol->UNC[0] = '\\'; | ||
1193 | vol->UNC[1] = '\\'; | ||
1194 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { | ||
1195 | printk(KERN_WARNING | ||
1196 | "CIFS: UNC Path does not begin " | ||
1197 | "with // or \\\\ \n"); | ||
1198 | goto cifs_parse_mount_err; | ||
1199 | } | ||
1200 | } else { | ||
1201 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | ||
1202 | goto cifs_parse_mount_err; | ||
1203 | } | ||
1204 | } else if ((strnicmp(data, "domain", 3) == 0) | ||
1205 | || (strnicmp(data, "workgroup", 5) == 0)) { | ||
1206 | if (!value || !*value) { | ||
1207 | printk(KERN_WARNING "CIFS: invalid domain name\n"); | ||
1208 | goto cifs_parse_mount_err; | ||
1209 | } | ||
1210 | /* BB are there cases in which a comma can be valid in | ||
1211 | a domain name and need special handling? */ | ||
1212 | if (strnlen(value, 256) < 256) { | ||
1213 | vol->domainname = kstrdup(value, GFP_KERNEL); | ||
1214 | if (!vol->domainname) { | ||
1215 | printk(KERN_WARNING "CIFS: no memory " | ||
1216 | "for domainname\n"); | ||
1217 | goto cifs_parse_mount_err; | ||
1218 | } | ||
1219 | cFYI(1, "Domain name set"); | ||
1220 | } else { | ||
1221 | printk(KERN_WARNING "CIFS: domain name too " | ||
1222 | "long\n"); | ||
1223 | goto cifs_parse_mount_err; | ||
1224 | } | ||
1225 | } else if (strnicmp(data, "srcaddr", 7) == 0) { | ||
1226 | vol->srcaddr.ss_family = AF_UNSPEC; | ||
1227 | |||
1228 | if (!value || !*value) { | ||
1229 | printk(KERN_WARNING "CIFS: srcaddr value" | ||
1230 | " not specified.\n"); | ||
1231 | goto cifs_parse_mount_err; | ||
1232 | } | ||
1233 | i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, | ||
1234 | value, strlen(value)); | ||
1235 | if (i == 0) { | ||
1236 | printk(KERN_WARNING "CIFS: Could not parse" | ||
1237 | " srcaddr: %s\n", | ||
1238 | value); | ||
1239 | goto cifs_parse_mount_err; | ||
1240 | } | ||
1241 | } else if (strnicmp(data, "prefixpath", 10) == 0) { | ||
1242 | if (!value || !*value) { | ||
1243 | printk(KERN_WARNING | ||
1244 | "CIFS: invalid path prefix\n"); | ||
1245 | goto cifs_parse_mount_err; | ||
1246 | } | ||
1247 | if ((temp_len = strnlen(value, 1024)) < 1024) { | ||
1248 | if (value[0] != '/') | ||
1249 | temp_len++; /* missing leading slash */ | ||
1250 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); | ||
1251 | if (vol->prepath == NULL) | ||
1252 | goto cifs_parse_mount_err; | ||
1253 | if (value[0] != '/') { | ||
1254 | vol->prepath[0] = '/'; | ||
1255 | strcpy(vol->prepath+1, value); | ||
1256 | } else | ||
1257 | strcpy(vol->prepath, value); | ||
1258 | cFYI(1, "prefix path %s", vol->prepath); | ||
1259 | } else { | ||
1260 | printk(KERN_WARNING "CIFS: prefix too long\n"); | ||
1261 | goto cifs_parse_mount_err; | ||
1262 | } | ||
1263 | } else if (strnicmp(data, "iocharset", 9) == 0) { | ||
1264 | if (!value || !*value) { | ||
1265 | printk(KERN_WARNING "CIFS: invalid iocharset " | ||
1266 | "specified\n"); | ||
1267 | goto cifs_parse_mount_err; | ||
1268 | } | ||
1269 | if (strnlen(value, 65) < 65) { | ||
1270 | if (strnicmp(value, "default", 7)) { | ||
1271 | vol->iocharset = kstrdup(value, | ||
1272 | GFP_KERNEL); | ||
1273 | |||
1274 | if (!vol->iocharset) { | ||
1275 | printk(KERN_WARNING "CIFS: no " | ||
1276 | "memory for" | ||
1277 | "charset\n"); | ||
1278 | goto cifs_parse_mount_err; | ||
1279 | } | ||
1280 | } | ||
1281 | /* if iocharset not set then load_nls_default | ||
1282 | is used by caller */ | ||
1283 | cFYI(1, "iocharset set to %s", value); | ||
1284 | } else { | ||
1285 | printk(KERN_WARNING "CIFS: iocharset name " | ||
1286 | "too long.\n"); | ||
1287 | goto cifs_parse_mount_err; | ||
1288 | } | ||
1289 | } else if (!strnicmp(data, "uid", 3) && value && *value) { | ||
1290 | vol->linux_uid = simple_strtoul(value, &value, 0); | ||
1291 | uid_specified = true; | ||
1292 | } else if (!strnicmp(data, "cruid", 5) && value && *value) { | ||
1293 | vol->cred_uid = simple_strtoul(value, &value, 0); | ||
1294 | } else if (!strnicmp(data, "forceuid", 8)) { | ||
1295 | override_uid = 1; | 1275 | override_uid = 1; |
1296 | } else if (!strnicmp(data, "noforceuid", 10)) { | 1276 | break; |
1277 | case Opt_noforceuid: | ||
1297 | override_uid = 0; | 1278 | override_uid = 0; |
1298 | } else if (!strnicmp(data, "gid", 3) && value && *value) { | 1279 | break; |
1299 | vol->linux_gid = simple_strtoul(value, &value, 0); | 1280 | case Opt_noblocksend: |
1300 | gid_specified = true; | ||
1301 | } else if (!strnicmp(data, "forcegid", 8)) { | ||
1302 | override_gid = 1; | ||
1303 | } else if (!strnicmp(data, "noforcegid", 10)) { | ||
1304 | override_gid = 0; | ||
1305 | } else if (strnicmp(data, "file_mode", 4) == 0) { | ||
1306 | if (value && *value) { | ||
1307 | vol->file_mode = | ||
1308 | simple_strtoul(value, &value, 0); | ||
1309 | } | ||
1310 | } else if (strnicmp(data, "dir_mode", 4) == 0) { | ||
1311 | if (value && *value) { | ||
1312 | vol->dir_mode = | ||
1313 | simple_strtoul(value, &value, 0); | ||
1314 | } | ||
1315 | } else if (strnicmp(data, "dirmode", 4) == 0) { | ||
1316 | if (value && *value) { | ||
1317 | vol->dir_mode = | ||
1318 | simple_strtoul(value, &value, 0); | ||
1319 | } | ||
1320 | } else if (strnicmp(data, "port", 4) == 0) { | ||
1321 | if (value && *value) { | ||
1322 | vol->port = | ||
1323 | simple_strtoul(value, &value, 0); | ||
1324 | } | ||
1325 | } else if (strnicmp(data, "rsize", 5) == 0) { | ||
1326 | if (value && *value) { | ||
1327 | vol->rsize = | ||
1328 | simple_strtoul(value, &value, 0); | ||
1329 | } | ||
1330 | } else if (strnicmp(data, "wsize", 5) == 0) { | ||
1331 | if (value && *value) { | ||
1332 | vol->wsize = | ||
1333 | simple_strtoul(value, &value, 0); | ||
1334 | } | ||
1335 | } else if (strnicmp(data, "sockopt", 5) == 0) { | ||
1336 | if (!value || !*value) { | ||
1337 | cERROR(1, "no socket option specified"); | ||
1338 | continue; | ||
1339 | } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) { | ||
1340 | vol->sockopt_tcp_nodelay = 1; | ||
1341 | } | ||
1342 | } else if (strnicmp(data, "netbiosname", 4) == 0) { | ||
1343 | if (!value || !*value || (*value == ' ')) { | ||
1344 | cFYI(1, "invalid (empty) netbiosname"); | ||
1345 | } else { | ||
1346 | memset(vol->source_rfc1001_name, 0x20, | ||
1347 | RFC1001_NAME_LEN); | ||
1348 | /* | ||
1349 | * FIXME: are there cases in which a comma can | ||
1350 | * be valid in workstation netbios name (and | ||
1351 | * need special handling)? | ||
1352 | */ | ||
1353 | for (i = 0; i < RFC1001_NAME_LEN; i++) { | ||
1354 | /* don't ucase netbiosname for user */ | ||
1355 | if (value[i] == 0) | ||
1356 | break; | ||
1357 | vol->source_rfc1001_name[i] = value[i]; | ||
1358 | } | ||
1359 | /* The string has 16th byte zero still from | ||
1360 | set at top of the function */ | ||
1361 | if (i == RFC1001_NAME_LEN && value[i] != 0) | ||
1362 | printk(KERN_WARNING "CIFS: netbiosname" | ||
1363 | " longer than 15 truncated.\n"); | ||
1364 | } | ||
1365 | } else if (strnicmp(data, "servern", 7) == 0) { | ||
1366 | /* servernetbiosname specified override *SMBSERVER */ | ||
1367 | if (!value || !*value || (*value == ' ')) { | ||
1368 | cFYI(1, "empty server netbiosname specified"); | ||
1369 | } else { | ||
1370 | /* last byte, type, is 0x20 for servr type */ | ||
1371 | memset(vol->target_rfc1001_name, 0x20, | ||
1372 | RFC1001_NAME_LEN_WITH_NULL); | ||
1373 | |||
1374 | for (i = 0; i < 15; i++) { | ||
1375 | /* BB are there cases in which a comma can be | ||
1376 | valid in this workstation netbios name | ||
1377 | (and need special handling)? */ | ||
1378 | |||
1379 | /* user or mount helper must uppercase | ||
1380 | the netbiosname */ | ||
1381 | if (value[i] == 0) | ||
1382 | break; | ||
1383 | else | ||
1384 | vol->target_rfc1001_name[i] = | ||
1385 | value[i]; | ||
1386 | } | ||
1387 | /* The string has 16th byte zero still from | ||
1388 | set at top of the function */ | ||
1389 | if (i == RFC1001_NAME_LEN && value[i] != 0) | ||
1390 | printk(KERN_WARNING "CIFS: server net" | ||
1391 | "biosname longer than 15 truncated.\n"); | ||
1392 | } | ||
1393 | } else if (strnicmp(data, "actimeo", 7) == 0) { | ||
1394 | if (value && *value) { | ||
1395 | vol->actimeo = HZ * simple_strtoul(value, | ||
1396 | &value, 0); | ||
1397 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { | ||
1398 | cERROR(1, "CIFS: attribute cache" | ||
1399 | "timeout too large"); | ||
1400 | goto cifs_parse_mount_err; | ||
1401 | } | ||
1402 | } | ||
1403 | } else if (strnicmp(data, "credentials", 4) == 0) { | ||
1404 | /* ignore */ | ||
1405 | } else if (strnicmp(data, "version", 3) == 0) { | ||
1406 | /* ignore */ | ||
1407 | } else if (strnicmp(data, "guest", 5) == 0) { | ||
1408 | /* ignore */ | ||
1409 | } else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) { | ||
1410 | /* ignore */ | ||
1411 | } else if (strnicmp(data, "ro", 2) == 0) { | ||
1412 | /* ignore */ | ||
1413 | } else if (strnicmp(data, "noblocksend", 11) == 0) { | ||
1414 | vol->noblocksnd = 1; | 1281 | vol->noblocksnd = 1; |
1415 | } else if (strnicmp(data, "noautotune", 10) == 0) { | 1282 | break; |
1283 | case Opt_noautotune: | ||
1416 | vol->noautotune = 1; | 1284 | vol->noautotune = 1; |
1417 | } else if ((strnicmp(data, "suid", 4) == 0) || | 1285 | break; |
1418 | (strnicmp(data, "nosuid", 6) == 0) || | 1286 | case Opt_hard: |
1419 | (strnicmp(data, "exec", 4) == 0) || | ||
1420 | (strnicmp(data, "noexec", 6) == 0) || | ||
1421 | (strnicmp(data, "nodev", 5) == 0) || | ||
1422 | (strnicmp(data, "noauto", 6) == 0) || | ||
1423 | (strnicmp(data, "dev", 3) == 0)) { | ||
1424 | /* The mount tool or mount.cifs helper (if present) | ||
1425 | uses these opts to set flags, and the flags are read | ||
1426 | by the kernel vfs layer before we get here (ie | ||
1427 | before read super) so there is no point trying to | ||
1428 | parse these options again and set anything and it | ||
1429 | is ok to just ignore them */ | ||
1430 | continue; | ||
1431 | } else if (strnicmp(data, "hard", 4) == 0) { | ||
1432 | vol->retry = 1; | 1287 | vol->retry = 1; |
1433 | } else if (strnicmp(data, "soft", 4) == 0) { | 1288 | break; |
1289 | case Opt_soft: | ||
1434 | vol->retry = 0; | 1290 | vol->retry = 0; |
1435 | } else if (strnicmp(data, "perm", 4) == 0) { | 1291 | break; |
1292 | case Opt_perm: | ||
1436 | vol->noperm = 0; | 1293 | vol->noperm = 0; |
1437 | } else if (strnicmp(data, "noperm", 6) == 0) { | 1294 | break; |
1295 | case Opt_noperm: | ||
1438 | vol->noperm = 1; | 1296 | vol->noperm = 1; |
1439 | } else if (strnicmp(data, "mapchars", 8) == 0) { | 1297 | break; |
1298 | case Opt_mapchars: | ||
1440 | vol->remap = 1; | 1299 | vol->remap = 1; |
1441 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | 1300 | break; |
1301 | case Opt_nomapchars: | ||
1442 | vol->remap = 0; | 1302 | vol->remap = 0; |
1443 | } else if (strnicmp(data, "sfu", 3) == 0) { | 1303 | break; |
1304 | case Opt_sfu: | ||
1444 | vol->sfu_emul = 1; | 1305 | vol->sfu_emul = 1; |
1445 | } else if (strnicmp(data, "nosfu", 5) == 0) { | 1306 | break; |
1307 | case Opt_nosfu: | ||
1446 | vol->sfu_emul = 0; | 1308 | vol->sfu_emul = 0; |
1447 | } else if (strnicmp(data, "nodfs", 5) == 0) { | 1309 | break; |
1310 | case Opt_nodfs: | ||
1448 | vol->nodfs = 1; | 1311 | vol->nodfs = 1; |
1449 | } else if (strnicmp(data, "posixpaths", 10) == 0) { | 1312 | break; |
1313 | case Opt_posixpaths: | ||
1450 | vol->posix_paths = 1; | 1314 | vol->posix_paths = 1; |
1451 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { | 1315 | break; |
1316 | case Opt_noposixpaths: | ||
1452 | vol->posix_paths = 0; | 1317 | vol->posix_paths = 0; |
1453 | } else if (strnicmp(data, "nounix", 6) == 0) { | 1318 | break; |
1454 | vol->no_linux_ext = 1; | 1319 | case Opt_nounix: |
1455 | } else if (strnicmp(data, "nolinux", 7) == 0) { | ||
1456 | vol->no_linux_ext = 1; | 1320 | vol->no_linux_ext = 1; |
1457 | } else if ((strnicmp(data, "nocase", 6) == 0) || | 1321 | break; |
1458 | (strnicmp(data, "ignorecase", 10) == 0)) { | 1322 | case Opt_nocase: |
1459 | vol->nocase = 1; | 1323 | vol->nocase = 1; |
1460 | } else if (strnicmp(data, "mand", 4) == 0) { | 1324 | break; |
1461 | /* ignore */ | 1325 | case Opt_brl: |
1462 | } else if (strnicmp(data, "nomand", 6) == 0) { | ||
1463 | /* ignore */ | ||
1464 | } else if (strnicmp(data, "_netdev", 7) == 0) { | ||
1465 | /* ignore */ | ||
1466 | } else if (strnicmp(data, "brl", 3) == 0) { | ||
1467 | vol->nobrl = 0; | 1326 | vol->nobrl = 0; |
1468 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | 1327 | break; |
1469 | (strnicmp(data, "nolock", 6) == 0)) { | 1328 | case Opt_nobrl: |
1470 | vol->nobrl = 1; | 1329 | vol->nobrl = 1; |
1471 | /* turn off mandatory locking in mode | 1330 | /* |
1472 | if remote locking is turned off since the | 1331 | * turn off mandatory locking in mode |
1473 | local vfs will do advisory */ | 1332 | * if remote locking is turned off since the |
1333 | * local vfs will do advisory | ||
1334 | */ | ||
1474 | if (vol->file_mode == | 1335 | if (vol->file_mode == |
1475 | (S_IALLUGO & ~(S_ISUID | S_IXGRP))) | 1336 | (S_IALLUGO & ~(S_ISUID | S_IXGRP))) |
1476 | vol->file_mode = S_IALLUGO; | 1337 | vol->file_mode = S_IALLUGO; |
1477 | } else if (strnicmp(data, "forcemandatorylock", 9) == 0) { | 1338 | break; |
1478 | /* will take the shorter form "forcemand" as well */ | 1339 | case Opt_forcemandatorylock: |
1479 | /* This mount option will force use of mandatory | ||
1480 | (DOS/Windows style) byte range locks, instead of | ||
1481 | using posix advisory byte range locks, even if the | ||
1482 | Unix extensions are available and posix locks would | ||
1483 | be supported otherwise. If Unix extensions are not | ||
1484 | negotiated this has no effect since mandatory locks | ||
1485 | would be used (mandatory locks is all that those | ||
1486 | those servers support) */ | ||
1487 | vol->mand_lock = 1; | 1340 | vol->mand_lock = 1; |
1488 | } else if (strnicmp(data, "setuids", 7) == 0) { | 1341 | break; |
1342 | case Opt_setuids: | ||
1489 | vol->setuids = 1; | 1343 | vol->setuids = 1; |
1490 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1344 | break; |
1345 | case Opt_nosetuids: | ||
1491 | vol->setuids = 0; | 1346 | vol->setuids = 0; |
1492 | } else if (strnicmp(data, "dynperm", 7) == 0) { | 1347 | break; |
1348 | case Opt_dynperm: | ||
1493 | vol->dynperm = true; | 1349 | vol->dynperm = true; |
1494 | } else if (strnicmp(data, "nodynperm", 9) == 0) { | 1350 | break; |
1351 | case Opt_nodynperm: | ||
1495 | vol->dynperm = false; | 1352 | vol->dynperm = false; |
1496 | } else if (strnicmp(data, "nohard", 6) == 0) { | 1353 | break; |
1354 | case Opt_nohard: | ||
1497 | vol->retry = 0; | 1355 | vol->retry = 0; |
1498 | } else if (strnicmp(data, "nosoft", 6) == 0) { | 1356 | break; |
1357 | case Opt_nosoft: | ||
1499 | vol->retry = 1; | 1358 | vol->retry = 1; |
1500 | } else if (strnicmp(data, "nointr", 6) == 0) { | 1359 | break; |
1360 | case Opt_nointr: | ||
1501 | vol->intr = 0; | 1361 | vol->intr = 0; |
1502 | } else if (strnicmp(data, "intr", 4) == 0) { | 1362 | break; |
1363 | case Opt_intr: | ||
1503 | vol->intr = 1; | 1364 | vol->intr = 1; |
1504 | } else if (strnicmp(data, "nostrictsync", 12) == 0) { | 1365 | break; |
1366 | case Opt_nostrictsync: | ||
1505 | vol->nostrictsync = 1; | 1367 | vol->nostrictsync = 1; |
1506 | } else if (strnicmp(data, "strictsync", 10) == 0) { | 1368 | break; |
1369 | case Opt_strictsync: | ||
1507 | vol->nostrictsync = 0; | 1370 | vol->nostrictsync = 0; |
1508 | } else if (strnicmp(data, "serverino", 7) == 0) { | 1371 | break; |
1372 | case Opt_serverino: | ||
1509 | vol->server_ino = 1; | 1373 | vol->server_ino = 1; |
1510 | } else if (strnicmp(data, "noserverino", 9) == 0) { | 1374 | break; |
1375 | case Opt_noserverino: | ||
1511 | vol->server_ino = 0; | 1376 | vol->server_ino = 0; |
1512 | } else if (strnicmp(data, "rwpidforward", 12) == 0) { | 1377 | break; |
1378 | case Opt_rwpidforward: | ||
1513 | vol->rwpidforward = 1; | 1379 | vol->rwpidforward = 1; |
1514 | } else if (strnicmp(data, "cifsacl", 7) == 0) { | 1380 | break; |
1381 | case Opt_cifsacl: | ||
1515 | vol->cifs_acl = 1; | 1382 | vol->cifs_acl = 1; |
1516 | } else if (strnicmp(data, "nocifsacl", 9) == 0) { | 1383 | break; |
1384 | case Opt_nocifsacl: | ||
1517 | vol->cifs_acl = 0; | 1385 | vol->cifs_acl = 0; |
1518 | } else if (strnicmp(data, "acl", 3) == 0) { | 1386 | break; |
1387 | case Opt_acl: | ||
1519 | vol->no_psx_acl = 0; | 1388 | vol->no_psx_acl = 0; |
1520 | } else if (strnicmp(data, "noacl", 5) == 0) { | 1389 | break; |
1390 | case Opt_noacl: | ||
1521 | vol->no_psx_acl = 1; | 1391 | vol->no_psx_acl = 1; |
1522 | } else if (strnicmp(data, "locallease", 6) == 0) { | 1392 | break; |
1393 | case Opt_locallease: | ||
1523 | vol->local_lease = 1; | 1394 | vol->local_lease = 1; |
1524 | } else if (strnicmp(data, "sign", 4) == 0) { | 1395 | break; |
1396 | case Opt_sign: | ||
1525 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1397 | vol->secFlg |= CIFSSEC_MUST_SIGN; |
1526 | } else if (strnicmp(data, "seal", 4) == 0) { | 1398 | break; |
1399 | case Opt_seal: | ||
1527 | /* we do not do the following in secFlags because seal | 1400 | /* we do not do the following in secFlags because seal |
1528 | is a per tree connection (mount) not a per socket | 1401 | * is a per tree connection (mount) not a per socket |
1529 | or per-smb connection option in the protocol */ | 1402 | * or per-smb connection option in the protocol |
1530 | /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ | 1403 | * vol->secFlg |= CIFSSEC_MUST_SEAL; |
1404 | */ | ||
1531 | vol->seal = 1; | 1405 | vol->seal = 1; |
1532 | } else if (strnicmp(data, "direct", 6) == 0) { | 1406 | break; |
1533 | vol->direct_io = 1; | 1407 | case Opt_direct: |
1534 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { | ||
1535 | vol->direct_io = 1; | 1408 | vol->direct_io = 1; |
1536 | } else if (strnicmp(data, "strictcache", 11) == 0) { | 1409 | break; |
1410 | case Opt_strictcache: | ||
1537 | vol->strict_io = 1; | 1411 | vol->strict_io = 1; |
1538 | } else if (strnicmp(data, "noac", 4) == 0) { | 1412 | break; |
1413 | case Opt_noac: | ||
1539 | printk(KERN_WARNING "CIFS: Mount option noac not " | 1414 | printk(KERN_WARNING "CIFS: Mount option noac not " |
1540 | "supported. Instead set " | 1415 | "supported. Instead set " |
1541 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); | 1416 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); |
1542 | } else if (strnicmp(data, "fsc", 3) == 0) { | 1417 | break; |
1418 | case Opt_fsc: | ||
1543 | #ifndef CONFIG_CIFS_FSCACHE | 1419 | #ifndef CONFIG_CIFS_FSCACHE |
1544 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " | 1420 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " |
1545 | "kernel config option set"); | 1421 | "kernel config option set"); |
1546 | goto cifs_parse_mount_err; | 1422 | goto cifs_parse_mount_err; |
1547 | #endif | 1423 | #endif |
1548 | vol->fsc = true; | 1424 | vol->fsc = true; |
1549 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1425 | break; |
1426 | case Opt_mfsymlinks: | ||
1550 | vol->mfsymlinks = true; | 1427 | vol->mfsymlinks = true; |
1551 | } else if (strnicmp(data, "multiuser", 8) == 0) { | 1428 | break; |
1429 | case Opt_multiuser: | ||
1552 | vol->multiuser = true; | 1430 | vol->multiuser = true; |
1553 | } else if (!strnicmp(data, "backupuid", 9) && value && *value) { | 1431 | break; |
1554 | err = kstrtouint(value, 0, &vol->backupuid); | 1432 | case Opt_sloppy: |
1555 | if (err < 0) { | 1433 | sloppy = true; |
1434 | break; | ||
1435 | |||
1436 | /* Numeric Values */ | ||
1437 | case Opt_backupuid: | ||
1438 | if (get_option_ul(args, &option)) { | ||
1556 | cERROR(1, "%s: Invalid backupuid value", | 1439 | cERROR(1, "%s: Invalid backupuid value", |
1557 | __func__); | 1440 | __func__); |
1558 | goto cifs_parse_mount_err; | 1441 | goto cifs_parse_mount_err; |
1559 | } | 1442 | } |
1443 | vol->backupuid = option; | ||
1560 | vol->backupuid_specified = true; | 1444 | vol->backupuid_specified = true; |
1561 | } else if (!strnicmp(data, "backupgid", 9) && value && *value) { | 1445 | break; |
1562 | err = kstrtouint(value, 0, &vol->backupgid); | 1446 | case Opt_backupgid: |
1563 | if (err < 0) { | 1447 | if (get_option_ul(args, &option)) { |
1564 | cERROR(1, "%s: Invalid backupgid value", | 1448 | cERROR(1, "%s: Invalid backupgid value", |
1565 | __func__); | 1449 | __func__); |
1566 | goto cifs_parse_mount_err; | 1450 | goto cifs_parse_mount_err; |
1567 | } | 1451 | } |
1452 | vol->backupgid = option; | ||
1568 | vol->backupgid_specified = true; | 1453 | vol->backupgid_specified = true; |
1569 | } else | 1454 | break; |
1570 | printk(KERN_WARNING "CIFS: Unknown mount option %s\n", | 1455 | case Opt_uid: |
1571 | data); | 1456 | if (get_option_ul(args, &option)) { |
1572 | } | 1457 | cERROR(1, "%s: Invalid uid value", |
1573 | if (vol->UNC == NULL) { | 1458 | __func__); |
1574 | if (devname == NULL) { | 1459 | goto cifs_parse_mount_err; |
1575 | printk(KERN_WARNING "CIFS: Missing UNC name for mount " | 1460 | } |
1576 | "target\n"); | 1461 | vol->linux_uid = option; |
1577 | goto cifs_parse_mount_err; | 1462 | uid_specified = true; |
1578 | } | 1463 | break; |
1579 | if ((temp_len = strnlen(devname, 300)) < 300) { | 1464 | case Opt_cruid: |
1580 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | 1465 | if (get_option_ul(args, &option)) { |
1581 | if (vol->UNC == NULL) | 1466 | cERROR(1, "%s: Invalid cruid value", |
1467 | __func__); | ||
1468 | goto cifs_parse_mount_err; | ||
1469 | } | ||
1470 | vol->cred_uid = option; | ||
1471 | break; | ||
1472 | case Opt_gid: | ||
1473 | if (get_option_ul(args, &option)) { | ||
1474 | cERROR(1, "%s: Invalid gid value", | ||
1475 | __func__); | ||
1476 | goto cifs_parse_mount_err; | ||
1477 | } | ||
1478 | vol->linux_gid = option; | ||
1479 | gid_specified = true; | ||
1480 | break; | ||
1481 | case Opt_file_mode: | ||
1482 | if (get_option_ul(args, &option)) { | ||
1483 | cERROR(1, "%s: Invalid file_mode value", | ||
1484 | __func__); | ||
1485 | goto cifs_parse_mount_err; | ||
1486 | } | ||
1487 | vol->file_mode = option; | ||
1488 | break; | ||
1489 | case Opt_dirmode: | ||
1490 | if (get_option_ul(args, &option)) { | ||
1491 | cERROR(1, "%s: Invalid dir_mode value", | ||
1492 | __func__); | ||
1493 | goto cifs_parse_mount_err; | ||
1494 | } | ||
1495 | vol->dir_mode = option; | ||
1496 | break; | ||
1497 | case Opt_port: | ||
1498 | if (get_option_ul(args, &option)) { | ||
1499 | cERROR(1, "%s: Invalid port value", | ||
1500 | __func__); | ||
1501 | goto cifs_parse_mount_err; | ||
1502 | } | ||
1503 | vol->port = option; | ||
1504 | break; | ||
1505 | case Opt_rsize: | ||
1506 | if (get_option_ul(args, &option)) { | ||
1507 | cERROR(1, "%s: Invalid rsize value", | ||
1508 | __func__); | ||
1509 | goto cifs_parse_mount_err; | ||
1510 | } | ||
1511 | vol->rsize = option; | ||
1512 | break; | ||
1513 | case Opt_wsize: | ||
1514 | if (get_option_ul(args, &option)) { | ||
1515 | cERROR(1, "%s: Invalid wsize value", | ||
1516 | __func__); | ||
1517 | goto cifs_parse_mount_err; | ||
1518 | } | ||
1519 | vol->wsize = option; | ||
1520 | break; | ||
1521 | case Opt_actimeo: | ||
1522 | if (get_option_ul(args, &option)) { | ||
1523 | cERROR(1, "%s: Invalid actimeo value", | ||
1524 | __func__); | ||
1525 | goto cifs_parse_mount_err; | ||
1526 | } | ||
1527 | vol->actimeo = HZ * option; | ||
1528 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { | ||
1529 | cERROR(1, "CIFS: attribute cache" | ||
1530 | "timeout too large"); | ||
1531 | goto cifs_parse_mount_err; | ||
1532 | } | ||
1533 | break; | ||
1534 | |||
1535 | /* String Arguments */ | ||
1536 | |||
1537 | case Opt_user: | ||
1538 | string = match_strdup(args); | ||
1539 | if (string == NULL) | ||
1540 | goto out_nomem; | ||
1541 | |||
1542 | if (!*string) { | ||
1543 | /* null user, ie. anonymous authentication */ | ||
1544 | vol->nullauth = 1; | ||
1545 | } else if (strnlen(string, MAX_USERNAME_SIZE) > | ||
1546 | MAX_USERNAME_SIZE) { | ||
1547 | printk(KERN_WARNING "CIFS: username too long\n"); | ||
1548 | goto cifs_parse_mount_err; | ||
1549 | } | ||
1550 | vol->username = kstrdup(string, GFP_KERNEL); | ||
1551 | if (!vol->username) { | ||
1552 | printk(KERN_WARNING "CIFS: no memory " | ||
1553 | "for username\n"); | ||
1554 | goto cifs_parse_mount_err; | ||
1555 | } | ||
1556 | break; | ||
1557 | case Opt_blank_pass: | ||
1558 | vol->password = NULL; | ||
1559 | break; | ||
1560 | case Opt_pass: | ||
1561 | /* passwords have to be handled differently | ||
1562 | * to allow the character used for deliminator | ||
1563 | * to be passed within them | ||
1564 | */ | ||
1565 | |||
1566 | /* Obtain the value string */ | ||
1567 | value = strchr(data, '='); | ||
1568 | if (value != NULL) | ||
1569 | *value++ = '\0'; | ||
1570 | |||
1571 | /* Set tmp_end to end of the string */ | ||
1572 | tmp_end = (char *) value + strlen(value); | ||
1573 | |||
1574 | /* Check if following character is the deliminator | ||
1575 | * If yes, we have encountered a double deliminator | ||
1576 | * reset the NULL character to the deliminator | ||
1577 | */ | ||
1578 | if (tmp_end < end && tmp_end[1] == delim) | ||
1579 | tmp_end[0] = delim; | ||
1580 | |||
1581 | /* Keep iterating until we get to a single deliminator | ||
1582 | * OR the end | ||
1583 | */ | ||
1584 | while ((tmp_end = strchr(tmp_end, delim)) != NULL && | ||
1585 | (tmp_end[1] == delim)) { | ||
1586 | tmp_end = (char *) &tmp_end[2]; | ||
1587 | } | ||
1588 | |||
1589 | /* Reset var options to point to next element */ | ||
1590 | if (tmp_end) { | ||
1591 | tmp_end[0] = '\0'; | ||
1592 | options = (char *) &tmp_end[1]; | ||
1593 | } else | ||
1594 | /* Reached the end of the mount option string */ | ||
1595 | options = end; | ||
1596 | |||
1597 | /* Now build new password string */ | ||
1598 | temp_len = strlen(value); | ||
1599 | vol->password = kzalloc(temp_len+1, GFP_KERNEL); | ||
1600 | if (vol->password == NULL) { | ||
1601 | printk(KERN_WARNING "CIFS: no memory " | ||
1602 | "for password\n"); | ||
1582 | goto cifs_parse_mount_err; | 1603 | goto cifs_parse_mount_err; |
1583 | strcpy(vol->UNC, devname); | 1604 | } |
1584 | if (strncmp(vol->UNC, "//", 2) == 0) { | 1605 | |
1606 | for (i = 0, j = 0; i < temp_len; i++, j++) { | ||
1607 | vol->password[j] = value[i]; | ||
1608 | if ((value[i] == delim) && | ||
1609 | value[i+1] == delim) | ||
1610 | /* skip the second deliminator */ | ||
1611 | i++; | ||
1612 | } | ||
1613 | vol->password[j] = '\0'; | ||
1614 | break; | ||
1615 | case Opt_ip: | ||
1616 | string = match_strdup(args); | ||
1617 | if (string == NULL) | ||
1618 | goto out_nomem; | ||
1619 | |||
1620 | if (!*string) { | ||
1621 | vol->UNCip = NULL; | ||
1622 | } else if (strnlen(string, INET6_ADDRSTRLEN) > | ||
1623 | INET6_ADDRSTRLEN) { | ||
1624 | printk(KERN_WARNING "CIFS: ip address " | ||
1625 | "too long\n"); | ||
1626 | goto cifs_parse_mount_err; | ||
1627 | } | ||
1628 | vol->UNCip = kstrdup(string, GFP_KERNEL); | ||
1629 | if (!vol->UNCip) { | ||
1630 | printk(KERN_WARNING "CIFS: no memory " | ||
1631 | "for UNC IP\n"); | ||
1632 | goto cifs_parse_mount_err; | ||
1633 | } | ||
1634 | break; | ||
1635 | case Opt_unc: | ||
1636 | string = match_strdup(args); | ||
1637 | if (string == NULL) | ||
1638 | goto out_nomem; | ||
1639 | |||
1640 | if (!*string) { | ||
1641 | printk(KERN_WARNING "CIFS: invalid path to " | ||
1642 | "network resource\n"); | ||
1643 | goto cifs_parse_mount_err; | ||
1644 | } | ||
1645 | |||
1646 | temp_len = strnlen(string, 300); | ||
1647 | if (temp_len == 300) { | ||
1648 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | ||
1649 | goto cifs_parse_mount_err; | ||
1650 | } | ||
1651 | |||
1652 | if (strncmp(string, "//", 2) == 0) { | ||
1585 | vol->UNC[0] = '\\'; | 1653 | vol->UNC[0] = '\\'; |
1586 | vol->UNC[1] = '\\'; | 1654 | vol->UNC[1] = '\\'; |
1587 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { | 1655 | } else if (strncmp(string, "\\\\", 2) != 0) { |
1588 | printk(KERN_WARNING "CIFS: UNC Path does not " | 1656 | printk(KERN_WARNING "CIFS: UNC Path does not " |
1589 | "begin with // or \\\\ \n"); | 1657 | "begin with // or \\\\\n"); |
1590 | goto cifs_parse_mount_err; | 1658 | goto cifs_parse_mount_err; |
1591 | } | 1659 | } |
1592 | value = strpbrk(vol->UNC+2, "/\\"); | 1660 | |
1593 | if (value) | 1661 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); |
1594 | *value = '\\'; | 1662 | if (vol->UNC == NULL) { |
1595 | } else { | 1663 | printk(KERN_WARNING "CIFS: no memory " |
1596 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | 1664 | "for UNC\n"); |
1665 | goto cifs_parse_mount_err; | ||
1666 | } | ||
1667 | strcpy(vol->UNC, string); | ||
1668 | break; | ||
1669 | case Opt_domain: | ||
1670 | string = match_strdup(args); | ||
1671 | if (string == NULL) | ||
1672 | goto out_nomem; | ||
1673 | |||
1674 | if (!*string) { | ||
1675 | printk(KERN_WARNING "CIFS: invalid domain" | ||
1676 | " name\n"); | ||
1677 | goto cifs_parse_mount_err; | ||
1678 | } else if (strnlen(string, 256) == 256) { | ||
1679 | printk(KERN_WARNING "CIFS: domain name too" | ||
1680 | " long\n"); | ||
1681 | goto cifs_parse_mount_err; | ||
1682 | } | ||
1683 | |||
1684 | vol->domainname = kstrdup(string, GFP_KERNEL); | ||
1685 | if (!vol->domainname) { | ||
1686 | printk(KERN_WARNING "CIFS: no memory " | ||
1687 | "for domainname\n"); | ||
1688 | goto cifs_parse_mount_err; | ||
1689 | } | ||
1690 | cFYI(1, "Domain name set"); | ||
1691 | break; | ||
1692 | case Opt_srcaddr: | ||
1693 | string = match_strdup(args); | ||
1694 | if (string == NULL) | ||
1695 | goto out_nomem; | ||
1696 | |||
1697 | if (!*string) { | ||
1698 | printk(KERN_WARNING "CIFS: srcaddr value not" | ||
1699 | " specified\n"); | ||
1700 | goto cifs_parse_mount_err; | ||
1701 | } else if (!cifs_convert_address( | ||
1702 | (struct sockaddr *)&vol->srcaddr, | ||
1703 | string, strlen(string))) { | ||
1704 | printk(KERN_WARNING "CIFS: Could not parse" | ||
1705 | " srcaddr: %s\n", string); | ||
1706 | goto cifs_parse_mount_err; | ||
1707 | } | ||
1708 | break; | ||
1709 | case Opt_prefixpath: | ||
1710 | string = match_strdup(args); | ||
1711 | if (string == NULL) | ||
1712 | goto out_nomem; | ||
1713 | |||
1714 | if (!*string) { | ||
1715 | printk(KERN_WARNING "CIFS: Invalid path" | ||
1716 | " prefix\n"); | ||
1717 | goto cifs_parse_mount_err; | ||
1718 | } | ||
1719 | temp_len = strnlen(string, 1024); | ||
1720 | if (string[0] != '/') | ||
1721 | temp_len++; /* missing leading slash */ | ||
1722 | if (temp_len > 1024) { | ||
1723 | printk(KERN_WARNING "CIFS: prefix too long\n"); | ||
1724 | goto cifs_parse_mount_err; | ||
1725 | } | ||
1726 | |||
1727 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); | ||
1728 | if (vol->prepath == NULL) { | ||
1729 | printk(KERN_WARNING "CIFS: no memory " | ||
1730 | "for path prefix\n"); | ||
1731 | goto cifs_parse_mount_err; | ||
1732 | } | ||
1733 | |||
1734 | if (string[0] != '/') { | ||
1735 | vol->prepath[0] = '/'; | ||
1736 | strcpy(vol->prepath+1, string); | ||
1737 | } else | ||
1738 | strcpy(vol->prepath, string); | ||
1739 | |||
1740 | break; | ||
1741 | case Opt_iocharset: | ||
1742 | string = match_strdup(args); | ||
1743 | if (string == NULL) | ||
1744 | goto out_nomem; | ||
1745 | |||
1746 | if (!*string) { | ||
1747 | printk(KERN_WARNING "CIFS: Invalid iocharset" | ||
1748 | " specified\n"); | ||
1749 | goto cifs_parse_mount_err; | ||
1750 | } else if (strnlen(string, 1024) >= 65) { | ||
1751 | printk(KERN_WARNING "CIFS: iocharset name " | ||
1752 | "too long.\n"); | ||
1753 | goto cifs_parse_mount_err; | ||
1754 | } | ||
1755 | |||
1756 | if (strnicmp(string, "default", 7) != 0) { | ||
1757 | vol->iocharset = kstrdup(string, | ||
1758 | GFP_KERNEL); | ||
1759 | if (!vol->iocharset) { | ||
1760 | printk(KERN_WARNING "CIFS: no memory" | ||
1761 | "for charset\n"); | ||
1762 | goto cifs_parse_mount_err; | ||
1763 | } | ||
1764 | } | ||
1765 | /* if iocharset not set then load_nls_default | ||
1766 | * is used by caller | ||
1767 | */ | ||
1768 | cFYI(1, "iocharset set to %s", string); | ||
1769 | break; | ||
1770 | case Opt_sockopt: | ||
1771 | string = match_strdup(args); | ||
1772 | if (string == NULL) | ||
1773 | goto out_nomem; | ||
1774 | |||
1775 | if (!*string) { | ||
1776 | printk(KERN_WARNING "CIFS: No socket option" | ||
1777 | " specified\n"); | ||
1778 | goto cifs_parse_mount_err; | ||
1779 | } | ||
1780 | if (strnicmp(string, "TCP_NODELAY", 11) == 0) | ||
1781 | vol->sockopt_tcp_nodelay = 1; | ||
1782 | break; | ||
1783 | case Opt_netbiosname: | ||
1784 | string = match_strdup(args); | ||
1785 | if (string == NULL) | ||
1786 | goto out_nomem; | ||
1787 | |||
1788 | if (!*string) { | ||
1789 | printk(KERN_WARNING "CIFS: Invalid (empty)" | ||
1790 | " netbiosname\n"); | ||
1791 | break; | ||
1792 | } | ||
1793 | |||
1794 | memset(vol->source_rfc1001_name, 0x20, | ||
1795 | RFC1001_NAME_LEN); | ||
1796 | /* | ||
1797 | * FIXME: are there cases in which a comma can | ||
1798 | * be valid in workstation netbios name (and | ||
1799 | * need special handling)? | ||
1800 | */ | ||
1801 | for (i = 0; i < RFC1001_NAME_LEN; i++) { | ||
1802 | /* don't ucase netbiosname for user */ | ||
1803 | if (string[i] == 0) | ||
1804 | break; | ||
1805 | vol->source_rfc1001_name[i] = string[i]; | ||
1806 | } | ||
1807 | /* The string has 16th byte zero still from | ||
1808 | * set at top of the function | ||
1809 | */ | ||
1810 | if (i == RFC1001_NAME_LEN && string[i] != 0) | ||
1811 | printk(KERN_WARNING "CIFS: netbiosname" | ||
1812 | " longer than 15 truncated.\n"); | ||
1813 | |||
1814 | break; | ||
1815 | case Opt_servern: | ||
1816 | /* servernetbiosname specified override *SMBSERVER */ | ||
1817 | string = match_strdup(args); | ||
1818 | if (string == NULL) | ||
1819 | goto out_nomem; | ||
1820 | |||
1821 | if (!*string) { | ||
1822 | printk(KERN_WARNING "CIFS: Empty server" | ||
1823 | " netbiosname specified\n"); | ||
1824 | break; | ||
1825 | } | ||
1826 | /* last byte, type, is 0x20 for servr type */ | ||
1827 | memset(vol->target_rfc1001_name, 0x20, | ||
1828 | RFC1001_NAME_LEN_WITH_NULL); | ||
1829 | |||
1830 | /* BB are there cases in which a comma can be | ||
1831 | valid in this workstation netbios name | ||
1832 | (and need special handling)? */ | ||
1833 | |||
1834 | /* user or mount helper must uppercase the | ||
1835 | netbios name */ | ||
1836 | for (i = 0; i < 15; i++) { | ||
1837 | if (string[i] == 0) | ||
1838 | break; | ||
1839 | vol->target_rfc1001_name[i] = string[i]; | ||
1840 | } | ||
1841 | /* The string has 16th byte zero still from | ||
1842 | set at top of the function */ | ||
1843 | if (i == RFC1001_NAME_LEN && string[i] != 0) | ||
1844 | printk(KERN_WARNING "CIFS: server net" | ||
1845 | "biosname longer than 15 truncated.\n"); | ||
1846 | break; | ||
1847 | case Opt_ver: | ||
1848 | string = match_strdup(args); | ||
1849 | if (string == NULL) | ||
1850 | goto out_nomem; | ||
1851 | |||
1852 | if (!*string) { | ||
1853 | cERROR(1, "no protocol version specified" | ||
1854 | " after vers= mount option"); | ||
1855 | goto cifs_parse_mount_err; | ||
1856 | } | ||
1857 | |||
1858 | if (strnicmp(string, "cifs", 4) == 0 || | ||
1859 | strnicmp(string, "1", 1) == 0) { | ||
1860 | /* This is the default */ | ||
1861 | break; | ||
1862 | } | ||
1863 | /* For all other value, error */ | ||
1864 | printk(KERN_WARNING "CIFS: Invalid version" | ||
1865 | " specified\n"); | ||
1597 | goto cifs_parse_mount_err; | 1866 | goto cifs_parse_mount_err; |
1867 | case Opt_sec: | ||
1868 | string = match_strdup(args); | ||
1869 | if (string == NULL) | ||
1870 | goto out_nomem; | ||
1871 | |||
1872 | if (!*string) { | ||
1873 | printk(KERN_WARNING "CIFS: no security flavor" | ||
1874 | " specified\n"); | ||
1875 | break; | ||
1876 | } | ||
1877 | |||
1878 | if (cifs_parse_security_flavors(string, vol) != 0) | ||
1879 | goto cifs_parse_mount_err; | ||
1880 | break; | ||
1881 | default: | ||
1882 | /* | ||
1883 | * An option we don't recognize. Save it off for later | ||
1884 | * if we haven't already found one | ||
1885 | */ | ||
1886 | if (!invalid) | ||
1887 | invalid = data; | ||
1888 | break; | ||
1598 | } | 1889 | } |
1890 | /* Free up any allocated string */ | ||
1891 | kfree(string); | ||
1892 | string = NULL; | ||
1893 | } | ||
1894 | |||
1895 | if (!sloppy && invalid) { | ||
1896 | printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid); | ||
1897 | goto cifs_parse_mount_err; | ||
1599 | } | 1898 | } |
1600 | 1899 | ||
1601 | #ifndef CONFIG_KEYS | 1900 | #ifndef CONFIG_KEYS |
@@ -1625,7 +1924,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1625 | kfree(mountdata_copy); | 1924 | kfree(mountdata_copy); |
1626 | return 0; | 1925 | return 0; |
1627 | 1926 | ||
1927 | out_nomem: | ||
1928 | printk(KERN_WARNING "Could not allocate temporary buffer\n"); | ||
1628 | cifs_parse_mount_err: | 1929 | cifs_parse_mount_err: |
1930 | kfree(string); | ||
1629 | kfree(mountdata_copy); | 1931 | kfree(mountdata_copy); |
1630 | return 1; | 1932 | return 1; |
1631 | } | 1933 | } |
@@ -1977,7 +2279,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1977 | cifs_fscache_get_client_cookie(tcp_ses); | 2279 | cifs_fscache_get_client_cookie(tcp_ses); |
1978 | 2280 | ||
1979 | /* queue echo request delayed work */ | 2281 | /* queue echo request delayed work */ |
1980 | queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); | 2282 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); |
1981 | 2283 | ||
1982 | return tcp_ses; | 2284 | return tcp_ses; |
1983 | 2285 | ||
@@ -3543,7 +3845,7 @@ remote_path_check: | |||
3543 | tlink_rb_insert(&cifs_sb->tlink_tree, tlink); | 3845 | tlink_rb_insert(&cifs_sb->tlink_tree, tlink); |
3544 | spin_unlock(&cifs_sb->tlink_tree_lock); | 3846 | spin_unlock(&cifs_sb->tlink_tree_lock); |
3545 | 3847 | ||
3546 | queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, | 3848 | queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, |
3547 | TLINK_IDLE_EXPIRE); | 3849 | TLINK_IDLE_EXPIRE); |
3548 | 3850 | ||
3549 | mount_fail_check: | 3851 | mount_fail_check: |
@@ -4097,6 +4399,6 @@ cifs_prune_tlinks(struct work_struct *work) | |||
4097 | } | 4399 | } |
4098 | spin_unlock(&cifs_sb->tlink_tree_lock); | 4400 | spin_unlock(&cifs_sb->tlink_tree_lock); |
4099 | 4401 | ||
4100 | queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, | 4402 | queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, |
4101 | TLINK_IDLE_EXPIRE); | 4403 | TLINK_IDLE_EXPIRE); |
4102 | } | 4404 | } |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 159fcc56dc2d..460d87b7cda0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1399,7 +1399,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) | |||
1399 | return rc; | 1399 | return rc; |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | /* update the file size (if needed) after a write */ | 1402 | /* |
1403 | * update the file size (if needed) after a write. Should be called with | ||
1404 | * the inode->i_lock held | ||
1405 | */ | ||
1403 | void | 1406 | void |
1404 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | 1407 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, |
1405 | unsigned int bytes_written) | 1408 | unsigned int bytes_written) |
@@ -1471,7 +1474,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, | |||
1471 | return rc; | 1474 | return rc; |
1472 | } | 1475 | } |
1473 | } else { | 1476 | } else { |
1477 | spin_lock(&dentry->d_inode->i_lock); | ||
1474 | cifs_update_eof(cifsi, *poffset, bytes_written); | 1478 | cifs_update_eof(cifsi, *poffset, bytes_written); |
1479 | spin_unlock(&dentry->d_inode->i_lock); | ||
1475 | *poffset += bytes_written; | 1480 | *poffset += bytes_written; |
1476 | } | 1481 | } |
1477 | } | 1482 | } |
@@ -1648,6 +1653,27 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1648 | return rc; | 1653 | return rc; |
1649 | } | 1654 | } |
1650 | 1655 | ||
1656 | /* | ||
1657 | * Marshal up the iov array, reserving the first one for the header. Also, | ||
1658 | * set wdata->bytes. | ||
1659 | */ | ||
1660 | static void | ||
1661 | cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) | ||
1662 | { | ||
1663 | int i; | ||
1664 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
1665 | loff_t size = i_size_read(inode); | ||
1666 | |||
1667 | /* marshal up the pages into iov array */ | ||
1668 | wdata->bytes = 0; | ||
1669 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1670 | iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), | ||
1671 | (loff_t)PAGE_CACHE_SIZE); | ||
1672 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
1673 | wdata->bytes += iov[i + 1].iov_len; | ||
1674 | } | ||
1675 | } | ||
1676 | |||
1651 | static int cifs_writepages(struct address_space *mapping, | 1677 | static int cifs_writepages(struct address_space *mapping, |
1652 | struct writeback_control *wbc) | 1678 | struct writeback_control *wbc) |
1653 | { | 1679 | { |
@@ -1684,7 +1710,8 @@ retry: | |||
1684 | tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1, | 1710 | tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1, |
1685 | end - index) + 1; | 1711 | end - index) + 1; |
1686 | 1712 | ||
1687 | wdata = cifs_writedata_alloc((unsigned int)tofind); | 1713 | wdata = cifs_writedata_alloc((unsigned int)tofind, |
1714 | cifs_writev_complete); | ||
1688 | if (!wdata) { | 1715 | if (!wdata) { |
1689 | rc = -ENOMEM; | 1716 | rc = -ENOMEM; |
1690 | break; | 1717 | break; |
@@ -1791,6 +1818,7 @@ retry: | |||
1791 | wdata->sync_mode = wbc->sync_mode; | 1818 | wdata->sync_mode = wbc->sync_mode; |
1792 | wdata->nr_pages = nr_pages; | 1819 | wdata->nr_pages = nr_pages; |
1793 | wdata->offset = page_offset(wdata->pages[0]); | 1820 | wdata->offset = page_offset(wdata->pages[0]); |
1821 | wdata->marshal_iov = cifs_writepages_marshal_iov; | ||
1794 | 1822 | ||
1795 | do { | 1823 | do { |
1796 | if (wdata->cfile != NULL) | 1824 | if (wdata->cfile != NULL) |
@@ -1802,6 +1830,7 @@ retry: | |||
1802 | rc = -EBADF; | 1830 | rc = -EBADF; |
1803 | break; | 1831 | break; |
1804 | } | 1832 | } |
1833 | wdata->pid = wdata->cfile->pid; | ||
1805 | rc = cifs_async_writev(wdata); | 1834 | rc = cifs_async_writev(wdata); |
1806 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); | 1835 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); |
1807 | 1836 | ||
@@ -2043,7 +2072,7 @@ cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) | |||
2043 | unsigned long i; | 2072 | unsigned long i; |
2044 | 2073 | ||
2045 | for (i = 0; i < num_pages; i++) { | 2074 | for (i = 0; i < num_pages; i++) { |
2046 | pages[i] = alloc_page(__GFP_HIGHMEM); | 2075 | pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); |
2047 | if (!pages[i]) { | 2076 | if (!pages[i]) { |
2048 | /* | 2077 | /* |
2049 | * save number of pages we have already allocated and | 2078 | * save number of pages we have already allocated and |
@@ -2051,15 +2080,14 @@ cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) | |||
2051 | */ | 2080 | */ |
2052 | num_pages = i; | 2081 | num_pages = i; |
2053 | rc = -ENOMEM; | 2082 | rc = -ENOMEM; |
2054 | goto error; | 2083 | break; |
2055 | } | 2084 | } |
2056 | } | 2085 | } |
2057 | 2086 | ||
2058 | return rc; | 2087 | if (rc) { |
2059 | 2088 | for (i = 0; i < num_pages; i++) | |
2060 | error: | 2089 | put_page(pages[i]); |
2061 | for (i = 0; i < num_pages; i++) | 2090 | } |
2062 | put_page(pages[i]); | ||
2063 | return rc; | 2091 | return rc; |
2064 | } | 2092 | } |
2065 | 2093 | ||
@@ -2070,9 +2098,7 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | |||
2070 | size_t clen; | 2098 | size_t clen; |
2071 | 2099 | ||
2072 | clen = min_t(const size_t, len, wsize); | 2100 | clen = min_t(const size_t, len, wsize); |
2073 | num_pages = clen / PAGE_CACHE_SIZE; | 2101 | num_pages = DIV_ROUND_UP(clen, PAGE_SIZE); |
2074 | if (clen % PAGE_CACHE_SIZE) | ||
2075 | num_pages++; | ||
2076 | 2102 | ||
2077 | if (cur_len) | 2103 | if (cur_len) |
2078 | *cur_len = clen; | 2104 | *cur_len = clen; |
@@ -2080,24 +2106,79 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | |||
2080 | return num_pages; | 2106 | return num_pages; |
2081 | } | 2107 | } |
2082 | 2108 | ||
2109 | static void | ||
2110 | cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) | ||
2111 | { | ||
2112 | int i; | ||
2113 | size_t bytes = wdata->bytes; | ||
2114 | |||
2115 | /* marshal up the pages into iov array */ | ||
2116 | for (i = 0; i < wdata->nr_pages; i++) { | ||
2117 | iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE); | ||
2118 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
2119 | bytes -= iov[i + 1].iov_len; | ||
2120 | } | ||
2121 | } | ||
2122 | |||
2123 | static void | ||
2124 | cifs_uncached_writev_complete(struct work_struct *work) | ||
2125 | { | ||
2126 | int i; | ||
2127 | struct cifs_writedata *wdata = container_of(work, | ||
2128 | struct cifs_writedata, work); | ||
2129 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
2130 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
2131 | |||
2132 | spin_lock(&inode->i_lock); | ||
2133 | cifs_update_eof(cifsi, wdata->offset, wdata->bytes); | ||
2134 | if (cifsi->server_eof > inode->i_size) | ||
2135 | i_size_write(inode, cifsi->server_eof); | ||
2136 | spin_unlock(&inode->i_lock); | ||
2137 | |||
2138 | complete(&wdata->done); | ||
2139 | |||
2140 | if (wdata->result != -EAGAIN) { | ||
2141 | for (i = 0; i < wdata->nr_pages; i++) | ||
2142 | put_page(wdata->pages[i]); | ||
2143 | } | ||
2144 | |||
2145 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
2146 | } | ||
2147 | |||
2148 | /* attempt to send write to server, retry on any -EAGAIN errors */ | ||
2149 | static int | ||
2150 | cifs_uncached_retry_writev(struct cifs_writedata *wdata) | ||
2151 | { | ||
2152 | int rc; | ||
2153 | |||
2154 | do { | ||
2155 | if (wdata->cfile->invalidHandle) { | ||
2156 | rc = cifs_reopen_file(wdata->cfile, false); | ||
2157 | if (rc != 0) | ||
2158 | continue; | ||
2159 | } | ||
2160 | rc = cifs_async_writev(wdata); | ||
2161 | } while (rc == -EAGAIN); | ||
2162 | |||
2163 | return rc; | ||
2164 | } | ||
2165 | |||
2083 | static ssize_t | 2166 | static ssize_t |
2084 | cifs_iovec_write(struct file *file, const struct iovec *iov, | 2167 | cifs_iovec_write(struct file *file, const struct iovec *iov, |
2085 | unsigned long nr_segs, loff_t *poffset) | 2168 | unsigned long nr_segs, loff_t *poffset) |
2086 | { | 2169 | { |
2087 | unsigned int written; | 2170 | unsigned long nr_pages, i; |
2088 | unsigned long num_pages, npages, i; | ||
2089 | size_t copied, len, cur_len; | 2171 | size_t copied, len, cur_len; |
2090 | ssize_t total_written = 0; | 2172 | ssize_t total_written = 0; |
2091 | struct kvec *to_send; | 2173 | loff_t offset = *poffset; |
2092 | struct page **pages; | ||
2093 | struct iov_iter it; | 2174 | struct iov_iter it; |
2094 | struct inode *inode; | ||
2095 | struct cifsFileInfo *open_file; | 2175 | struct cifsFileInfo *open_file; |
2096 | struct cifs_tcon *pTcon; | 2176 | struct cifs_tcon *tcon; |
2097 | struct cifs_sb_info *cifs_sb; | 2177 | struct cifs_sb_info *cifs_sb; |
2098 | struct cifs_io_parms io_parms; | 2178 | struct cifs_writedata *wdata, *tmp; |
2099 | int xid, rc; | 2179 | struct list_head wdata_list; |
2100 | __u32 pid; | 2180 | int rc; |
2181 | pid_t pid; | ||
2101 | 2182 | ||
2102 | len = iov_length(iov, nr_segs); | 2183 | len = iov_length(iov, nr_segs); |
2103 | if (!len) | 2184 | if (!len) |
@@ -2107,103 +2188,103 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
2107 | if (rc) | 2188 | if (rc) |
2108 | return rc; | 2189 | return rc; |
2109 | 2190 | ||
2191 | INIT_LIST_HEAD(&wdata_list); | ||
2110 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2192 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2111 | num_pages = get_numpages(cifs_sb->wsize, len, &cur_len); | ||
2112 | |||
2113 | pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL); | ||
2114 | if (!pages) | ||
2115 | return -ENOMEM; | ||
2116 | |||
2117 | to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL); | ||
2118 | if (!to_send) { | ||
2119 | kfree(pages); | ||
2120 | return -ENOMEM; | ||
2121 | } | ||
2122 | |||
2123 | rc = cifs_write_allocate_pages(pages, num_pages); | ||
2124 | if (rc) { | ||
2125 | kfree(pages); | ||
2126 | kfree(to_send); | ||
2127 | return rc; | ||
2128 | } | ||
2129 | |||
2130 | xid = GetXid(); | ||
2131 | open_file = file->private_data; | 2193 | open_file = file->private_data; |
2194 | tcon = tlink_tcon(open_file->tlink); | ||
2132 | 2195 | ||
2133 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2196 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
2134 | pid = open_file->pid; | 2197 | pid = open_file->pid; |
2135 | else | 2198 | else |
2136 | pid = current->tgid; | 2199 | pid = current->tgid; |
2137 | 2200 | ||
2138 | pTcon = tlink_tcon(open_file->tlink); | ||
2139 | inode = file->f_path.dentry->d_inode; | ||
2140 | |||
2141 | iov_iter_init(&it, iov, nr_segs, len, 0); | 2201 | iov_iter_init(&it, iov, nr_segs, len, 0); |
2142 | npages = num_pages; | ||
2143 | |||
2144 | do { | 2202 | do { |
2145 | size_t save_len = cur_len; | 2203 | size_t save_len; |
2146 | for (i = 0; i < npages; i++) { | 2204 | |
2147 | copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE); | 2205 | nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len); |
2148 | copied = iov_iter_copy_from_user(pages[i], &it, 0, | 2206 | wdata = cifs_writedata_alloc(nr_pages, |
2149 | copied); | 2207 | cifs_uncached_writev_complete); |
2208 | if (!wdata) { | ||
2209 | rc = -ENOMEM; | ||
2210 | break; | ||
2211 | } | ||
2212 | |||
2213 | rc = cifs_write_allocate_pages(wdata->pages, nr_pages); | ||
2214 | if (rc) { | ||
2215 | kfree(wdata); | ||
2216 | break; | ||
2217 | } | ||
2218 | |||
2219 | save_len = cur_len; | ||
2220 | for (i = 0; i < nr_pages; i++) { | ||
2221 | copied = min_t(const size_t, cur_len, PAGE_SIZE); | ||
2222 | copied = iov_iter_copy_from_user(wdata->pages[i], &it, | ||
2223 | 0, copied); | ||
2150 | cur_len -= copied; | 2224 | cur_len -= copied; |
2151 | iov_iter_advance(&it, copied); | 2225 | iov_iter_advance(&it, copied); |
2152 | to_send[i+1].iov_base = kmap(pages[i]); | ||
2153 | to_send[i+1].iov_len = copied; | ||
2154 | } | 2226 | } |
2155 | |||
2156 | cur_len = save_len - cur_len; | 2227 | cur_len = save_len - cur_len; |
2157 | 2228 | ||
2158 | do { | 2229 | wdata->sync_mode = WB_SYNC_ALL; |
2159 | if (open_file->invalidHandle) { | 2230 | wdata->nr_pages = nr_pages; |
2160 | rc = cifs_reopen_file(open_file, false); | 2231 | wdata->offset = (__u64)offset; |
2161 | if (rc != 0) | 2232 | wdata->cfile = cifsFileInfo_get(open_file); |
2162 | break; | 2233 | wdata->pid = pid; |
2163 | } | 2234 | wdata->bytes = cur_len; |
2164 | io_parms.netfid = open_file->netfid; | 2235 | wdata->marshal_iov = cifs_uncached_marshal_iov; |
2165 | io_parms.pid = pid; | 2236 | rc = cifs_uncached_retry_writev(wdata); |
2166 | io_parms.tcon = pTcon; | 2237 | if (rc) { |
2167 | io_parms.offset = *poffset; | 2238 | kref_put(&wdata->refcount, cifs_writedata_release); |
2168 | io_parms.length = cur_len; | ||
2169 | rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send, | ||
2170 | npages, 0); | ||
2171 | } while (rc == -EAGAIN); | ||
2172 | |||
2173 | for (i = 0; i < npages; i++) | ||
2174 | kunmap(pages[i]); | ||
2175 | |||
2176 | if (written) { | ||
2177 | len -= written; | ||
2178 | total_written += written; | ||
2179 | cifs_update_eof(CIFS_I(inode), *poffset, written); | ||
2180 | *poffset += written; | ||
2181 | } else if (rc < 0) { | ||
2182 | if (!total_written) | ||
2183 | total_written = rc; | ||
2184 | break; | 2239 | break; |
2185 | } | 2240 | } |
2186 | 2241 | ||
2187 | /* get length and number of kvecs of the next write */ | 2242 | list_add_tail(&wdata->list, &wdata_list); |
2188 | npages = get_numpages(cifs_sb->wsize, len, &cur_len); | 2243 | offset += cur_len; |
2244 | len -= cur_len; | ||
2189 | } while (len > 0); | 2245 | } while (len > 0); |
2190 | 2246 | ||
2191 | if (total_written > 0) { | 2247 | /* |
2192 | spin_lock(&inode->i_lock); | 2248 | * If at least one write was successfully sent, then discard any rc |
2193 | if (*poffset > inode->i_size) | 2249 | * value from the later writes. If the other write succeeds, then |
2194 | i_size_write(inode, *poffset); | 2250 | * we'll end up returning whatever was written. If it fails, then |
2195 | spin_unlock(&inode->i_lock); | 2251 | * we'll get a new rc value from that. |
2252 | */ | ||
2253 | if (!list_empty(&wdata_list)) | ||
2254 | rc = 0; | ||
2255 | |||
2256 | /* | ||
2257 | * Wait for and collect replies for any successful sends in order of | ||
2258 | * increasing offset. Once an error is hit or we get a fatal signal | ||
2259 | * while waiting, then return without waiting for any more replies. | ||
2260 | */ | ||
2261 | restart_loop: | ||
2262 | list_for_each_entry_safe(wdata, tmp, &wdata_list, list) { | ||
2263 | if (!rc) { | ||
2264 | /* FIXME: freezable too? */ | ||
2265 | rc = wait_for_completion_killable(&wdata->done); | ||
2266 | if (rc) | ||
2267 | rc = -EINTR; | ||
2268 | else if (wdata->result) | ||
2269 | rc = wdata->result; | ||
2270 | else | ||
2271 | total_written += wdata->bytes; | ||
2272 | |||
2273 | /* resend call if it's a retryable error */ | ||
2274 | if (rc == -EAGAIN) { | ||
2275 | rc = cifs_uncached_retry_writev(wdata); | ||
2276 | goto restart_loop; | ||
2277 | } | ||
2278 | } | ||
2279 | list_del_init(&wdata->list); | ||
2280 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
2196 | } | 2281 | } |
2197 | 2282 | ||
2198 | cifs_stats_bytes_written(pTcon, total_written); | 2283 | if (total_written > 0) |
2199 | mark_inode_dirty_sync(inode); | 2284 | *poffset += total_written; |
2200 | 2285 | ||
2201 | for (i = 0; i < num_pages; i++) | 2286 | cifs_stats_bytes_written(tcon, total_written); |
2202 | put_page(pages[i]); | 2287 | return total_written ? total_written : (ssize_t)rc; |
2203 | kfree(to_send); | ||
2204 | kfree(pages); | ||
2205 | FreeXid(xid); | ||
2206 | return total_written; | ||
2207 | } | 2288 | } |
2208 | 2289 | ||
2209 | ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | 2290 | ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index c273c12de98e..c29d1aa2c54f 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -213,55 +213,62 @@ cifs_small_buf_release(void *buf_to_free) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | /* | 215 | /* |
216 | Find a free multiplex id (SMB mid). Otherwise there could be | 216 | * Find a free multiplex id (SMB mid). Otherwise there could be |
217 | mid collisions which might cause problems, demultiplexing the | 217 | * mid collisions which might cause problems, demultiplexing the |
218 | wrong response to this request. Multiplex ids could collide if | 218 | * wrong response to this request. Multiplex ids could collide if |
219 | one of a series requests takes much longer than the others, or | 219 | * one of a series requests takes much longer than the others, or |
220 | if a very large number of long lived requests (byte range | 220 | * if a very large number of long lived requests (byte range |
221 | locks or FindNotify requests) are pending. No more than | 221 | * locks or FindNotify requests) are pending. No more than |
222 | 64K-1 requests can be outstanding at one time. If no | 222 | * 64K-1 requests can be outstanding at one time. If no |
223 | mids are available, return zero. A future optimization | 223 | * mids are available, return zero. A future optimization |
224 | could make the combination of mids and uid the key we use | 224 | * could make the combination of mids and uid the key we use |
225 | to demultiplex on (rather than mid alone). | 225 | * to demultiplex on (rather than mid alone). |
226 | In addition to the above check, the cifs demultiplex | 226 | * In addition to the above check, the cifs demultiplex |
227 | code already used the command code as a secondary | 227 | * code already used the command code as a secondary |
228 | check of the frame and if signing is negotiated the | 228 | * check of the frame and if signing is negotiated the |
229 | response would be discarded if the mid were the same | 229 | * response would be discarded if the mid were the same |
230 | but the signature was wrong. Since the mid is not put in the | 230 | * but the signature was wrong. Since the mid is not put in the |
231 | pending queue until later (when it is about to be dispatched) | 231 | * pending queue until later (when it is about to be dispatched) |
232 | we do have to limit the number of outstanding requests | 232 | * we do have to limit the number of outstanding requests |
233 | to somewhat less than 64K-1 although it is hard to imagine | 233 | * to somewhat less than 64K-1 although it is hard to imagine |
234 | so many threads being in the vfs at one time. | 234 | * so many threads being in the vfs at one time. |
235 | */ | 235 | */ |
236 | __u16 GetNextMid(struct TCP_Server_Info *server) | 236 | __u64 GetNextMid(struct TCP_Server_Info *server) |
237 | { | 237 | { |
238 | __u16 mid = 0; | 238 | __u64 mid = 0; |
239 | __u16 last_mid; | 239 | __u16 last_mid, cur_mid; |
240 | bool collision; | 240 | bool collision; |
241 | 241 | ||
242 | spin_lock(&GlobalMid_Lock); | 242 | spin_lock(&GlobalMid_Lock); |
243 | last_mid = server->CurrentMid; /* we do not want to loop forever */ | 243 | |
244 | server->CurrentMid++; | 244 | /* mid is 16 bit only for CIFS/SMB */ |
245 | /* This nested loop looks more expensive than it is. | 245 | cur_mid = (__u16)((server->CurrentMid) & 0xffff); |
246 | In practice the list of pending requests is short, | 246 | /* we do not want to loop forever */ |
247 | fewer than 50, and the mids are likely to be unique | 247 | last_mid = cur_mid; |
248 | on the first pass through the loop unless some request | 248 | cur_mid++; |
249 | takes longer than the 64 thousand requests before it | 249 | |
250 | (and it would also have to have been a request that | 250 | /* |
251 | did not time out) */ | 251 | * This nested loop looks more expensive than it is. |
252 | while (server->CurrentMid != last_mid) { | 252 | * In practice the list of pending requests is short, |
253 | * fewer than 50, and the mids are likely to be unique | ||
254 | * on the first pass through the loop unless some request | ||
255 | * takes longer than the 64 thousand requests before it | ||
256 | * (and it would also have to have been a request that | ||
257 | * did not time out). | ||
258 | */ | ||
259 | while (cur_mid != last_mid) { | ||
253 | struct mid_q_entry *mid_entry; | 260 | struct mid_q_entry *mid_entry; |
254 | unsigned int num_mids; | 261 | unsigned int num_mids; |
255 | 262 | ||
256 | collision = false; | 263 | collision = false; |
257 | if (server->CurrentMid == 0) | 264 | if (cur_mid == 0) |
258 | server->CurrentMid++; | 265 | cur_mid++; |
259 | 266 | ||
260 | num_mids = 0; | 267 | num_mids = 0; |
261 | list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { | 268 | list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { |
262 | ++num_mids; | 269 | ++num_mids; |
263 | if (mid_entry->mid == server->CurrentMid && | 270 | if (mid_entry->mid == cur_mid && |
264 | mid_entry->midState == MID_REQUEST_SUBMITTED) { | 271 | mid_entry->mid_state == MID_REQUEST_SUBMITTED) { |
265 | /* This mid is in use, try a different one */ | 272 | /* This mid is in use, try a different one */ |
266 | collision = true; | 273 | collision = true; |
267 | break; | 274 | break; |
@@ -282,10 +289,11 @@ __u16 GetNextMid(struct TCP_Server_Info *server) | |||
282 | server->tcpStatus = CifsNeedReconnect; | 289 | server->tcpStatus = CifsNeedReconnect; |
283 | 290 | ||
284 | if (!collision) { | 291 | if (!collision) { |
285 | mid = server->CurrentMid; | 292 | mid = (__u64)cur_mid; |
293 | server->CurrentMid = mid; | ||
286 | break; | 294 | break; |
287 | } | 295 | } |
288 | server->CurrentMid++; | 296 | cur_mid++; |
289 | } | 297 | } |
290 | spin_unlock(&GlobalMid_Lock); | 298 | spin_unlock(&GlobalMid_Lock); |
291 | return mid; | 299 | return mid; |
@@ -420,8 +428,10 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid) | |||
420 | } | 428 | } |
421 | 429 | ||
422 | int | 430 | int |
423 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int total_read) | 431 | checkSMB(char *buf, unsigned int total_read) |
424 | { | 432 | { |
433 | struct smb_hdr *smb = (struct smb_hdr *)buf; | ||
434 | __u16 mid = smb->Mid; | ||
425 | __u32 rfclen = be32_to_cpu(smb->smb_buf_length); | 435 | __u32 rfclen = be32_to_cpu(smb->smb_buf_length); |
426 | __u32 clc_len; /* calculated length */ | 436 | __u32 clc_len; /* calculated length */ |
427 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", | 437 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", |
@@ -502,8 +512,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int total_read) | |||
502 | } | 512 | } |
503 | 513 | ||
504 | bool | 514 | bool |
505 | is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | 515 | is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) |
506 | { | 516 | { |
517 | struct smb_hdr *buf = (struct smb_hdr *)buffer; | ||
507 | struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; | 518 | struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; |
508 | struct list_head *tmp, *tmp1, *tmp2; | 519 | struct list_head *tmp, *tmp1, *tmp2; |
509 | struct cifs_ses *ses; | 520 | struct cifs_ses *ses; |
@@ -584,7 +595,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
584 | 595 | ||
585 | cifs_set_oplock_level(pCifsInode, | 596 | cifs_set_oplock_level(pCifsInode, |
586 | pSMB->OplockLevel ? OPLOCK_READ : 0); | 597 | pSMB->OplockLevel ? OPLOCK_READ : 0); |
587 | queue_work(system_nrt_wq, | 598 | queue_work(cifsiod_wq, |
588 | &netfile->oplock_break); | 599 | &netfile->oplock_break); |
589 | netfile->oplock_break_cancelled = false; | 600 | netfile->oplock_break_cancelled = false; |
590 | 601 | ||
@@ -604,16 +615,15 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
604 | } | 615 | } |
605 | 616 | ||
606 | void | 617 | void |
607 | dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | 618 | dump_smb(void *buf, int smb_buf_length) |
608 | { | 619 | { |
609 | int i, j; | 620 | int i, j; |
610 | char debug_line[17]; | 621 | char debug_line[17]; |
611 | unsigned char *buffer; | 622 | unsigned char *buffer = buf; |
612 | 623 | ||
613 | if (traceSMB == 0) | 624 | if (traceSMB == 0) |
614 | return; | 625 | return; |
615 | 626 | ||
616 | buffer = (unsigned char *) smb_buf; | ||
617 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { | 627 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { |
618 | if (i % 8 == 0) { | 628 | if (i % 8 == 0) { |
619 | /* have reached the beginning of line */ | 629 | /* have reached the beginning of line */ |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 73e47e84b61a..dd23a321bdda 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -836,8 +836,9 @@ ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) | |||
836 | } | 836 | } |
837 | 837 | ||
838 | int | 838 | int |
839 | map_smb_to_linux_error(struct smb_hdr *smb, bool logErr) | 839 | map_smb_to_linux_error(char *buf, bool logErr) |
840 | { | 840 | { |
841 | struct smb_hdr *smb = (struct smb_hdr *)buf; | ||
841 | unsigned int i; | 842 | unsigned int i; |
842 | int rc = -EIO; /* if transport error smb error may not be set */ | 843 | int rc = -EIO; /* if transport error smb error may not be set */ |
843 | __u8 smberrclass; | 844 | __u8 smberrclass; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 310918b6fcb4..0961336513d5 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -60,8 +60,8 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | |||
60 | memset(temp, 0, sizeof(struct mid_q_entry)); | 60 | memset(temp, 0, sizeof(struct mid_q_entry)); |
61 | temp->mid = smb_buffer->Mid; /* always LE */ | 61 | temp->mid = smb_buffer->Mid; /* always LE */ |
62 | temp->pid = current->pid; | 62 | temp->pid = current->pid; |
63 | temp->command = smb_buffer->Command; | 63 | temp->command = cpu_to_le16(smb_buffer->Command); |
64 | cFYI(1, "For smb_command %d", temp->command); | 64 | cFYI(1, "For smb_command %d", smb_buffer->Command); |
65 | /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ | 65 | /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ |
66 | /* when mid allocated can be before when sent */ | 66 | /* when mid allocated can be before when sent */ |
67 | temp->when_alloc = jiffies; | 67 | temp->when_alloc = jiffies; |
@@ -75,7 +75,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | |||
75 | } | 75 | } |
76 | 76 | ||
77 | atomic_inc(&midCount); | 77 | atomic_inc(&midCount); |
78 | temp->midState = MID_REQUEST_ALLOCATED; | 78 | temp->mid_state = MID_REQUEST_ALLOCATED; |
79 | return temp; | 79 | return temp; |
80 | } | 80 | } |
81 | 81 | ||
@@ -85,9 +85,9 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) | |||
85 | #ifdef CONFIG_CIFS_STATS2 | 85 | #ifdef CONFIG_CIFS_STATS2 |
86 | unsigned long now; | 86 | unsigned long now; |
87 | #endif | 87 | #endif |
88 | midEntry->midState = MID_FREE; | 88 | midEntry->mid_state = MID_FREE; |
89 | atomic_dec(&midCount); | 89 | atomic_dec(&midCount); |
90 | if (midEntry->largeBuf) | 90 | if (midEntry->large_buf) |
91 | cifs_buf_release(midEntry->resp_buf); | 91 | cifs_buf_release(midEntry->resp_buf); |
92 | else | 92 | else |
93 | cifs_small_buf_release(midEntry->resp_buf); | 93 | cifs_small_buf_release(midEntry->resp_buf); |
@@ -97,8 +97,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) | |||
97 | something is wrong, unless it is quite a slow link or server */ | 97 | something is wrong, unless it is quite a slow link or server */ |
98 | if ((now - midEntry->when_alloc) > HZ) { | 98 | if ((now - midEntry->when_alloc) > HZ) { |
99 | if ((cifsFYI & CIFS_TIMER) && | 99 | if ((cifsFYI & CIFS_TIMER) && |
100 | (midEntry->command != SMB_COM_LOCKING_ANDX)) { | 100 | (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) { |
101 | printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d", | 101 | printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu", |
102 | midEntry->command, midEntry->mid); | 102 | midEntry->command, midEntry->mid); |
103 | printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n", | 103 | printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n", |
104 | now - midEntry->when_alloc, | 104 | now - midEntry->when_alloc, |
@@ -126,11 +126,11 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
126 | int rc = 0; | 126 | int rc = 0; |
127 | int i = 0; | 127 | int i = 0; |
128 | struct msghdr smb_msg; | 128 | struct msghdr smb_msg; |
129 | struct smb_hdr *smb_buffer = iov[0].iov_base; | 129 | __be32 *buf_len = (__be32 *)(iov[0].iov_base); |
130 | unsigned int len = iov[0].iov_len; | 130 | unsigned int len = iov[0].iov_len; |
131 | unsigned int total_len; | 131 | unsigned int total_len; |
132 | int first_vec = 0; | 132 | int first_vec = 0; |
133 | unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); | 133 | unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); |
134 | struct socket *ssocket = server->ssocket; | 134 | struct socket *ssocket = server->ssocket; |
135 | 135 | ||
136 | if (ssocket == NULL) | 136 | if (ssocket == NULL) |
@@ -150,7 +150,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
150 | total_len += iov[i].iov_len; | 150 | total_len += iov[i].iov_len; |
151 | 151 | ||
152 | cFYI(1, "Sending smb: total_len %d", total_len); | 152 | cFYI(1, "Sending smb: total_len %d", total_len); |
153 | dump_smb(smb_buffer, len); | 153 | dump_smb(iov[0].iov_base, len); |
154 | 154 | ||
155 | i = 0; | 155 | i = 0; |
156 | while (total_len) { | 156 | while (total_len) { |
@@ -158,24 +158,24 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
158 | n_vec - first_vec, total_len); | 158 | n_vec - first_vec, total_len); |
159 | if ((rc == -ENOSPC) || (rc == -EAGAIN)) { | 159 | if ((rc == -ENOSPC) || (rc == -EAGAIN)) { |
160 | i++; | 160 | i++; |
161 | /* if blocking send we try 3 times, since each can block | 161 | /* |
162 | for 5 seconds. For nonblocking we have to try more | 162 | * If blocking send we try 3 times, since each can block |
163 | but wait increasing amounts of time allowing time for | 163 | * for 5 seconds. For nonblocking we have to try more |
164 | socket to clear. The overall time we wait in either | 164 | * but wait increasing amounts of time allowing time for |
165 | case to send on the socket is about 15 seconds. | 165 | * socket to clear. The overall time we wait in either |
166 | Similarly we wait for 15 seconds for | 166 | * case to send on the socket is about 15 seconds. |
167 | a response from the server in SendReceive[2] | 167 | * Similarly we wait for 15 seconds for a response from |
168 | for the server to send a response back for | 168 | * the server in SendReceive[2] for the server to send |
169 | most types of requests (except SMB Write | 169 | * a response back for most types of requests (except |
170 | past end of file which can be slow, and | 170 | * SMB Write past end of file which can be slow, and |
171 | blocking lock operations). NFS waits slightly longer | 171 | * blocking lock operations). NFS waits slightly longer |
172 | than CIFS, but this can make it take longer for | 172 | * than CIFS, but this can make it take longer for |
173 | nonresponsive servers to be detected and 15 seconds | 173 | * nonresponsive servers to be detected and 15 seconds |
174 | is more than enough time for modern networks to | 174 | * is more than enough time for modern networks to |
175 | send a packet. In most cases if we fail to send | 175 | * send a packet. In most cases if we fail to send |
176 | after the retries we will kill the socket and | 176 | * after the retries we will kill the socket and |
177 | reconnect which may clear the network problem. | 177 | * reconnect which may clear the network problem. |
178 | */ | 178 | */ |
179 | if ((i >= 14) || (!server->noblocksnd && (i > 2))) { | 179 | if ((i >= 14) || (!server->noblocksnd && (i > 2))) { |
180 | cERROR(1, "sends on sock %p stuck for 15 seconds", | 180 | cERROR(1, "sends on sock %p stuck for 15 seconds", |
181 | ssocket); | 181 | ssocket); |
@@ -235,9 +235,8 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
235 | else | 235 | else |
236 | rc = 0; | 236 | rc = 0; |
237 | 237 | ||
238 | /* Don't want to modify the buffer as a | 238 | /* Don't want to modify the buffer as a side effect of this call. */ |
239 | side effect of this call. */ | 239 | *buf_len = cpu_to_be32(smb_buf_length); |
240 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length); | ||
241 | 240 | ||
242 | return rc; | 241 | return rc; |
243 | } | 242 | } |
@@ -342,13 +341,40 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) | |||
342 | int error; | 341 | int error; |
343 | 342 | ||
344 | error = wait_event_freezekillable(server->response_q, | 343 | error = wait_event_freezekillable(server->response_q, |
345 | midQ->midState != MID_REQUEST_SUBMITTED); | 344 | midQ->mid_state != MID_REQUEST_SUBMITTED); |
346 | if (error < 0) | 345 | if (error < 0) |
347 | return -ERESTARTSYS; | 346 | return -ERESTARTSYS; |
348 | 347 | ||
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | 350 | ||
351 | static int | ||
352 | cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov, | ||
353 | unsigned int nvec, struct mid_q_entry **ret_mid) | ||
354 | { | ||
355 | int rc; | ||
356 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
357 | struct mid_q_entry *mid; | ||
358 | |||
359 | /* enable signing if server requires it */ | ||
360 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
361 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
362 | |||
363 | mid = AllocMidQEntry(hdr, server); | ||
364 | if (mid == NULL) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | /* put it on the pending_mid_q */ | ||
368 | spin_lock(&GlobalMid_Lock); | ||
369 | list_add_tail(&mid->qhead, &server->pending_mid_q); | ||
370 | spin_unlock(&GlobalMid_Lock); | ||
371 | |||
372 | rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); | ||
373 | if (rc) | ||
374 | delete_mid(mid); | ||
375 | *ret_mid = mid; | ||
376 | return rc; | ||
377 | } | ||
352 | 378 | ||
353 | /* | 379 | /* |
354 | * Send a SMB request and set the callback function in the mid to handle | 380 | * Send a SMB request and set the callback function in the mid to handle |
@@ -361,40 +387,24 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, | |||
361 | { | 387 | { |
362 | int rc; | 388 | int rc; |
363 | struct mid_q_entry *mid; | 389 | struct mid_q_entry *mid; |
364 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
365 | 390 | ||
366 | rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); | 391 | rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); |
367 | if (rc) | 392 | if (rc) |
368 | return rc; | 393 | return rc; |
369 | 394 | ||
370 | /* enable signing if server requires it */ | ||
371 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
372 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
373 | |||
374 | mutex_lock(&server->srv_mutex); | 395 | mutex_lock(&server->srv_mutex); |
375 | mid = AllocMidQEntry(hdr, server); | 396 | rc = cifs_setup_async_request(server, iov, nvec, &mid); |
376 | if (mid == NULL) { | 397 | if (rc) { |
377 | mutex_unlock(&server->srv_mutex); | 398 | mutex_unlock(&server->srv_mutex); |
378 | cifs_add_credits(server, 1); | 399 | cifs_add_credits(server, 1); |
379 | wake_up(&server->request_q); | 400 | wake_up(&server->request_q); |
380 | return -ENOMEM; | 401 | return rc; |
381 | } | ||
382 | |||
383 | /* put it on the pending_mid_q */ | ||
384 | spin_lock(&GlobalMid_Lock); | ||
385 | list_add_tail(&mid->qhead, &server->pending_mid_q); | ||
386 | spin_unlock(&GlobalMid_Lock); | ||
387 | |||
388 | rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); | ||
389 | if (rc) { | ||
390 | mutex_unlock(&server->srv_mutex); | ||
391 | goto out_err; | ||
392 | } | 402 | } |
393 | 403 | ||
394 | mid->receive = receive; | 404 | mid->receive = receive; |
395 | mid->callback = callback; | 405 | mid->callback = callback; |
396 | mid->callback_data = cbdata; | 406 | mid->callback_data = cbdata; |
397 | mid->midState = MID_REQUEST_SUBMITTED; | 407 | mid->mid_state = MID_REQUEST_SUBMITTED; |
398 | 408 | ||
399 | cifs_in_send_inc(server); | 409 | cifs_in_send_inc(server); |
400 | rc = smb_sendv(server, iov, nvec); | 410 | rc = smb_sendv(server, iov, nvec); |
@@ -424,14 +434,14 @@ out_err: | |||
424 | */ | 434 | */ |
425 | int | 435 | int |
426 | SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, | 436 | SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, |
427 | struct smb_hdr *in_buf, int flags) | 437 | char *in_buf, int flags) |
428 | { | 438 | { |
429 | int rc; | 439 | int rc; |
430 | struct kvec iov[1]; | 440 | struct kvec iov[1]; |
431 | int resp_buf_type; | 441 | int resp_buf_type; |
432 | 442 | ||
433 | iov[0].iov_base = (char *)in_buf; | 443 | iov[0].iov_base = in_buf; |
434 | iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; | 444 | iov[0].iov_len = get_rfc1002_length(in_buf) + 4; |
435 | flags |= CIFS_NO_RESP; | 445 | flags |= CIFS_NO_RESP; |
436 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | 446 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); |
437 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); | 447 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); |
@@ -444,11 +454,11 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
444 | { | 454 | { |
445 | int rc = 0; | 455 | int rc = 0; |
446 | 456 | ||
447 | cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command, | 457 | cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__, |
448 | mid->mid, mid->midState); | 458 | le16_to_cpu(mid->command), mid->mid, mid->mid_state); |
449 | 459 | ||
450 | spin_lock(&GlobalMid_Lock); | 460 | spin_lock(&GlobalMid_Lock); |
451 | switch (mid->midState) { | 461 | switch (mid->mid_state) { |
452 | case MID_RESPONSE_RECEIVED: | 462 | case MID_RESPONSE_RECEIVED: |
453 | spin_unlock(&GlobalMid_Lock); | 463 | spin_unlock(&GlobalMid_Lock); |
454 | return rc; | 464 | return rc; |
@@ -463,8 +473,8 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
463 | break; | 473 | break; |
464 | default: | 474 | default: |
465 | list_del_init(&mid->qhead); | 475 | list_del_init(&mid->qhead); |
466 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, | 476 | cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__, |
467 | mid->mid, mid->midState); | 477 | mid->mid, mid->mid_state); |
468 | rc = -EIO; | 478 | rc = -EIO; |
469 | } | 479 | } |
470 | spin_unlock(&GlobalMid_Lock); | 480 | spin_unlock(&GlobalMid_Lock); |
@@ -514,7 +524,7 @@ int | |||
514 | cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | 524 | cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, |
515 | bool log_error) | 525 | bool log_error) |
516 | { | 526 | { |
517 | unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4; | 527 | unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; |
518 | 528 | ||
519 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); | 529 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); |
520 | 530 | ||
@@ -534,6 +544,24 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
534 | return map_smb_to_linux_error(mid->resp_buf, log_error); | 544 | return map_smb_to_linux_error(mid->resp_buf, log_error); |
535 | } | 545 | } |
536 | 546 | ||
547 | static int | ||
548 | cifs_setup_request(struct cifs_ses *ses, struct kvec *iov, | ||
549 | unsigned int nvec, struct mid_q_entry **ret_mid) | ||
550 | { | ||
551 | int rc; | ||
552 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
553 | struct mid_q_entry *mid; | ||
554 | |||
555 | rc = allocate_mid(ses, hdr, &mid); | ||
556 | if (rc) | ||
557 | return rc; | ||
558 | rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number); | ||
559 | if (rc) | ||
560 | delete_mid(mid); | ||
561 | *ret_mid = mid; | ||
562 | return rc; | ||
563 | } | ||
564 | |||
537 | int | 565 | int |
538 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, | 566 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, |
539 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, | 567 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, |
@@ -542,55 +570,53 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
542 | int rc = 0; | 570 | int rc = 0; |
543 | int long_op; | 571 | int long_op; |
544 | struct mid_q_entry *midQ; | 572 | struct mid_q_entry *midQ; |
545 | struct smb_hdr *in_buf = iov[0].iov_base; | 573 | char *buf = iov[0].iov_base; |
546 | 574 | ||
547 | long_op = flags & CIFS_TIMEOUT_MASK; | 575 | long_op = flags & CIFS_TIMEOUT_MASK; |
548 | 576 | ||
549 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ | 577 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ |
550 | 578 | ||
551 | if ((ses == NULL) || (ses->server == NULL)) { | 579 | if ((ses == NULL) || (ses->server == NULL)) { |
552 | cifs_small_buf_release(in_buf); | 580 | cifs_small_buf_release(buf); |
553 | cERROR(1, "Null session"); | 581 | cERROR(1, "Null session"); |
554 | return -EIO; | 582 | return -EIO; |
555 | } | 583 | } |
556 | 584 | ||
557 | if (ses->server->tcpStatus == CifsExiting) { | 585 | if (ses->server->tcpStatus == CifsExiting) { |
558 | cifs_small_buf_release(in_buf); | 586 | cifs_small_buf_release(buf); |
559 | return -ENOENT; | 587 | return -ENOENT; |
560 | } | 588 | } |
561 | 589 | ||
562 | /* Ensure that we do not send more than 50 overlapping requests | 590 | /* |
563 | to the same server. We may make this configurable later or | 591 | * Ensure that we do not send more than 50 overlapping requests |
564 | use ses->maxReq */ | 592 | * to the same server. We may make this configurable later or |
593 | * use ses->maxReq. | ||
594 | */ | ||
565 | 595 | ||
566 | rc = wait_for_free_request(ses->server, long_op); | 596 | rc = wait_for_free_request(ses->server, long_op); |
567 | if (rc) { | 597 | if (rc) { |
568 | cifs_small_buf_release(in_buf); | 598 | cifs_small_buf_release(buf); |
569 | return rc; | 599 | return rc; |
570 | } | 600 | } |
571 | 601 | ||
572 | /* make sure that we sign in the same order that we send on this socket | 602 | /* |
573 | and avoid races inside tcp sendmsg code that could cause corruption | 603 | * Make sure that we sign in the same order that we send on this socket |
574 | of smb data */ | 604 | * and avoid races inside tcp sendmsg code that could cause corruption |
605 | * of smb data. | ||
606 | */ | ||
575 | 607 | ||
576 | mutex_lock(&ses->server->srv_mutex); | 608 | mutex_lock(&ses->server->srv_mutex); |
577 | 609 | ||
578 | rc = allocate_mid(ses, in_buf, &midQ); | 610 | rc = cifs_setup_request(ses, iov, n_vec, &midQ); |
579 | if (rc) { | 611 | if (rc) { |
580 | mutex_unlock(&ses->server->srv_mutex); | 612 | mutex_unlock(&ses->server->srv_mutex); |
581 | cifs_small_buf_release(in_buf); | 613 | cifs_small_buf_release(buf); |
582 | /* Update # of requests on wire to server */ | 614 | /* Update # of requests on wire to server */ |
583 | cifs_add_credits(ses->server, 1); | 615 | cifs_add_credits(ses->server, 1); |
584 | return rc; | 616 | return rc; |
585 | } | 617 | } |
586 | rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); | ||
587 | if (rc) { | ||
588 | mutex_unlock(&ses->server->srv_mutex); | ||
589 | cifs_small_buf_release(in_buf); | ||
590 | goto out; | ||
591 | } | ||
592 | 618 | ||
593 | midQ->midState = MID_REQUEST_SUBMITTED; | 619 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
594 | cifs_in_send_inc(ses->server); | 620 | cifs_in_send_inc(ses->server); |
595 | rc = smb_sendv(ses->server, iov, n_vec); | 621 | rc = smb_sendv(ses->server, iov, n_vec); |
596 | cifs_in_send_dec(ses->server); | 622 | cifs_in_send_dec(ses->server); |
@@ -599,30 +625,30 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
599 | mutex_unlock(&ses->server->srv_mutex); | 625 | mutex_unlock(&ses->server->srv_mutex); |
600 | 626 | ||
601 | if (rc < 0) { | 627 | if (rc < 0) { |
602 | cifs_small_buf_release(in_buf); | 628 | cifs_small_buf_release(buf); |
603 | goto out; | 629 | goto out; |
604 | } | 630 | } |
605 | 631 | ||
606 | if (long_op == CIFS_ASYNC_OP) { | 632 | if (long_op == CIFS_ASYNC_OP) { |
607 | cifs_small_buf_release(in_buf); | 633 | cifs_small_buf_release(buf); |
608 | goto out; | 634 | goto out; |
609 | } | 635 | } |
610 | 636 | ||
611 | rc = wait_for_response(ses->server, midQ); | 637 | rc = wait_for_response(ses->server, midQ); |
612 | if (rc != 0) { | 638 | if (rc != 0) { |
613 | send_nt_cancel(ses->server, in_buf, midQ); | 639 | send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ); |
614 | spin_lock(&GlobalMid_Lock); | 640 | spin_lock(&GlobalMid_Lock); |
615 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 641 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
616 | midQ->callback = DeleteMidQEntry; | 642 | midQ->callback = DeleteMidQEntry; |
617 | spin_unlock(&GlobalMid_Lock); | 643 | spin_unlock(&GlobalMid_Lock); |
618 | cifs_small_buf_release(in_buf); | 644 | cifs_small_buf_release(buf); |
619 | cifs_add_credits(ses->server, 1); | 645 | cifs_add_credits(ses->server, 1); |
620 | return rc; | 646 | return rc; |
621 | } | 647 | } |
622 | spin_unlock(&GlobalMid_Lock); | 648 | spin_unlock(&GlobalMid_Lock); |
623 | } | 649 | } |
624 | 650 | ||
625 | cifs_small_buf_release(in_buf); | 651 | cifs_small_buf_release(buf); |
626 | 652 | ||
627 | rc = cifs_sync_mid_result(midQ, ses->server); | 653 | rc = cifs_sync_mid_result(midQ, ses->server); |
628 | if (rc != 0) { | 654 | if (rc != 0) { |
@@ -630,15 +656,16 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
630 | return rc; | 656 | return rc; |
631 | } | 657 | } |
632 | 658 | ||
633 | if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) { | 659 | if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { |
634 | rc = -EIO; | 660 | rc = -EIO; |
635 | cFYI(1, "Bad MID state?"); | 661 | cFYI(1, "Bad MID state?"); |
636 | goto out; | 662 | goto out; |
637 | } | 663 | } |
638 | 664 | ||
639 | iov[0].iov_base = (char *)midQ->resp_buf; | 665 | buf = (char *)midQ->resp_buf; |
640 | iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4; | 666 | iov[0].iov_base = buf; |
641 | if (midQ->largeBuf) | 667 | iov[0].iov_len = get_rfc1002_length(buf) + 4; |
668 | if (midQ->large_buf) | ||
642 | *pRespBufType = CIFS_LARGE_BUFFER; | 669 | *pRespBufType = CIFS_LARGE_BUFFER; |
643 | else | 670 | else |
644 | *pRespBufType = CIFS_SMALL_BUFFER; | 671 | *pRespBufType = CIFS_SMALL_BUFFER; |
@@ -710,7 +737,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
710 | goto out; | 737 | goto out; |
711 | } | 738 | } |
712 | 739 | ||
713 | midQ->midState = MID_REQUEST_SUBMITTED; | 740 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
714 | 741 | ||
715 | cifs_in_send_inc(ses->server); | 742 | cifs_in_send_inc(ses->server); |
716 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); | 743 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
@@ -728,7 +755,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
728 | if (rc != 0) { | 755 | if (rc != 0) { |
729 | send_nt_cancel(ses->server, in_buf, midQ); | 756 | send_nt_cancel(ses->server, in_buf, midQ); |
730 | spin_lock(&GlobalMid_Lock); | 757 | spin_lock(&GlobalMid_Lock); |
731 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 758 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
732 | /* no longer considered to be "in-flight" */ | 759 | /* no longer considered to be "in-flight" */ |
733 | midQ->callback = DeleteMidQEntry; | 760 | midQ->callback = DeleteMidQEntry; |
734 | spin_unlock(&GlobalMid_Lock); | 761 | spin_unlock(&GlobalMid_Lock); |
@@ -745,13 +772,13 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
745 | } | 772 | } |
746 | 773 | ||
747 | if (!midQ->resp_buf || !out_buf || | 774 | if (!midQ->resp_buf || !out_buf || |
748 | midQ->midState != MID_RESPONSE_RECEIVED) { | 775 | midQ->mid_state != MID_RESPONSE_RECEIVED) { |
749 | rc = -EIO; | 776 | rc = -EIO; |
750 | cERROR(1, "Bad MID state?"); | 777 | cERROR(1, "Bad MID state?"); |
751 | goto out; | 778 | goto out; |
752 | } | 779 | } |
753 | 780 | ||
754 | *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length); | 781 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); |
755 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); | 782 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
756 | rc = cifs_check_receive(midQ, ses->server, 0); | 783 | rc = cifs_check_receive(midQ, ses->server, 0); |
757 | out: | 784 | out: |
@@ -844,7 +871,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
844 | return rc; | 871 | return rc; |
845 | } | 872 | } |
846 | 873 | ||
847 | midQ->midState = MID_REQUEST_SUBMITTED; | 874 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
848 | cifs_in_send_inc(ses->server); | 875 | cifs_in_send_inc(ses->server); |
849 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); | 876 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
850 | cifs_in_send_dec(ses->server); | 877 | cifs_in_send_dec(ses->server); |
@@ -858,13 +885,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
858 | 885 | ||
859 | /* Wait for a reply - allow signals to interrupt. */ | 886 | /* Wait for a reply - allow signals to interrupt. */ |
860 | rc = wait_event_interruptible(ses->server->response_q, | 887 | rc = wait_event_interruptible(ses->server->response_q, |
861 | (!(midQ->midState == MID_REQUEST_SUBMITTED)) || | 888 | (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || |
862 | ((ses->server->tcpStatus != CifsGood) && | 889 | ((ses->server->tcpStatus != CifsGood) && |
863 | (ses->server->tcpStatus != CifsNew))); | 890 | (ses->server->tcpStatus != CifsNew))); |
864 | 891 | ||
865 | /* Were we interrupted by a signal ? */ | 892 | /* Were we interrupted by a signal ? */ |
866 | if ((rc == -ERESTARTSYS) && | 893 | if ((rc == -ERESTARTSYS) && |
867 | (midQ->midState == MID_REQUEST_SUBMITTED) && | 894 | (midQ->mid_state == MID_REQUEST_SUBMITTED) && |
868 | ((ses->server->tcpStatus == CifsGood) || | 895 | ((ses->server->tcpStatus == CifsGood) || |
869 | (ses->server->tcpStatus == CifsNew))) { | 896 | (ses->server->tcpStatus == CifsNew))) { |
870 | 897 | ||
@@ -894,7 +921,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
894 | if (rc) { | 921 | if (rc) { |
895 | send_nt_cancel(ses->server, in_buf, midQ); | 922 | send_nt_cancel(ses->server, in_buf, midQ); |
896 | spin_lock(&GlobalMid_Lock); | 923 | spin_lock(&GlobalMid_Lock); |
897 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 924 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
898 | /* no longer considered to be "in-flight" */ | 925 | /* no longer considered to be "in-flight" */ |
899 | midQ->callback = DeleteMidQEntry; | 926 | midQ->callback = DeleteMidQEntry; |
900 | spin_unlock(&GlobalMid_Lock); | 927 | spin_unlock(&GlobalMid_Lock); |
@@ -912,13 +939,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
912 | return rc; | 939 | return rc; |
913 | 940 | ||
914 | /* rcvd frame is ok */ | 941 | /* rcvd frame is ok */ |
915 | if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) { | 942 | if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { |
916 | rc = -EIO; | 943 | rc = -EIO; |
917 | cERROR(1, "Bad MID state?"); | 944 | cERROR(1, "Bad MID state?"); |
918 | goto out; | 945 | goto out; |
919 | } | 946 | } |
920 | 947 | ||
921 | *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length); | 948 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); |
922 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); | 949 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
923 | rc = cifs_check_receive(midQ, ses->server, 0); | 950 | rc = cifs_check_receive(midQ, ses->server, 0); |
924 | out: | 951 | out: |