aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/README12
-rw-r--r--fs/cifs/cifs_debug.c51
-rw-r--r--fs/cifs/cifsacl.h38
-rw-r--r--fs/cifs/cifsencrypt.c55
-rw-r--r--fs/cifs/cifsfs.c28
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h16
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h20
-rw-r--r--fs/cifs/cifssmb.c98
-rw-r--r--fs/cifs/connect.c55
-rw-r--r--fs/cifs/dir.c8
-rw-r--r--fs/cifs/file.c68
-rw-r--r--fs/cifs/inode.c9
-rw-r--r--fs/cifs/misc.c17
-rw-r--r--fs/cifs/readdir.c17
-rw-r--r--fs/cifs/rfc1002pdu.h4
-rw-r--r--fs/cifs/transport.c39
19 files changed, 399 insertions, 153 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 943ef9b82244..1d2137561c55 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,8 @@
1Version 1.40
2------------
3Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
4of readpages by eliminating one extra memcpy.
5
1Version 1.39 6Version 1.39
2------------ 7------------
3Defer close of a file handle slightly if pending writes depend on that handle 8Defer close of a file handle slightly if pending writes depend on that handle
@@ -7,6 +12,8 @@ Fix SFU style symlinks and mknod needed for servers which do not support the
7CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative 12CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
8dentries so files that the client sees as deleted but that later get created 13dentries so files that the client sees as deleted but that later get created
9on the server will be recognized. Add client side permission check on setattr. 14on the server will be recognized. Add client side permission check on setattr.
15Timeout stuck requests better (where server has never responded or sent corrupt
16responses)
10 17
11Version 1.38 18Version 1.38
12------------ 19------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e5d09a2fc7a5..b0070d1b149d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -436,7 +436,17 @@ A partial list of the supported mount options follows:
436 SFU does). In the future the bottom 9 bits of the mode 436 SFU does). In the future the bottom 9 bits of the mode
437 mode also will be emulated using queries of the security 437 mode also will be emulated using queries of the security
438 descriptor (ACL). 438 descriptor (ACL).
439 439sec Security mode. Allowed values are:
440 none attempt to connection as a null user (no name)
441 krb5 Use Kerberos version 5 authentication
442 krb5i Use Kerberos authentication and packet signing
443 ntlm Use NTLM password hashing (default)
444 ntlmi Use NTLM password hashing with signing (if
445 /proc/fs/cifs/PacketSigningEnabled on or if
446 server requires signing also can be the default)
447 ntlmv2 Use NTLMv2 password hashing
448 ntlmv2i Use NTLMv2 password hashing with packet signing
449
440The mount.cifs mount helper also accepts a few mount options before -o 450The mount.cifs mount helper also accepts a few mount options before -o
441including: 451including:
442 452
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 22a444a3fe4c..f4124a32bef8 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -219,6 +219,10 @@ cifs_stats_write(struct file *file, const char __user *buffer,
219 219
220 if (c == '1' || c == 'y' || c == 'Y' || c == '0') { 220 if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
221 read_lock(&GlobalSMBSeslock); 221 read_lock(&GlobalSMBSeslock);
222#ifdef CONFIG_CIFS_STATS2
223 atomic_set(&totBufAllocCount, 0);
224 atomic_set(&totSmBufAllocCount, 0);
225#endif /* CONFIG_CIFS_STATS2 */
222 list_for_each(tmp, &GlobalTreeConnectionList) { 226 list_for_each(tmp, &GlobalTreeConnectionList) {
223 tcon = list_entry(tmp, struct cifsTconInfo, 227 tcon = list_entry(tmp, struct cifsTconInfo,
224 cifsConnectionList); 228 cifsConnectionList);
@@ -276,6 +280,14 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
276 smBufAllocCount.counter,cifs_min_small); 280 smBufAllocCount.counter,cifs_min_small);
277 length += item_length; 281 length += item_length;
278 buf += item_length; 282 buf += item_length;
283#ifdef CONFIG_CIFS_STATS2
284 item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
285 atomic_read(&totBufAllocCount),
286 atomic_read(&totSmBufAllocCount));
287 length += item_length;
288 buf += item_length;
289#endif /* CONFIG_CIFS_STATS2 */
290
279 item_length = 291 item_length =
280 sprintf(buf,"Operations (MIDs): %d\n", 292 sprintf(buf,"Operations (MIDs): %d\n",
281 midCount.counter); 293 midCount.counter);
@@ -389,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
389static write_proc_t ntlmv2_enabled_write; 401static write_proc_t ntlmv2_enabled_write;
390static read_proc_t packet_signing_enabled_read; 402static read_proc_t packet_signing_enabled_read;
391static write_proc_t packet_signing_enabled_write; 403static write_proc_t packet_signing_enabled_write;
392static read_proc_t quotaEnabled_read; 404static read_proc_t experimEnabled_read;
393static write_proc_t quotaEnabled_write; 405static write_proc_t experimEnabled_write;
394static read_proc_t linuxExtensionsEnabled_read; 406static read_proc_t linuxExtensionsEnabled_read;
395static write_proc_t linuxExtensionsEnabled_write; 407static write_proc_t linuxExtensionsEnabled_write;
396 408
@@ -430,9 +442,9 @@ cifs_proc_init(void)
430 pde->write_proc = oplockEnabled_write; 442 pde->write_proc = oplockEnabled_write;
431 443
432 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs, 444 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
433 quotaEnabled_read, NULL); 445 experimEnabled_read, NULL);
434 if (pde) 446 if (pde)
435 pde->write_proc = quotaEnabled_write; 447 pde->write_proc = experimEnabled_write;
436 448
437 pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs, 449 pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
438 linuxExtensionsEnabled_read, NULL); 450 linuxExtensionsEnabled_read, NULL);
@@ -574,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
574} 586}
575 587
576static int 588static int
577quotaEnabled_read(char *page, char **start, off_t off, 589experimEnabled_read(char *page, char **start, off_t off,
578 int count, int *eof, void *data) 590 int count, int *eof, void *data)
579{ 591{
580 int len; 592 int len;
581 593
582 len = sprintf(page, "%d\n", experimEnabled); 594 len = sprintf(page, "%d\n", experimEnabled);
583/* could also check if quotas are enabled in kernel 595
584 as a whole first */
585 len -= off; 596 len -= off;
586 *start = page + off; 597 *start = page + off;
587 598
@@ -596,21 +607,23 @@ quotaEnabled_read(char *page, char **start, off_t off,
596 return len; 607 return len;
597} 608}
598static int 609static int
599quotaEnabled_write(struct file *file, const char __user *buffer, 610experimEnabled_write(struct file *file, const char __user *buffer,
600 unsigned long count, void *data) 611 unsigned long count, void *data)
601{ 612{
602 char c; 613 char c;
603 int rc; 614 int rc;
604 615
605 rc = get_user(c, buffer); 616 rc = get_user(c, buffer);
606 if (rc) 617 if (rc)
607 return rc; 618 return rc;
608 if (c == '0' || c == 'n' || c == 'N') 619 if (c == '0' || c == 'n' || c == 'N')
609 experimEnabled = 0; 620 experimEnabled = 0;
610 else if (c == '1' || c == 'y' || c == 'Y') 621 else if (c == '1' || c == 'y' || c == 'Y')
611 experimEnabled = 1; 622 experimEnabled = 1;
623 else if (c == '2')
624 experimEnabled = 2;
612 625
613 return count; 626 return count;
614} 627}
615 628
616static int 629static int
@@ -620,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
620 int len; 633 int len;
621 634
622 len = sprintf(page, "%d\n", linuxExtEnabled); 635 len = sprintf(page, "%d\n", linuxExtEnabled);
623/* could also check if quotas are enabled in kernel
624 as a whole first */
625 len -= off; 636 len -= off;
626 *start = page + off; 637 *start = page + off;
627 638
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
new file mode 100644
index 000000000000..d152ff50ea8c
--- /dev/null
+++ b/fs/cifs/cifsacl.h
@@ -0,0 +1,38 @@
1/*
2 * fs/cifs/cifsacl.h
3 *
4 * Copyright (c) International Business Machines Corp., 2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifndef _CIFSACL_H
23#define _CIFSACL_H
24
25struct cifs_sid {
26 __u8 revision; /* revision level */
27 __u8 num_subauths;
28 __u8 authority[6];
29 __u8 sub_auth[4];
30 /* next sub_auth if any ... */
31} __attribute__((packed));
32
33/* everyone */
34const cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
35/* group users */
36const cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
37
38#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fe2bb7c4c912..a2c24858d40f 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsencrypt.c 2 * fs/cifs/cifsencrypt.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2003 4 * Copyright (C) International Business Machines Corp., 2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -82,6 +82,59 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
82 return rc; 82 return rc;
83} 83}
84 84
85static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
86 const char * key, char * signature)
87{
88 struct MD5Context context;
89
90 if((iov == NULL) || (signature == NULL))
91 return -EINVAL;
92
93 MD5Init(&context);
94 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
95
96/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
97
98 MD5Final(signature,&context);
99
100 return -EOPNOTSUPP;
101/* return 0; */
102}
103
104
105int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
106 __u32 * pexpected_response_sequence_number)
107{
108 int rc = 0;
109 char smb_signature[20];
110 struct smb_hdr * cifs_pdu = iov[0].iov_base;
111
112 if((cifs_pdu == NULL) || (server == NULL))
113 return -EINVAL;
114
115 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
116 return rc;
117
118 spin_lock(&GlobalMid_Lock);
119 cifs_pdu->Signature.Sequence.SequenceNumber =
120 cpu_to_le32(server->sequence_number);
121 cifs_pdu->Signature.Sequence.Reserved = 0;
122
123 *pexpected_response_sequence_number = server->sequence_number++;
124 server->sequence_number++;
125 spin_unlock(&GlobalMid_Lock);
126
127 rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
128 smb_signature);
129 if(rc)
130 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
131 else
132 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
133
134 return rc;
135
136}
137
85int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, 138int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
86 __u32 expected_sequence_number) 139 __u32 expected_sequence_number)
87{ 140{
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e10213b7541e..79eeccd0437f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -513,6 +513,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
513 return written; 513 return written;
514} 514}
515 515
516static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
517{
518 /* origin == SEEK_END => we must revalidate the cached file length */
519 if (origin == 2) {
520 int retval = cifs_revalidate(file->f_dentry);
521 if (retval < 0)
522 return (loff_t)retval;
523 }
524 return remote_llseek(file, offset, origin);
525}
526
516static struct file_system_type cifs_fs_type = { 527static struct file_system_type cifs_fs_type = {
517 .owner = THIS_MODULE, 528 .owner = THIS_MODULE,
518 .name = "cifs", 529 .name = "cifs",
@@ -586,6 +597,7 @@ struct file_operations cifs_file_ops = {
586 .flush = cifs_flush, 597 .flush = cifs_flush,
587 .mmap = cifs_file_mmap, 598 .mmap = cifs_file_mmap,
588 .sendfile = generic_file_sendfile, 599 .sendfile = generic_file_sendfile,
600 .llseek = cifs_llseek,
589#ifdef CONFIG_CIFS_POSIX 601#ifdef CONFIG_CIFS_POSIX
590 .ioctl = cifs_ioctl, 602 .ioctl = cifs_ioctl,
591#endif /* CONFIG_CIFS_POSIX */ 603#endif /* CONFIG_CIFS_POSIX */
@@ -609,7 +621,7 @@ struct file_operations cifs_file_direct_ops = {
609#ifdef CONFIG_CIFS_POSIX 621#ifdef CONFIG_CIFS_POSIX
610 .ioctl = cifs_ioctl, 622 .ioctl = cifs_ioctl,
611#endif /* CONFIG_CIFS_POSIX */ 623#endif /* CONFIG_CIFS_POSIX */
612 624 .llseek = cifs_llseek,
613#ifdef CONFIG_CIFS_EXPERIMENTAL 625#ifdef CONFIG_CIFS_EXPERIMENTAL
614 .dir_notify = cifs_dir_notify, 626 .dir_notify = cifs_dir_notify,
615#endif /* CONFIG_CIFS_EXPERIMENTAL */ 627#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -627,6 +639,7 @@ struct file_operations cifs_file_nobrl_ops = {
627 .flush = cifs_flush, 639 .flush = cifs_flush,
628 .mmap = cifs_file_mmap, 640 .mmap = cifs_file_mmap,
629 .sendfile = generic_file_sendfile, 641 .sendfile = generic_file_sendfile,
642 .llseek = cifs_llseek,
630#ifdef CONFIG_CIFS_POSIX 643#ifdef CONFIG_CIFS_POSIX
631 .ioctl = cifs_ioctl, 644 .ioctl = cifs_ioctl,
632#endif /* CONFIG_CIFS_POSIX */ 645#endif /* CONFIG_CIFS_POSIX */
@@ -649,7 +662,7 @@ struct file_operations cifs_file_direct_nobrl_ops = {
649#ifdef CONFIG_CIFS_POSIX 662#ifdef CONFIG_CIFS_POSIX
650 .ioctl = cifs_ioctl, 663 .ioctl = cifs_ioctl,
651#endif /* CONFIG_CIFS_POSIX */ 664#endif /* CONFIG_CIFS_POSIX */
652 665 .llseek = cifs_llseek,
653#ifdef CONFIG_CIFS_EXPERIMENTAL 666#ifdef CONFIG_CIFS_EXPERIMENTAL
654 .dir_notify = cifs_dir_notify, 667 .dir_notify = cifs_dir_notify,
655#endif /* CONFIG_CIFS_EXPERIMENTAL */ 668#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -733,7 +746,7 @@ cifs_init_request_bufs(void)
733 kmem_cache_destroy(cifs_req_cachep); 746 kmem_cache_destroy(cifs_req_cachep);
734 return -ENOMEM; 747 return -ENOMEM;
735 } 748 }
736 /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and 749 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
737 almost all handle based requests (but not write response, nor is it 750 almost all handle based requests (but not write response, nor is it
738 sufficient for path based requests). A smaller size would have 751 sufficient for path based requests). A smaller size would have
739 been more efficient (compacting multiple slab items on one 4k page) 752 been more efficient (compacting multiple slab items on one 4k page)
@@ -742,7 +755,8 @@ cifs_init_request_bufs(void)
742 efficient to alloc 1 per page off the slab compared to 17K (5page) 755 efficient to alloc 1 per page off the slab compared to 17K (5page)
743 alloc of large cifs buffers even when page debugging is on */ 756 alloc of large cifs buffers even when page debugging is on */
744 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", 757 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
745 MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); 758 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
759 NULL, NULL);
746 if (cifs_sm_req_cachep == NULL) { 760 if (cifs_sm_req_cachep == NULL) {
747 mempool_destroy(cifs_req_poolp); 761 mempool_destroy(cifs_req_poolp);
748 kmem_cache_destroy(cifs_req_cachep); 762 kmem_cache_destroy(cifs_req_cachep);
@@ -954,6 +968,12 @@ init_cifs(void)
954 atomic_set(&tconInfoReconnectCount, 0); 968 atomic_set(&tconInfoReconnectCount, 0);
955 969
956 atomic_set(&bufAllocCount, 0); 970 atomic_set(&bufAllocCount, 0);
971 atomic_set(&smBufAllocCount, 0);
972#ifdef CONFIG_CIFS_STATS2
973 atomic_set(&totBufAllocCount, 0);
974 atomic_set(&totSmBufAllocCount, 0);
975#endif /* CONFIG_CIFS_STATS2 */
976
957 atomic_set(&midCount, 0); 977 atomic_set(&midCount, 0);
958 GlobalCurrentXid = 0; 978 GlobalCurrentXid = 0;
959 GlobalTotalActiveXid = 0; 979 GlobalTotalActiveXid = 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9ec40e0e54fc..821a8eb22559 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
100extern int cifs_ioctl (struct inode * inode, struct file * filep, 100extern int cifs_ioctl (struct inode * inode, struct file * filep,
101 unsigned int command, unsigned long arg); 101 unsigned int command, unsigned long arg);
102#define CIFS_VERSION "1.39" 102#define CIFS_VERSION "1.40"
103#endif /* _CIFSFS_H */ 103#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1ba08f8c5bc4..862e403ff211 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -285,6 +285,7 @@ struct cifs_search_info {
285 unsigned endOfSearch:1; 285 unsigned endOfSearch:1;
286 unsigned emptyDir:1; 286 unsigned emptyDir:1;
287 unsigned unicode:1; 287 unsigned unicode:1;
288 unsigned smallBuf:1; /* so we know which buf_release function to call */
288}; 289};
289 290
290struct cifsFileInfo { 291struct cifsFileInfo {
@@ -420,7 +421,12 @@ struct dir_notify_req {
420#define MID_RESPONSE_RECEIVED 4 421#define MID_RESPONSE_RECEIVED 4
421#define MID_RETRY_NEEDED 8 /* session closed while this request out */ 422#define MID_RETRY_NEEDED 8 /* session closed while this request out */
422#define MID_NO_RESP_NEEDED 0x10 423#define MID_NO_RESP_NEEDED 0x10
423#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */ 424
425/* Types of response buffer returned from SendReceive2 */
426#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
427#define CIFS_SMALL_BUFFER 1
428#define CIFS_LARGE_BUFFER 2
429#define CIFS_IOVEC 4 /* array of response buffers */
424 430
425/* 431/*
426 ***************************************************************** 432 *****************************************************************
@@ -505,8 +511,12 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
505GLOBAL_EXTERN atomic_t tconInfoReconnectCount; 511GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
506 512
507/* Various Debug counters to remove someday (BB) */ 513/* Various Debug counters to remove someday (BB) */
508GLOBAL_EXTERN atomic_t bufAllocCount; 514GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */
509GLOBAL_EXTERN atomic_t smBufAllocCount; 515#ifdef CONFIG_CIFS_STATS2
516GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
517GLOBAL_EXTERN atomic_t totSmBufAllocCount;
518#endif
519GLOBAL_EXTERN atomic_t smBufAllocCount;
510GLOBAL_EXTERN atomic_t midCount; 520GLOBAL_EXTERN atomic_t midCount;
511 521
512/* Misc globals */ 522/* Misc globals */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 33e1859fd2f6..3c09fb9cc569 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifspdu.h 2 * fs/cifs/cifspdu.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -80,7 +80,11 @@
80#define NT_TRANSACT_GET_USER_QUOTA 0x07 80#define NT_TRANSACT_GET_USER_QUOTA 0x07
81#define NT_TRANSACT_SET_USER_QUOTA 0x08 81#define NT_TRANSACT_SET_USER_QUOTA 0x08
82 82
83#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */ 83#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
84/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
85/* among the requests (NTCreateX response is bigger with wct of 34) */
86#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
87#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
84 88
85/* internal cifs vfs structures */ 89/* internal cifs vfs structures */
86/***************************************************************** 90/*****************************************************************
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f4c5ce..8ef0ce47f5b6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -48,8 +48,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
48 struct smb_hdr * /* out */ , 48 struct smb_hdr * /* out */ ,
49 int * /* bytes returned */ , const int long_op); 49 int * /* bytes returned */ , const int long_op);
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct kvec *, int /* nvec */, 51 struct kvec *, int /* nvec to send */,
52 int * /* bytes returned */ , const int long_op); 52 int * /* type of buf returned */ , const int long_op);
53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
55extern int is_valid_oplock_break(struct smb_hdr *smb); 55extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -93,11 +93,12 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
93 const struct nls_table *); 93 const struct nls_table *);
94 94
95extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 95extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
96 const char *searchName, const struct nls_table *nls_codepage, 96 const char *searchName, const struct nls_table *nls_codepage,
97 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep); 97 __u16 *searchHandle, struct cifs_search_info * psrch_inf,
98 int map, const char dirsep);
98 99
99extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 100extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
100 __u16 searchHandle, struct cifs_search_info * psrch_inf); 101 __u16 searchHandle, struct cifs_search_info * psrch_inf);
101 102
102extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, 103extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
103 const __u16 search_handle); 104 const __u16 search_handle);
@@ -230,19 +231,18 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
230 const int smb_file_id); 231 const int smb_file_id);
231 232
232extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 233extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
233 const int netfid, unsigned int count, 234 const int netfid, unsigned int count,
234 const __u64 lseek, unsigned int *nbytes, char **buf); 235 const __u64 lseek, unsigned int *nbytes, char **buf,
236 int * return_buf_type);
235extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 237extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
236 const int netfid, const unsigned int count, 238 const int netfid, const unsigned int count,
237 const __u64 lseek, unsigned int *nbytes, 239 const __u64 lseek, unsigned int *nbytes,
238 const char *buf, const char __user *ubuf, 240 const char *buf, const char __user *ubuf,
239 const int long_op); 241 const int long_op);
240#ifdef CONFIG_CIFS_EXPERIMENTAL
241extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 242extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
242 const int netfid, const unsigned int count, 243 const int netfid, const unsigned int count,
243 const __u64 offset, unsigned int *nbytes, 244 const __u64 offset, unsigned int *nbytes,
244 struct kvec *iov, const int nvec, const int long_op); 245 struct kvec *iov, const int nvec, const int long_op);
245#endif /* CONFIG_CIFS_EXPERIMENTAL */
246extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 246extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
247 const unsigned char *searchName, __u64 * inode_number, 247 const unsigned char *searchName, __u64 * inode_number,
248 const struct nls_table *nls_codepage, 248 const struct nls_table *nls_codepage,
@@ -269,6 +269,8 @@ extern void tconInfoFree(struct cifsTconInfo *);
269extern int cifs_reconnect(struct TCP_Server_Info *server); 269extern int cifs_reconnect(struct TCP_Server_Info *server);
270 270
271extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); 271extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
272extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
273 __u32 *);
272extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 274extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
273 __u32 expected_sequence_number); 275 __u32 expected_sequence_number);
274extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 276extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e556d37e..1620991cd4d2 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -958,21 +958,19 @@ openRetry:
958 return rc; 958 return rc;
959} 959}
960 960
961/* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
964
965int 961int
966CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 962CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
967 const int netfid, const unsigned int count, 963 const int netfid, const unsigned int count,
968 const __u64 lseek, unsigned int *nbytes, char **buf) 964 const __u64 lseek, unsigned int *nbytes, char **buf,
965 int * pbuf_type)
969{ 966{
970 int rc = -EACCES; 967 int rc = -EACCES;
971 READ_REQ *pSMB = NULL; 968 READ_REQ *pSMB = NULL;
972 READ_RSP *pSMBr = NULL; 969 READ_RSP *pSMBr = NULL;
973 char *pReadData = NULL; 970 char *pReadData = NULL;
974 int bytes_returned;
975 int wct; 971 int wct;
972 int resp_buf_type = 0;
973 struct kvec iov[1];
976 974
977 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 975 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
978 if(tcon->ses->capabilities & CAP_LARGE_FILES) 976 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -981,8 +979,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
981 wct = 10; /* old style read */ 979 wct = 10; /* old style read */
982 980
983 *nbytes = 0; 981 *nbytes = 0;
984 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, 982 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
985 (void **) &pSMBr);
986 if (rc) 983 if (rc)
987 return rc; 984 return rc;
988 985
@@ -990,13 +987,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
990 if (tcon->ses->server == NULL) 987 if (tcon->ses->server == NULL)
991 return -ECONNABORTED; 988 return -ECONNABORTED;
992 989
993 pSMB->AndXCommand = 0xFF; /* none */ 990 pSMB->AndXCommand = 0xFF; /* none */
994 pSMB->Fid = netfid; 991 pSMB->Fid = netfid;
995 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 992 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
996 if(wct == 12) 993 if(wct == 12)
997 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 994 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
998 else if((lseek >> 32) > 0) /* can not handle this big offset for old */ 995 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
999 return -EIO; 996 return -EIO;
1000 997
1001 pSMB->Remaining = 0; 998 pSMB->Remaining = 0;
1002 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 999 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1005,14 +1002,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1005 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ 1002 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1006 else { 1003 else {
1007 /* old style read */ 1004 /* old style read */
1008 struct smb_com_readx_req * pSMBW = 1005 struct smb_com_readx_req * pSMBW =
1009 (struct smb_com_readx_req *)pSMB; 1006 (struct smb_com_readx_req *)pSMB;
1010 pSMBW->ByteCount = 0; 1007 pSMBW->ByteCount = 0;
1011 } 1008 }
1012 1009
1013 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1010 iov[0].iov_base = (char *)pSMB;
1014 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1011 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1012 rc = SendReceive2(xid, tcon->ses, iov,
1013 1 /* num iovecs */,
1014 &resp_buf_type, 0);
1015 cifs_stats_inc(&tcon->num_reads); 1015 cifs_stats_inc(&tcon->num_reads);
1016 pSMBr = (READ_RSP *)iov[0].iov_base;
1016 if (rc) { 1017 if (rc) {
1017 cERROR(1, ("Send error in read = %d", rc)); 1018 cERROR(1, ("Send error in read = %d", rc));
1018 } else { 1019 } else {
@@ -1022,33 +1023,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1022 *nbytes = data_length; 1023 *nbytes = data_length;
1023 1024
1024 /*check that DataLength would not go beyond end of SMB */ 1025 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length > CIFSMaxBufSize) 1026 if ((data_length > CIFSMaxBufSize)
1026 || (data_length > count)) { 1027 || (data_length > count)) {
1027 cFYI(1,("bad length %d for count %d",data_length,count)); 1028 cFYI(1,("bad length %d for count %d",data_length,count));
1028 rc = -EIO; 1029 rc = -EIO;
1029 *nbytes = 0; 1030 *nbytes = 0;
1030 } else { 1031 } else {
1031 pReadData = 1032 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1032 (char *) (&pSMBr->hdr.Protocol) +
1033 le16_to_cpu(pSMBr->DataOffset); 1033 le16_to_cpu(pSMBr->DataOffset);
1034/* if(rc = copy_to_user(buf, pReadData, data_length)) { 1034/* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc)); 1035 cERROR(1,("Faulting on read rc = %d",rc));
1036 rc = -EFAULT; 1036 rc = -EFAULT;
1037 }*/ /* can not use copy_to_user when using page cache*/ 1037 }*/ /* can not use copy_to_user when using page cache*/
1038 if(*buf) 1038 if(*buf)
1039 memcpy(*buf,pReadData,data_length); 1039 memcpy(*buf,pReadData,data_length);
1040 } 1040 }
1041 } 1041 }
1042 if(*buf)
1043 cifs_buf_release(pSMB);
1044 else
1045 *buf = (char *)pSMB;
1046 1042
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls 1043 cifs_small_buf_release(pSMB);
1044 if(*buf) {
1045 if(resp_buf_type == CIFS_SMALL_BUFFER)
1046 cifs_small_buf_release(iov[0].iov_base);
1047 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1048 cifs_buf_release(iov[0].iov_base);
1049 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1050 *buf = iov[0].iov_base;
1051 if(resp_buf_type == CIFS_SMALL_BUFFER)
1052 *pbuf_type = CIFS_SMALL_BUFFER;
1053 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1054 *pbuf_type = CIFS_LARGE_BUFFER;
1055 }
1056
1057 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */ 1058 since file handle passed in no longer valid */
1049 return rc; 1059 return rc;
1050} 1060}
1051 1061
1062
1052int 1063int
1053CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 1064CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1054 const int netfid, const unsigned int count, 1065 const int netfid, const unsigned int count,
@@ -1155,7 +1166,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1155 return rc; 1166 return rc;
1156} 1167}
1157 1168
1158#ifdef CONFIG_CIFS_EXPERIMENTAL
1159int 1169int
1160CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1170CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1161 const int netfid, const unsigned int count, 1171 const int netfid, const unsigned int count,
@@ -1164,10 +1174,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1164{ 1174{
1165 int rc = -EACCES; 1175 int rc = -EACCES;
1166 WRITE_REQ *pSMB = NULL; 1176 WRITE_REQ *pSMB = NULL;
1167 int bytes_returned, wct; 1177 int wct;
1168 int smb_hdr_len; 1178 int smb_hdr_len;
1179 int resp_buf_type = 0;
1169 1180
1170 /* BB removeme BB */
1171 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count)); 1181 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1172 1182
1173 if(tcon->ses->capabilities & CAP_LARGE_FILES) 1183 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -1210,22 +1220,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1210 pSMBW->ByteCount = cpu_to_le16(count + 5); 1220 pSMBW->ByteCount = cpu_to_le16(count + 5);
1211 } 1221 }
1212 iov[0].iov_base = pSMB; 1222 iov[0].iov_base = pSMB;
1213 iov[0].iov_len = smb_hdr_len + 4; 1223 if(wct == 14)
1224 iov[0].iov_len = smb_hdr_len + 4;
1225 else /* wct == 12 pad bigger by four bytes */
1226 iov[0].iov_len = smb_hdr_len + 8;
1227
1214 1228
1215 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned, 1229 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1216 long_op); 1230 long_op);
1217 cifs_stats_inc(&tcon->num_writes); 1231 cifs_stats_inc(&tcon->num_writes);
1218 if (rc) { 1232 if (rc) {
1219 cFYI(1, ("Send error Write2 = %d", rc)); 1233 cFYI(1, ("Send error Write2 = %d", rc));
1220 *nbytes = 0; 1234 *nbytes = 0;
1235 } else if(resp_buf_type == 0) {
1236 /* presumably this can not happen, but best to be safe */
1237 rc = -EIO;
1238 *nbytes = 0;
1221 } else { 1239 } else {
1222 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; 1240 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1223 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1241 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1224 *nbytes = (*nbytes) << 16; 1242 *nbytes = (*nbytes) << 16;
1225 *nbytes += le16_to_cpu(pSMBr->Count); 1243 *nbytes += le16_to_cpu(pSMBr->Count);
1226 } 1244 }
1227 1245
1228 cifs_small_buf_release(pSMB); 1246 cifs_small_buf_release(pSMB);
1247 if(resp_buf_type == CIFS_SMALL_BUFFER)
1248 cifs_small_buf_release(iov[0].iov_base);
1249 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1250 cifs_buf_release(iov[0].iov_base);
1229 1251
1230 /* Note: On -EAGAIN error only caller can retry on handle based calls 1252 /* Note: On -EAGAIN error only caller can retry on handle based calls
1231 since file handle passed in no longer valid */ 1253 since file handle passed in no longer valid */
@@ -1234,8 +1256,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1234} 1256}
1235 1257
1236 1258
1237#endif /* CIFS_EXPERIMENTAL */
1238
1239int 1259int
1240CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1260CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1241 const __u16 smb_file_id, const __u64 len, 1261 const __u16 smb_file_id, const __u64 len,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c467de857610..45c9d726c002 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -82,6 +82,12 @@ struct smb_vol {
82 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
84 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
85 unsigned krb5:1;
86 unsigned ntlm:1;
87 unsigned ntlmv2:1;
88 unsigned nullauth:1; /* attempt to authenticate with null user */
89 unsigned sign:1;
90 unsigned seal:1; /* encrypt */
85 unsigned nocase; /* request case insensitive filenames */ 91 unsigned nocase; /* request case insensitive filenames */
86 unsigned nobrl; /* disable sending byte range locks to srv */ 92 unsigned nobrl; /* disable sending byte range locks to srv */
87 unsigned int rsize; 93 unsigned int rsize;
@@ -508,7 +514,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
508 /* else length ok */ 514 /* else length ok */
509 reconnect = 0; 515 reconnect = 0;
510 516
511 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { 517 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
512 isLargeBuf = TRUE; 518 isLargeBuf = TRUE;
513 memcpy(bigbuf, smallbuf, 4); 519 memcpy(bigbuf, smallbuf, 4);
514 smb_buffer = bigbuf; 520 smb_buffer = bigbuf;
@@ -777,7 +783,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
777 783
778 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 784 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
779 vol->rw = TRUE; 785 vol->rw = TRUE;
780 786 vol->ntlm = TRUE;
781 /* default is always to request posix paths. */ 787 /* default is always to request posix paths. */
782 vol->posix_paths = 1; 788 vol->posix_paths = 1;
783 789
@@ -903,6 +909,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
903 printk(KERN_WARNING "CIFS: ip address too long\n"); 909 printk(KERN_WARNING "CIFS: ip address too long\n");
904 return 1; 910 return 1;
905 } 911 }
912 } else if (strnicmp(data, "sec", 3) == 0) {
913 if (!value || !*value) {
914 cERROR(1,("no security value specified"));
915 continue;
916 } else if (strnicmp(value, "krb5i", 5) == 0) {
917 vol->sign = 1;
918 vol->krb5 = 1;
919 } else if (strnicmp(value, "krb5p", 5) == 0) {
920 /* vol->seal = 1;
921 vol->krb5 = 1; */
922 cERROR(1,("Krb5 cifs privacy not supported"));
923 return 1;
924 } else if (strnicmp(value, "krb5", 4) == 0) {
925 vol->krb5 = 1;
926 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
927 vol->ntlmv2 = 1;
928 vol->sign = 1;
929 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
930 vol->ntlmv2 = 1;
931 } else if (strnicmp(value, "ntlmi", 5) == 0) {
932 vol->ntlm = 1;
933 vol->sign = 1;
934 } else if (strnicmp(value, "ntlm", 4) == 0) {
935 /* ntlm is default so can be turned off too */
936 vol->ntlm = 1;
937 } else if (strnicmp(value, "nontlm", 6) == 0) {
938 vol->ntlm = 0;
939 } else if (strnicmp(value, "none", 4) == 0) {
940 vol->nullauth = 1;
941 } else {
942 cERROR(1,("bad security option: %s", value));
943 return 1;
944 }
906 } else if ((strnicmp(data, "unc", 3) == 0) 945 } else if ((strnicmp(data, "unc", 3) == 0)
907 || (strnicmp(data, "target", 6) == 0) 946 || (strnicmp(data, "target", 6) == 0)
908 || (strnicmp(data, "path", 4) == 0)) { 947 || (strnicmp(data, "path", 4) == 0)) {
@@ -1546,7 +1585,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1546 cFYI(1, ("Username: %s ", volume_info.username)); 1585 cFYI(1, ("Username: %s ", volume_info.username));
1547 1586
1548 } else { 1587 } else {
1549 cifserror("No username specified "); 1588 cifserror("No username specified");
1550 /* In userspace mount helper we can get user name from alternate 1589 /* In userspace mount helper we can get user name from alternate
1551 locations such as env variables and files on disk */ 1590 locations such as env variables and files on disk */
1552 kfree(volume_info.UNC); 1591 kfree(volume_info.UNC);
@@ -1587,7 +1626,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1587 return -EINVAL; 1626 return -EINVAL;
1588 } else /* which servers DFS root would we conect to */ { 1627 } else /* which servers DFS root would we conect to */ {
1589 cERROR(1, 1628 cERROR(1,
1590 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); 1629 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1591 kfree(volume_info.UNC); 1630 kfree(volume_info.UNC);
1592 kfree(volume_info.password); 1631 kfree(volume_info.password);
1593 FreeXid(xid); 1632 FreeXid(xid);
@@ -1626,7 +1665,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1626 1665
1627 1666
1628 if (srvTcp) { 1667 if (srvTcp) {
1629 cFYI(1, ("Existing tcp session with server found ")); 1668 cFYI(1, ("Existing tcp session with server found"));
1630 } else { /* create socket */ 1669 } else { /* create socket */
1631 if(volume_info.port) 1670 if(volume_info.port)
1632 sin_server.sin_port = htons(volume_info.port); 1671 sin_server.sin_port = htons(volume_info.port);
@@ -1689,11 +1728,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1689 1728
1690 if (existingCifsSes) { 1729 if (existingCifsSes) {
1691 pSesInfo = existingCifsSes; 1730 pSesInfo = existingCifsSes;
1692 cFYI(1, ("Existing smb sess found ")); 1731 cFYI(1, ("Existing smb sess found"));
1693 kfree(volume_info.password); 1732 kfree(volume_info.password);
1694 /* volume_info.UNC freed at end of function */ 1733 /* volume_info.UNC freed at end of function */
1695 } else if (!rc) { 1734 } else if (!rc) {
1696 cFYI(1, ("Existing smb sess not found ")); 1735 cFYI(1, ("Existing smb sess not found"));
1697 pSesInfo = sesInfoAlloc(); 1736 pSesInfo = sesInfoAlloc();
1698 if (pSesInfo == NULL) 1737 if (pSesInfo == NULL)
1699 rc = -ENOMEM; 1738 rc = -ENOMEM;
@@ -1777,7 +1816,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1777 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, 1816 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1778 volume_info.username); 1817 volume_info.username);
1779 if (tcon) { 1818 if (tcon) {
1780 cFYI(1, ("Found match on UNC path ")); 1819 cFYI(1, ("Found match on UNC path"));
1781 /* we can have only one retry value for a connection 1820 /* we can have only one retry value for a connection
1782 to a share so for resources mounted more than once 1821 to a share so for resources mounted more than once
1783 to the same server share the last value passed in 1822 to the same server share the last value passed in
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 32cc96cafa3e..fed55e3c53df 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * vfs operations that deal with dentries 4 * vfs operations that deal with dentries
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003 6 * Copyright (C) International Business Machines Corp., 2002,2005
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -200,8 +200,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
200 (oplock & CIFS_CREATE_ACTION)) 200 (oplock & CIFS_CREATE_ACTION))
201 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 201 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
202 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 202 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
203 (__u64)current->euid, 203 (__u64)current->fsuid,
204 (__u64)current->egid, 204 (__u64)current->fsgid,
205 0 /* dev */, 205 0 /* dev */,
206 cifs_sb->local_nls, 206 cifs_sb->local_nls,
207 cifs_sb->mnt_cifs_flags & 207 cifs_sb->mnt_cifs_flags &
@@ -325,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
325 else if (pTcon->ses->capabilities & CAP_UNIX) { 325 else if (pTcon->ses->capabilities & CAP_UNIX) {
326 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 326 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
327 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 327 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
328 mode,(__u64)current->euid,(__u64)current->egid, 328 mode,(__u64)current->fsuid,(__u64)current->fsgid,
329 device_number, cifs_sb->local_nls, 329 device_number, cifs_sb->local_nls,
330 cifs_sb->mnt_cifs_flags & 330 cifs_sb->mnt_cifs_flags &
331 CIFS_MOUNT_MAP_SPECIAL_CHR); 331 CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5ade53d7bca8..378095a442d0 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -553,13 +553,13 @@ int cifs_closedir(struct inode *inode, struct file *file)
553 } 553 }
554 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; 554 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
555 if (ptmp) { 555 if (ptmp) {
556 /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir")); 556 cFYI(1, ("closedir free smb buf in srch struct"));
557 pCFileStruct->srch_inf.ntwrk_buf_start = NULL; 557 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
558 cifs_buf_release(ptmp); 558 cifs_buf_release(ptmp);
559 } 559 }
560 ptmp = pCFileStruct->search_resume_name; 560 ptmp = pCFileStruct->search_resume_name;
561 if (ptmp) { 561 if (ptmp) {
562 /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir")); 562 cFYI(1, ("closedir free resume name"));
563 pCFileStruct->search_resume_name = NULL; 563 pCFileStruct->search_resume_name = NULL;
564 kfree(ptmp); 564 kfree(ptmp);
565 } 565 }
@@ -868,10 +868,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
868 if (rc != 0) 868 if (rc != 0)
869 break; 869 break;
870 } 870 }
871#ifdef CONFIG_CIFS_EXPERIMENTAL
872 /* BB FIXME We can not sign across two buffers yet */ 871 /* BB FIXME We can not sign across two buffers yet */
873 if((experimEnabled) && ((pTcon->ses->server->secMode & 872 if((pTcon->ses->server->secMode &
874 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) { 873 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
875 struct kvec iov[2]; 874 struct kvec iov[2];
876 unsigned int len; 875 unsigned int len;
877 876
@@ -887,7 +886,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
887 iov, 1, long_op); 886 iov, 1, long_op);
888 } else 887 } else
889 /* BB FIXME fixup indentation of line below */ 888 /* BB FIXME fixup indentation of line below */
890#endif
891 rc = CIFSSMBWrite(xid, pTcon, 889 rc = CIFSSMBWrite(xid, pTcon,
892 open_file->netfid, 890 open_file->netfid,
893 min_t(const int, cifs_sb->wsize, 891 min_t(const int, cifs_sb->wsize,
@@ -1024,7 +1022,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1024 return rc; 1022 return rc;
1025} 1023}
1026 1024
1027#ifdef CONFIG_CIFS_EXPERIMENTAL
1028static int cifs_writepages(struct address_space *mapping, 1025static int cifs_writepages(struct address_space *mapping,
1029 struct writeback_control *wbc) 1026 struct writeback_control *wbc)
1030{ 1027{
@@ -1227,7 +1224,6 @@ retry:
1227 1224
1228 return rc; 1225 return rc;
1229} 1226}
1230#endif
1231 1227
1232static int cifs_writepage(struct page* page, struct writeback_control *wbc) 1228static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1233{ 1229{
@@ -1426,6 +1422,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1426 rc = -EAGAIN; 1422 rc = -EAGAIN;
1427 smb_read_data = NULL; 1423 smb_read_data = NULL;
1428 while (rc == -EAGAIN) { 1424 while (rc == -EAGAIN) {
1425 int buf_type = CIFS_NO_BUFFER;
1429 if ((open_file->invalidHandle) && 1426 if ((open_file->invalidHandle) &&
1430 (!open_file->closePend)) { 1427 (!open_file->closePend)) {
1431 rc = cifs_reopen_file(file->f_dentry->d_inode, 1428 rc = cifs_reopen_file(file->f_dentry->d_inode,
@@ -1434,20 +1431,22 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1434 break; 1431 break;
1435 } 1432 }
1436 rc = CIFSSMBRead(xid, pTcon, 1433 rc = CIFSSMBRead(xid, pTcon,
1437 open_file->netfid, 1434 open_file->netfid,
1438 current_read_size, *poffset, 1435 current_read_size, *poffset,
1439 &bytes_read, &smb_read_data); 1436 &bytes_read, &smb_read_data,
1437 &buf_type);
1440 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1438 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1441 if (copy_to_user(current_offset, 1439 if (copy_to_user(current_offset,
1442 smb_read_data + 4 /* RFC1001 hdr */ 1440 smb_read_data + 4 /* RFC1001 hdr */
1443 + le16_to_cpu(pSMBr->DataOffset), 1441 + le16_to_cpu(pSMBr->DataOffset),
1444 bytes_read)) { 1442 bytes_read)) {
1445 rc = -EFAULT; 1443 rc = -EFAULT;
1446 FreeXid(xid); 1444 }
1447 return rc;
1448 }
1449 if (smb_read_data) { 1445 if (smb_read_data) {
1450 cifs_buf_release(smb_read_data); 1446 if(buf_type == CIFS_SMALL_BUFFER)
1447 cifs_small_buf_release(smb_read_data);
1448 else if(buf_type == CIFS_LARGE_BUFFER)
1449 cifs_buf_release(smb_read_data);
1451 smb_read_data = NULL; 1450 smb_read_data = NULL;
1452 } 1451 }
1453 } 1452 }
@@ -1480,6 +1479,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1480 int xid; 1479 int xid;
1481 char *current_offset; 1480 char *current_offset;
1482 struct cifsFileInfo *open_file; 1481 struct cifsFileInfo *open_file;
1482 int buf_type = CIFS_NO_BUFFER;
1483 1483
1484 xid = GetXid(); 1484 xid = GetXid();
1485 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 1485 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1516,9 +1516,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1516 break; 1516 break;
1517 } 1517 }
1518 rc = CIFSSMBRead(xid, pTcon, 1518 rc = CIFSSMBRead(xid, pTcon,
1519 open_file->netfid, 1519 open_file->netfid,
1520 current_read_size, *poffset, 1520 current_read_size, *poffset,
1521 &bytes_read, &current_offset); 1521 &bytes_read, &current_offset,
1522 &buf_type);
1522 } 1523 }
1523 if (rc || (bytes_read == 0)) { 1524 if (rc || (bytes_read == 0)) {
1524 if (total_read) { 1525 if (total_read) {
@@ -1616,6 +1617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1616 struct smb_com_read_rsp *pSMBr; 1617 struct smb_com_read_rsp *pSMBr;
1617 struct pagevec lru_pvec; 1618 struct pagevec lru_pvec;
1618 struct cifsFileInfo *open_file; 1619 struct cifsFileInfo *open_file;
1620 int buf_type = CIFS_NO_BUFFER;
1619 1621
1620 xid = GetXid(); 1622 xid = GetXid();
1621 if (file->private_data == NULL) { 1623 if (file->private_data == NULL) {
@@ -1672,14 +1674,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1672 } 1674 }
1673 1675
1674 rc = CIFSSMBRead(xid, pTcon, 1676 rc = CIFSSMBRead(xid, pTcon,
1675 open_file->netfid, 1677 open_file->netfid,
1676 read_size, offset, 1678 read_size, offset,
1677 &bytes_read, &smb_read_data); 1679 &bytes_read, &smb_read_data,
1678 1680 &buf_type);
1679 /* BB more RC checks ? */ 1681 /* BB more RC checks ? */
1680 if (rc== -EAGAIN) { 1682 if (rc== -EAGAIN) {
1681 if (smb_read_data) { 1683 if (smb_read_data) {
1682 cifs_buf_release(smb_read_data); 1684 if(buf_type == CIFS_SMALL_BUFFER)
1685 cifs_small_buf_release(smb_read_data);
1686 else if(buf_type == CIFS_LARGE_BUFFER)
1687 cifs_buf_release(smb_read_data);
1683 smb_read_data = NULL; 1688 smb_read_data = NULL;
1684 } 1689 }
1685 } 1690 }
@@ -1736,7 +1741,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1736 break; 1741 break;
1737 } 1742 }
1738 if (smb_read_data) { 1743 if (smb_read_data) {
1739 cifs_buf_release(smb_read_data); 1744 if(buf_type == CIFS_SMALL_BUFFER)
1745 cifs_small_buf_release(smb_read_data);
1746 else if(buf_type == CIFS_LARGE_BUFFER)
1747 cifs_buf_release(smb_read_data);
1740 smb_read_data = NULL; 1748 smb_read_data = NULL;
1741 } 1749 }
1742 bytes_read = 0; 1750 bytes_read = 0;
@@ -1825,10 +1833,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1825 open_file = find_writable_file(cifsInode); 1833 open_file = find_writable_file(cifsInode);
1826 1834
1827 if(open_file) { 1835 if(open_file) {
1836 struct cifs_sb_info *cifs_sb;
1837
1828 /* there is not actually a write pending so let 1838 /* there is not actually a write pending so let
1829 this handle go free and allow it to 1839 this handle go free and allow it to
1830 be closable if needed */ 1840 be closable if needed */
1831 atomic_dec(&open_file->wrtPending); 1841 atomic_dec(&open_file->wrtPending);
1842
1843 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1844 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1845 /* since no page cache to corrupt on directio
1846 we can change size safely */
1847 return 1;
1848 }
1849
1832 return 0; 1850 return 0;
1833 } else 1851 } else
1834 return 1; 1852 return 1;
@@ -1873,9 +1891,7 @@ struct address_space_operations cifs_addr_ops = {
1873 .readpage = cifs_readpage, 1891 .readpage = cifs_readpage,
1874 .readpages = cifs_readpages, 1892 .readpages = cifs_readpages,
1875 .writepage = cifs_writepage, 1893 .writepage = cifs_writepage,
1876#ifdef CONFIG_CIFS_EXPERIMENTAL
1877 .writepages = cifs_writepages, 1894 .writepages = cifs_writepages,
1878#endif
1879 .prepare_write = cifs_prepare_write, 1895 .prepare_write = cifs_prepare_write,
1880 .commit_write = cifs_commit_write, 1896 .commit_write = cifs_commit_write,
1881 .set_page_dirty = __set_page_dirty_nobuffers, 1897 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3ebce9430f4a..59359911f481 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
229 cifs_sb->mnt_cifs_flags & 229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR); 230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) { 231 if (rc==0) {
232 int buf_type = CIFS_NO_BUFFER;
232 /* Read header */ 233 /* Read header */
233 rc = CIFSSMBRead(xid, pTcon, 234 rc = CIFSSMBRead(xid, pTcon,
234 netfid, 235 netfid,
235 24 /* length */, 0 /* offset */, 236 24 /* length */, 0 /* offset */,
236 &bytes_read, &pbuf); 237 &bytes_read, &pbuf, &buf_type);
237 if((rc == 0) && (bytes_read >= 8)) { 238 if((rc == 0) && (bytes_read >= 8)) {
238 if(memcmp("IntxBLK", pbuf, 8) == 0) { 239 if(memcmp("IntxBLK", pbuf, 8) == 0) {
239 cFYI(1,("Block device")); 240 cFYI(1,("Block device"));
@@ -267,7 +268,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
267 } else { 268 } else {
268 inode->i_mode |= S_IFREG; /* then it is a file */ 269 inode->i_mode |= S_IFREG; /* then it is a file */
269 rc = -EOPNOTSUPP; /* or some unknown SFU type */ 270 rc = -EOPNOTSUPP; /* or some unknown SFU type */
270 } 271 }
271 CIFSSMBClose(xid, pTcon, netfid); 272 CIFSSMBClose(xid, pTcon, netfid);
272 } 273 }
273 return rc; 274 return rc;
@@ -750,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
750 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
751 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 752 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
752 mode, 753 mode,
753 (__u64)current->euid, 754 (__u64)current->fsuid,
754 (__u64)current->egid, 755 (__u64)current->fsgid,
755 0 /* dev_t */, 756 0 /* dev_t */,
756 cifs_sb->local_nls, 757 cifs_sb->local_nls,
757 cifs_sb->mnt_cifs_flags & 758 cifs_sb->mnt_cifs_flags &
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 94baf6c8ecbd..812c6bb0fe38 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/misc.c 2 * fs/cifs/misc.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -161,6 +161,9 @@ cifs_buf_get(void)
161 if (ret_buf) { 161 if (ret_buf) {
162 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); 162 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
163 atomic_inc(&bufAllocCount); 163 atomic_inc(&bufAllocCount);
164#ifdef CONFIG_CIFS_STATS2
165 atomic_inc(&totBufAllocCount);
166#endif /* CONFIG_CIFS_STATS2 */
164 } 167 }
165 168
166 return ret_buf; 169 return ret_buf;
@@ -195,6 +198,10 @@ cifs_small_buf_get(void)
195 /* No need to clear memory here, cleared in header assemble */ 198 /* No need to clear memory here, cleared in header assemble */
196 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ 199 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
197 atomic_inc(&smBufAllocCount); 200 atomic_inc(&smBufAllocCount);
201#ifdef CONFIG_CIFS_STATS2
202 atomic_inc(&totSmBufAllocCount);
203#endif /* CONFIG_CIFS_STATS2 */
204
198 } 205 }
199 return ret_buf; 206 return ret_buf;
200} 207}
@@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
292 struct cifsSesInfo * ses; 299 struct cifsSesInfo * ses;
293 char *temp = (char *) buffer; 300 char *temp = (char *) buffer;
294 301
295 memset(temp,0,MAX_CIFS_HDR_SIZE); 302 memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
296 303
297 buffer->smb_buf_length = 304 buffer->smb_buf_length =
298 (2 * word_count) + sizeof (struct smb_hdr) - 305 (2 * word_count) + sizeof (struct smb_hdr) -
@@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
348 /* BB Add support for establishing new tCon and SMB Session */ 355 /* BB Add support for establishing new tCon and SMB Session */
349 /* with userid/password pairs found on the smb session */ 356 /* with userid/password pairs found on the smb session */
350 /* for other target tcp/ip addresses BB */ 357 /* for other target tcp/ip addresses BB */
351 if(current->uid != treeCon->ses->linux_uid) { 358 if(current->fsuid != treeCon->ses->linux_uid) {
352 cFYI(1,("Multiuser mode and UID did not match tcon uid ")); 359 cFYI(1,("Multiuser mode and UID did not match tcon uid"));
353 read_lock(&GlobalSMBSeslock); 360 read_lock(&GlobalSMBSeslock);
354 list_for_each(temp_item, &GlobalSMBSessionList) { 361 list_for_each(temp_item, &GlobalSMBSessionList) {
355 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); 362 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
356 if(ses->linux_uid == current->uid) { 363 if(ses->linux_uid == current->fsuid) {
357 if(ses->server == treeCon->ses->server) { 364 if(ses->server == treeCon->ses->server) {
358 cFYI(1,("found matching uid substitute right smb_uid")); 365 cFYI(1,("found matching uid substitute right smb_uid"));
359 buffer->Uid = ses->Suid; 366 buffer->Uid = ses->Suid;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9bdaaecae36f..288cc048d37f 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -214,8 +214,7 @@ static void fill_in_inode(struct inode *tmp_inode,
214 tmp_inode->i_fop = &cifs_file_nobrl_ops; 214 tmp_inode->i_fop = &cifs_file_nobrl_ops;
215 else 215 else
216 tmp_inode->i_fop = &cifs_file_ops; 216 tmp_inode->i_fop = &cifs_file_ops;
217 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 217
218 tmp_inode->i_fop->lock = NULL;
219 tmp_inode->i_data.a_ops = &cifs_addr_ops; 218 tmp_inode->i_data.a_ops = &cifs_addr_ops;
220 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 219 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
221 (cifs_sb->tcon->ses->server->maxBuf < 220 (cifs_sb->tcon->ses->server->maxBuf <
@@ -327,12 +326,18 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
327 if (S_ISREG(tmp_inode->i_mode)) { 326 if (S_ISREG(tmp_inode->i_mode)) {
328 cFYI(1, ("File inode")); 327 cFYI(1, ("File inode"));
329 tmp_inode->i_op = &cifs_file_inode_ops; 328 tmp_inode->i_op = &cifs_file_inode_ops;
330 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 329
331 tmp_inode->i_fop = &cifs_file_direct_ops; 330 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
331 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
332 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
333 else
334 tmp_inode->i_fop = &cifs_file_direct_ops;
335
336 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
337 tmp_inode->i_fop = &cifs_file_nobrl_ops;
332 else 338 else
333 tmp_inode->i_fop = &cifs_file_ops; 339 tmp_inode->i_fop = &cifs_file_ops;
334 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 340
335 tmp_inode->i_fop->lock = NULL;
336 tmp_inode->i_data.a_ops = &cifs_addr_ops; 341 tmp_inode->i_data.a_ops = &cifs_addr_ops;
337 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 342 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
338 (cifs_sb->tcon->ses->server->maxBuf < 343 (cifs_sb->tcon->ses->server->maxBuf <
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index 9222033cad8e..aede606132aa 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -24,11 +24,11 @@
24/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ 24/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
25 25
26 /* RFC 1002 session packet types */ 26 /* RFC 1002 session packet types */
27#define RFC1002_SESSION_MESASAGE 0x00 27#define RFC1002_SESSION_MESSAGE 0x00
28#define RFC1002_SESSION_REQUEST 0x81 28#define RFC1002_SESSION_REQUEST 0x81
29#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 29#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
30#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 30#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
31#define RFC1002_RETARGET_SESSION_RESPONSE 0x83 31#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
32#define RFC1002_SESSION_KEEP_ALIVE 0x85 32#define RFC1002_SESSION_KEEP_ALIVE 0x85
33 33
34 /* RFC 1002 flags (only one defined */ 34 /* RFC 1002 flags (only one defined */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f8871196098c..c96a148c39b2 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -206,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
206 return rc; 206 return rc;
207} 207}
208 208
209#ifdef CONFIG_CIFS_EXPERIMENTAL
210static int 209static int
211smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, 210smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
212 struct sockaddr *sin) 211 struct sockaddr *sin)
@@ -299,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
299 298
300int 299int
301SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 300SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
302 struct kvec *iov, int n_vec, int *pbytes_returned, 301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
303 const int long_op) 302 const int long_op)
304{ 303{
305 int rc = 0; 304 int rc = 0;
@@ -307,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
307 unsigned long timeout; 306 unsigned long timeout;
308 struct mid_q_entry *midQ; 307 struct mid_q_entry *midQ;
309 struct smb_hdr *in_buf = iov[0].iov_base; 308 struct smb_hdr *in_buf = iov[0].iov_base;
309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
310 311
311 if (ses == NULL) { 312 if (ses == NULL) {
312 cERROR(1,("Null smb session")); 313 cERROR(1,("Null smb session"));
@@ -392,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
392 return -ENOMEM; 393 return -ENOMEM;
393 } 394 }
394 395
395/* BB FIXME */ 396 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
396/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
397 397
398 midQ->midState = MID_REQUEST_SUBMITTED; 398 midQ->midState = MID_REQUEST_SUBMITTED;
399#ifdef CONFIG_CIFS_STATS2 399#ifdef CONFIG_CIFS_STATS2
@@ -492,18 +492,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
492 492
493 if (midQ->resp_buf && 493 if (midQ->resp_buf &&
494 (midQ->midState == MID_RESPONSE_RECEIVED)) { 494 (midQ->midState == MID_RESPONSE_RECEIVED)) {
495 in_buf->smb_buf_length = receive_len;
496 /* BB verify that length would not overrun small buf */
497 memcpy((char *)in_buf + 4,
498 (char *)midQ->resp_buf + 4,
499 receive_len);
500 495
501 dump_smb(in_buf, 80); 496 iov[0].iov_base = (char *)midQ->resp_buf;
497 if(midQ->largeBuf)
498 *pRespBufType = CIFS_LARGE_BUFFER;
499 else
500 *pRespBufType = CIFS_SMALL_BUFFER;
501 iov[0].iov_len = receive_len + 4;
502 iov[1].iov_len = 0;
503
504 dump_smb(midQ->resp_buf, 80);
502 /* convert the length into a more usable form */ 505 /* convert the length into a more usable form */
503 if((receive_len > 24) && 506 if((receive_len > 24) &&
504 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 507 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
505 SECMODE_SIGN_ENABLED))) { 508 SECMODE_SIGN_ENABLED))) {
506 rc = cifs_verify_signature(in_buf, 509 rc = cifs_verify_signature(midQ->resp_buf,
507 ses->server->mac_signing_key, 510 ses->server->mac_signing_key,
508 midQ->sequence_number+1); 511 midQ->sequence_number+1);
509 if(rc) { 512 if(rc) {
@@ -512,18 +515,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
512 } 515 }
513 } 516 }
514 517
515 *pbytes_returned = in_buf->smb_buf_length;
516
517 /* BB special case reconnect tid and uid here? */ 518 /* BB special case reconnect tid and uid here? */
518 /* BB special case Errbadpassword and pwdexpired here */ 519 /* BB special case Errbadpassword and pwdexpired here */
519 rc = map_smb_to_linux_error(in_buf); 520 rc = map_smb_to_linux_error(midQ->resp_buf);
520 521
521 /* convert ByteCount if necessary */ 522 /* convert ByteCount if necessary */
522 if (receive_len >= 523 if (receive_len >=
523 sizeof (struct smb_hdr) - 524 sizeof (struct smb_hdr) -
524 4 /* do not count RFC1001 header */ + 525 4 /* do not count RFC1001 header */ +
525 (2 * in_buf->WordCount) + 2 /* bcc */ ) 526 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
526 BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf)); 527 BCC(midQ->resp_buf) =
528 le16_to_cpu(BCC_LE(midQ->resp_buf));
529 midQ->resp_buf = NULL; /* mark it so will not be freed
530 by DeleteMidQEntry */
527 } else { 531 } else {
528 rc = -EIO; 532 rc = -EIO;
529 cFYI(1,("Bad MID state?")); 533 cFYI(1,("Bad MID state?"));
@@ -549,7 +553,6 @@ out_unlock2:
549 553
550 return rc; 554 return rc;
551} 555}
552#endif /* CIFS_EXPERIMENTAL */
553 556
554int 557int
555SendReceive(const unsigned int xid, struct cifsSesInfo *ses, 558SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -790,7 +793,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
790 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 793 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
791 } else { 794 } else {
792 rc = -EIO; 795 rc = -EIO;
793 cERROR(1,("Bad MID state? ")); 796 cERROR(1,("Bad MID state?"));
794 } 797 }
795 } 798 }
796cifs_no_response_exit: 799cifs_no_response_exit: