aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES16
-rw-r--r--fs/cifs/README42
-rw-r--r--fs/cifs/TODO4
-rw-r--r--fs/cifs/cifs_debug.c51
-rw-r--r--fs/cifs/cifs_fs_sb.h5
-rw-r--r--fs/cifs/cifs_unicode.c13
-rw-r--r--fs/cifs/cifs_unicode.h6
-rw-r--r--fs/cifs/cifs_uniupr.h2
-rw-r--r--fs/cifs/cifsacl.h38
-rw-r--r--fs/cifs/cifsencrypt.c57
-rw-r--r--fs/cifs/cifsfs.c158
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifspdu.h107
-rw-r--r--fs/cifs/cifsproto.h23
-rw-r--r--fs/cifs/cifssmb.c360
-rw-r--r--fs/cifs/connect.c180
-rw-r--r--fs/cifs/dir.c74
-rw-r--r--fs/cifs/file.c81
-rw-r--r--fs/cifs/inode.c268
-rw-r--r--fs/cifs/misc.c36
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/readdir.c60
-rw-r--r--fs/cifs/rfc1002pdu.h4
-rw-r--r--fs/cifs/transport.c43
-rw-r--r--fs/cifs/xattr.c22
26 files changed, 1273 insertions, 403 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index eab3750cf304..d335015473a5 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,22 @@
1Version 1.40
2------------
3Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
4of readpages by eliminating one extra memcpy. Allow update of file size
5from remote server even if file is open for write as long as mount is
6directio. Recognize share mode security and send NTLM encrypted password
7on tree connect if share mode negotiated.
8
1Version 1.39 9Version 1.39
2------------ 10------------
3Defer close of a file handle slightly if pending writes depend on that file handle 11Defer close of a file handle slightly if pending writes depend on that handle
4(this reduces the EBADF bad file handle errors that can be logged under heavy 12(this reduces the EBADF bad file handle errors that can be logged under heavy
5stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 13stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2
14Fix SFU style symlinks and mknod needed for servers which do not support the
15CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
16dentries so files that the client sees as deleted but that later get created
17on the server will be recognized. Add client side permission check on setattr.
18Timeout stuck requests better (where server has never responded or sent corrupt
19responses)
6 20
7Version 1.38 21Version 1.38
8------------ 22------------
diff --git a/fs/cifs/README b/fs/cifs/README
index bb90941826ad..b0070d1b149d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -278,7 +278,9 @@ A partial list of the supported mount options follows:
278 (such as Windows), permissions can also be checked at the 278 (such as Windows), permissions can also be checked at the
279 client, and a crude form of client side permission checking 279 client, and a crude form of client side permission checking
280 can be enabled by specifying file_mode and dir_mode on 280 can be enabled by specifying file_mode and dir_mode on
281 the client 281 the client. Note that the mount.cifs helper must be
282 at version 1.10 or higher to support specifying the uid
283 (or gid) in non-numberic form.
282 gid If CIFS Unix extensions are not supported by the server 284 gid If CIFS Unix extensions are not supported by the server
283 this overrides the default gid for inodes. 285 this overrides the default gid for inodes.
284 file_mode If CIFS Unix extensions are not supported by the server 286 file_mode If CIFS Unix extensions are not supported by the server
@@ -345,7 +347,10 @@ A partial list of the supported mount options follows:
345 client system. It is typically only needed when the server 347 client system. It is typically only needed when the server
346 supports the CIFS Unix Extensions but the UIDs/GIDs on the 348 supports the CIFS Unix Extensions but the UIDs/GIDs on the
347 client and server system do not match closely enough to allow 349 client and server system do not match closely enough to allow
348 access by the user doing the mount. 350 access by the user doing the mount, but it may be useful with
351 non CIFS Unix Extension mounts for cases in which the default
352 mode is specified on the mount but is not to be enforced on the
353 client (e.g. perhaps when MultiUserMount is enabled)
349 Note that this does not affect the normal ACL check on the 354 Note that this does not affect the normal ACL check on the
350 target machine done by the server software (of the server 355 target machine done by the server software (of the server
351 ACL against the user name provided at mount time). 356 ACL against the user name provided at mount time).
@@ -368,15 +373,21 @@ A partial list of the supported mount options follows:
368 setuids If the CIFS Unix extensions are negotiated with the server 373 setuids If the CIFS Unix extensions are negotiated with the server
369 the client will attempt to set the effective uid and gid of 374 the client will attempt to set the effective uid and gid of
370 the local process on newly created files, directories, and 375 the local process on newly created files, directories, and
371 devices (create, mkdir, mknod). 376 devices (create, mkdir, mknod). If the CIFS Unix Extensions
377 are not negotiated, for newly created files and directories
378 instead of using the default uid and gid specified on the
379 the mount, cache the new file's uid and gid locally which means
380 that the uid for the file can change when the inode is
381 reloaded (or the user remounts the share).
372 nosetuids The client will not attempt to set the uid and gid on 382 nosetuids The client will not attempt to set the uid and gid on
373 on newly created files, directories, and devices (create, 383 on newly created files, directories, and devices (create,
374 mkdir, mknod) which will result in the server setting the 384 mkdir, mknod) which will result in the server setting the
375 uid and gid to the default (usually the server uid of the 385 uid and gid to the default (usually the server uid of the
376 user who mounted the share). Letting the server (rather than 386 user who mounted the share). Letting the server (rather than
377 the client) set the uid and gid is the default. This 387 the client) set the uid and gid is the default. If the CIFS
378 parameter has no effect if the CIFS Unix Extensions are not 388 Unix Extensions are not negotiated then the uid and gid for
379 negotiated. 389 new files will appear to be the uid (gid) of the mounter or the
390 uid (gid) parameter specified on the mount.
380 netbiosname When mounting to servers via port 139, specifies the RFC1001 391 netbiosname When mounting to servers via port 139, specifies the RFC1001
381 source name to use to represent the client netbios machine 392 source name to use to represent the client netbios machine
382 name when doing the RFC1001 netbios session initialize. 393 name when doing the RFC1001 netbios session initialize.
@@ -418,7 +429,24 @@ A partial list of the supported mount options follows:
418 byte range locks). 429 byte range locks).
419 remount remount the share (often used to change from ro to rw mounts 430 remount remount the share (often used to change from ro to rw mounts
420 or vice versa) 431 or vice versa)
421 432 sfu When the CIFS Unix Extensions are not negotiated, attempt to
433 create device files and fifos in a format compatible with
434 Services for Unix (SFU). In addition retrieve bits 10-12
435 of the mode via the SETFILEBITS extended attribute (as
436 SFU does). In the future the bottom 9 bits of the mode
437 mode also will be emulated using queries of the security
438 descriptor (ACL).
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
422The 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
423including: 451including:
424 452
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index c909298d11ed..fc34c74ec4be 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
1version 1.37 October 9, 2005 1Version 1.39 November 30, 2005
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -58,7 +58,7 @@ o) Improve performance of readpages by sending more than one read
58at a time when 8 pages or more are requested. In conjuntion 58at a time when 8 pages or more are requested. In conjuntion
59add support for async_cifs_readpages. 59add support for async_cifs_readpages.
60 60
61p) Add support for storing symlink and fifo info to Windows servers 61p) Add support for storing symlink info to Windows servers
62in the Extended Attribute format their SFU clients would recognize. 62in the Extended Attribute format their SFU clients would recognize.
63 63
64q) Finish fcntl D_NOTIFY support so kde and gnome file list windows 64q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
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/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index f799f6f0e729..ad58eb0c4d6d 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,9 +24,10 @@
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ 26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
27#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ 27#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
28#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ 28#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
29#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ 29#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
30#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
30 31
31struct cifs_sb_info { 32struct cifs_sb_info {
32 struct cifsTconInfo *tcon; /* primary mount */ 33 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 4e12053f0806..d2b128255944 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifs_unicode.c 2 * fs/cifs/cifs_unicode.c
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2000,2002 4 * Copyright (c) International Business Machines Corp., 2000,2005
5 * Modified by Steve French (sfrench@us.ibm.com) 5 * Modified by Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
31 * 31 *
32 */ 32 */
33int 33int
34cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */ 34cifs_strfromUCS_le(char *to, const __le16 * from,
35 int len, const struct nls_table *codepage) 35 int len, const struct nls_table *codepage)
36{ 36{
37 int i; 37 int i;
@@ -60,25 +60,26 @@ cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
60 * 60 *
61 */ 61 */
62int 62int
63cifs_strtoUCS(wchar_t * to, const char *from, int len, 63cifs_strtoUCS(__le16 * to, const char *from, int len,
64 const struct nls_table *codepage) 64 const struct nls_table *codepage)
65{ 65{
66 int charlen; 66 int charlen;
67 int i; 67 int i;
68 wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
68 69
69 for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 70 for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
70 71
71 /* works for 2.4.0 kernel or later */ 72 /* works for 2.4.0 kernel or later */
72 charlen = codepage->char2uni(from, len, &to[i]); 73 charlen = codepage->char2uni(from, len, &wchar_to[i]);
73 if (charlen < 1) { 74 if (charlen < 1) {
74 cERROR(1, 75 cERROR(1,
75 ("cifs_strtoUCS: char2uni returned %d", 76 ("cifs_strtoUCS: char2uni returned %d",
76 charlen)); 77 charlen));
77 /* A question mark */ 78 /* A question mark */
78 to[i] = (wchar_t)cpu_to_le16(0x003f); 79 to[i] = cpu_to_le16(0x003f);
79 charlen = 1; 80 charlen = 1;
80 } else 81 } else
81 to[i] = (wchar_t)cpu_to_le16(to[i]); 82 to[i] = cpu_to_le16(wchar_to[i]);
82 83
83 } 84 }
84 85
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index da8dde965275..39e5b970325f 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -5,7 +5,7 @@
5 * Convert a unicode character to upper or lower case using 5 * Convert a unicode character to upper or lower case using
6 * compressed tables. 6 * compressed tables.
7 * 7 *
8 * Copyright (c) International Business Machines Corp., 2000,2002 8 * Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -59,8 +59,8 @@ extern struct UniCaseRange UniLowerRange[];
59#endif /* UNIUPR_NOLOWER */ 59#endif /* UNIUPR_NOLOWER */
60 60
61#ifdef __KERNEL__ 61#ifdef __KERNEL__
62int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *); 62int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
63int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *); 63int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
64#endif 64#endif
65 65
66/* 66/*
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
index decd138f14d4..da2ad5b451ac 100644
--- a/fs/cifs/cifs_uniupr.h
+++ b/fs/cifs/cifs_uniupr.h
@@ -242,7 +242,7 @@ static signed char UniCaseRangeLff20[27] = {
242/* 242/*
243 * Lower Case Range 243 * Lower Case Range
244 */ 244 */
245const static struct UniCaseRange CifsUniLowerRange[] = { 245static const struct UniCaseRange CifsUniLowerRange[] = {
246 0x0380, 0x03ab, UniCaseRangeL0380, 246 0x0380, 0x03ab, UniCaseRangeL0380,
247 0x0400, 0x042f, UniCaseRangeL0400, 247 0x0400, 0x042f, UniCaseRangeL0400,
248 0x0490, 0x04cb, UniCaseRangeL0490, 248 0x0490, 0x04cb, UniCaseRangeL0490,
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
new file mode 100644
index 000000000000..d0776ac2b804
--- /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 __u32 sub_auth[4];
30 /* next sub_auth if any ... */
31} __attribute__((packed));
32
33/* everyone */
34extern const struct cifs_sid sid_everyone;
35/* group users */
36extern const struct cifs_sid sid_user;
37
38#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 1959c7c4b185..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{
@@ -149,7 +202,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
149 char temp_hash[16]; 202 char temp_hash[16];
150 struct HMACMD5Context ctx; 203 struct HMACMD5Context ctx;
151 char * ucase_buf; 204 char * ucase_buf;
152 wchar_t * unicode_buf; 205 __le16 * unicode_buf;
153 unsigned int i,user_name_len,dom_name_len; 206 unsigned int i,user_name_len,dom_name_len;
154 207
155 if(ses == NULL) 208 if(ses == NULL)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 682b0235ad9a..79eeccd0437f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -32,6 +32,7 @@
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/vfs.h> 33#include <linux/vfs.h>
34#include <linux/mempool.h> 34#include <linux/mempool.h>
35#include <linux/delay.h>
35#include "cifsfs.h" 36#include "cifsfs.h"
36#include "cifspdu.h" 37#include "cifspdu.h"
37#define DECLARE_GLOBALS_HERE 38#define DECLARE_GLOBALS_HERE
@@ -429,6 +430,11 @@ static void cifs_umount_begin(struct super_block * sblock)
429 { 430 {
430 cFYI(1,("wake up tasks now - umount begin not complete")); 431 cFYI(1,("wake up tasks now - umount begin not complete"));
431 wake_up_all(&tcon->ses->server->request_q); 432 wake_up_all(&tcon->ses->server->request_q);
433 wake_up_all(&tcon->ses->server->response_q);
434 msleep(1); /* yield */
435 /* we have to kick the requests once more */
436 wake_up_all(&tcon->ses->server->response_q);
437 msleep(1);
432 } 438 }
433/* BB FIXME - finish add checks for tidStatus BB */ 439/* BB FIXME - finish add checks for tidStatus BB */
434 440
@@ -483,56 +489,40 @@ cifs_get_sb(struct file_system_type *fs_type,
483 return sb; 489 return sb;
484} 490}
485 491
486static ssize_t 492static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
487cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size, 493 unsigned long nr_segs, loff_t *ppos)
488 loff_t * poffset)
489{ 494{
490 if(file->f_dentry == NULL) 495 struct inode *inode = file->f_dentry->d_inode;
491 return -EIO; 496 ssize_t written;
492 else if(file->f_dentry->d_inode == NULL)
493 return -EIO;
494
495 cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
496 497
497 if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) { 498 written = generic_file_writev(file, iov, nr_segs, ppos);
498 return generic_file_read(file,read_data,read_size,poffset); 499 if (!CIFS_I(inode)->clientCanCacheAll)
499 } else { 500 filemap_fdatawrite(inode->i_mapping);
500 /* BB do we need to lock inode from here until after invalidate? */ 501 return written;
501/* if(file->f_dentry->d_inode->i_mapping) {
502 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
503 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
504 }*/
505/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
506
507 /* BB we should make timer configurable - perhaps
508 by simply calling cifs_revalidate here */
509 /* invalidate_remote_inode(file->f_dentry->d_inode);*/
510 return generic_file_read(file,read_data,read_size,poffset);
511 }
512} 502}
513 503
514static ssize_t 504static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
515cifs_write_wrapper(struct file * file, const char __user *write_data, 505 size_t count, loff_t pos)
516 size_t write_size, loff_t * poffset)
517{ 506{
507 struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
518 ssize_t written; 508 ssize_t written;
519 509
520 if(file->f_dentry == NULL) 510 written = generic_file_aio_write(iocb, buf, count, pos);
521 return -EIO; 511 if (!CIFS_I(inode)->clientCanCacheAll)
522 else if(file->f_dentry->d_inode == NULL) 512 filemap_fdatawrite(inode->i_mapping);
523 return -EIO;
524
525 cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
526
527 written = generic_file_write(file,write_data,write_size,poffset);
528 if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
529 if(file->f_dentry->d_inode->i_mapping) {
530 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
531 }
532 }
533 return written; 513 return written;
534} 514}
535 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}
536 526
537static struct file_system_type cifs_fs_type = { 527static struct file_system_type cifs_fs_type = {
538 .owner = THIS_MODULE, 528 .owner = THIS_MODULE,
@@ -594,8 +584,12 @@ struct inode_operations cifs_symlink_inode_ops = {
594}; 584};
595 585
596struct file_operations cifs_file_ops = { 586struct file_operations cifs_file_ops = {
597 .read = cifs_read_wrapper, 587 .read = do_sync_read,
598 .write = cifs_write_wrapper, 588 .write = do_sync_write,
589 .readv = generic_file_readv,
590 .writev = cifs_file_writev,
591 .aio_read = generic_file_aio_read,
592 .aio_write = cifs_file_aio_write,
599 .open = cifs_open, 593 .open = cifs_open,
600 .release = cifs_close, 594 .release = cifs_close,
601 .lock = cifs_lock, 595 .lock = cifs_lock,
@@ -603,15 +597,12 @@ struct file_operations cifs_file_ops = {
603 .flush = cifs_flush, 597 .flush = cifs_flush,
604 .mmap = cifs_file_mmap, 598 .mmap = cifs_file_mmap,
605 .sendfile = generic_file_sendfile, 599 .sendfile = generic_file_sendfile,
600 .llseek = cifs_llseek,
606#ifdef CONFIG_CIFS_POSIX 601#ifdef CONFIG_CIFS_POSIX
607 .ioctl = cifs_ioctl, 602 .ioctl = cifs_ioctl,
608#endif /* CONFIG_CIFS_POSIX */ 603#endif /* CONFIG_CIFS_POSIX */
609 604
610#ifdef CONFIG_CIFS_EXPERIMENTAL 605#ifdef CONFIG_CIFS_EXPERIMENTAL
611 .readv = generic_file_readv,
612 .writev = generic_file_writev,
613 .aio_read = generic_file_aio_read,
614 .aio_write = generic_file_aio_write,
615 .dir_notify = cifs_dir_notify, 606 .dir_notify = cifs_dir_notify,
616#endif /* CONFIG_CIFS_EXPERIMENTAL */ 607#endif /* CONFIG_CIFS_EXPERIMENTAL */
617}; 608};
@@ -630,12 +621,53 @@ struct file_operations cifs_file_direct_ops = {
630#ifdef CONFIG_CIFS_POSIX 621#ifdef CONFIG_CIFS_POSIX
631 .ioctl = cifs_ioctl, 622 .ioctl = cifs_ioctl,
632#endif /* CONFIG_CIFS_POSIX */ 623#endif /* CONFIG_CIFS_POSIX */
624 .llseek = cifs_llseek,
625#ifdef CONFIG_CIFS_EXPERIMENTAL
626 .dir_notify = cifs_dir_notify,
627#endif /* CONFIG_CIFS_EXPERIMENTAL */
628};
629struct file_operations cifs_file_nobrl_ops = {
630 .read = do_sync_read,
631 .write = do_sync_write,
632 .readv = generic_file_readv,
633 .writev = cifs_file_writev,
634 .aio_read = generic_file_aio_read,
635 .aio_write = cifs_file_aio_write,
636 .open = cifs_open,
637 .release = cifs_close,
638 .fsync = cifs_fsync,
639 .flush = cifs_flush,
640 .mmap = cifs_file_mmap,
641 .sendfile = generic_file_sendfile,
642 .llseek = cifs_llseek,
643#ifdef CONFIG_CIFS_POSIX
644 .ioctl = cifs_ioctl,
645#endif /* CONFIG_CIFS_POSIX */
633 646
634#ifdef CONFIG_CIFS_EXPERIMENTAL 647#ifdef CONFIG_CIFS_EXPERIMENTAL
635 .dir_notify = cifs_dir_notify, 648 .dir_notify = cifs_dir_notify,
636#endif /* CONFIG_CIFS_EXPERIMENTAL */ 649#endif /* CONFIG_CIFS_EXPERIMENTAL */
637}; 650};
638 651
652struct file_operations cifs_file_direct_nobrl_ops = {
653 /* no mmap, no aio, no readv -
654 BB reevaluate whether they can be done with directio, no cache */
655 .read = cifs_user_read,
656 .write = cifs_user_write,
657 .open = cifs_open,
658 .release = cifs_close,
659 .fsync = cifs_fsync,
660 .flush = cifs_flush,
661 .sendfile = generic_file_sendfile, /* BB removeme BB */
662#ifdef CONFIG_CIFS_POSIX
663 .ioctl = cifs_ioctl,
664#endif /* CONFIG_CIFS_POSIX */
665 .llseek = cifs_llseek,
666#ifdef CONFIG_CIFS_EXPERIMENTAL
667 .dir_notify = cifs_dir_notify,
668#endif /* CONFIG_CIFS_EXPERIMENTAL */
669};
670
639struct file_operations cifs_dir_ops = { 671struct file_operations cifs_dir_ops = {
640 .readdir = cifs_readdir, 672 .readdir = cifs_readdir,
641 .release = cifs_closedir, 673 .release = cifs_closedir,
@@ -714,7 +746,7 @@ cifs_init_request_bufs(void)
714 kmem_cache_destroy(cifs_req_cachep); 746 kmem_cache_destroy(cifs_req_cachep);
715 return -ENOMEM; 747 return -ENOMEM;
716 } 748 }
717 /* 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
718 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
719 sufficient for path based requests). A smaller size would have 751 sufficient for path based requests). A smaller size would have
720 been more efficient (compacting multiple slab items on one 4k page) 752 been more efficient (compacting multiple slab items on one 4k page)
@@ -723,7 +755,8 @@ cifs_init_request_bufs(void)
723 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)
724 alloc of large cifs buffers even when page debugging is on */ 756 alloc of large cifs buffers even when page debugging is on */
725 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", 757 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
726 MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); 758 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
759 NULL, NULL);
727 if (cifs_sm_req_cachep == NULL) { 760 if (cifs_sm_req_cachep == NULL) {
728 mempool_destroy(cifs_req_poolp); 761 mempool_destroy(cifs_req_poolp);
729 kmem_cache_destroy(cifs_req_cachep); 762 kmem_cache_destroy(cifs_req_cachep);
@@ -841,9 +874,9 @@ static int cifs_oplock_thread(void * dummyarg)
841 DeleteOplockQEntry(oplock_item); 874 DeleteOplockQEntry(oplock_item);
842 /* can not grab inode sem here since it would 875 /* can not grab inode sem here since it would
843 deadlock when oplock received on delete 876 deadlock when oplock received on delete
844 since vfs_unlink holds the i_sem across 877 since vfs_unlink holds the i_mutex across
845 the call */ 878 the call */
846 /* down(&inode->i_sem);*/ 879 /* mutex_lock(&inode->i_mutex);*/
847 if (S_ISREG(inode->i_mode)) { 880 if (S_ISREG(inode->i_mode)) {
848 rc = filemap_fdatawrite(inode->i_mapping); 881 rc = filemap_fdatawrite(inode->i_mapping);
849 if(CIFS_I(inode)->clientCanCacheRead == 0) { 882 if(CIFS_I(inode)->clientCanCacheRead == 0) {
@@ -852,7 +885,7 @@ static int cifs_oplock_thread(void * dummyarg)
852 } 885 }
853 } else 886 } else
854 rc = 0; 887 rc = 0;
855 /* up(&inode->i_sem);*/ 888 /* mutex_unlock(&inode->i_mutex);*/
856 if (rc) 889 if (rc)
857 CIFS_I(inode)->write_behind_rc = rc; 890 CIFS_I(inode)->write_behind_rc = rc;
858 cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); 891 cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
@@ -882,6 +915,9 @@ static int cifs_oplock_thread(void * dummyarg)
882 915
883static int cifs_dnotify_thread(void * dummyarg) 916static int cifs_dnotify_thread(void * dummyarg)
884{ 917{
918 struct list_head *tmp;
919 struct cifsSesInfo *ses;
920
885 daemonize("cifsdnotifyd"); 921 daemonize("cifsdnotifyd");
886 allow_signal(SIGTERM); 922 allow_signal(SIGTERM);
887 923
@@ -890,7 +926,19 @@ static int cifs_dnotify_thread(void * dummyarg)
890 if(try_to_freeze()) 926 if(try_to_freeze())
891 continue; 927 continue;
892 set_current_state(TASK_INTERRUPTIBLE); 928 set_current_state(TASK_INTERRUPTIBLE);
893 schedule_timeout(39*HZ); 929 schedule_timeout(15*HZ);
930 read_lock(&GlobalSMBSeslock);
931 /* check if any stuck requests that need
932 to be woken up and wakeq so the
933 thread can wake up and error out */
934 list_for_each(tmp, &GlobalSMBSessionList) {
935 ses = list_entry(tmp, struct cifsSesInfo,
936 cifsSessionList);
937 if(ses && ses->server &&
938 atomic_read(&ses->server->inFlight))
939 wake_up_all(&ses->server->response_q);
940 }
941 read_unlock(&GlobalSMBSeslock);
894 } while(!signal_pending(current)); 942 } while(!signal_pending(current));
895 complete_and_exit (&cifs_dnotify_exited, 0); 943 complete_and_exit (&cifs_dnotify_exited, 0);
896} 944}
@@ -920,6 +968,12 @@ init_cifs(void)
920 atomic_set(&tconInfoReconnectCount, 0); 968 atomic_set(&tconInfoReconnectCount, 0);
921 969
922 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
923 atomic_set(&midCount, 0); 977 atomic_set(&midCount, 0);
924 GlobalCurrentXid = 0; 978 GlobalCurrentXid = 0;
925 GlobalTotalActiveXid = 0; 979 GlobalTotalActiveXid = 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 1223fa81dbd2..821a8eb22559 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -63,6 +63,8 @@ extern struct inode_operations cifs_symlink_inode_ops;
63/* Functions related to files and directories */ 63/* Functions related to files and directories */
64extern struct file_operations cifs_file_ops; 64extern struct file_operations cifs_file_ops;
65extern struct file_operations cifs_file_direct_ops; /* if directio mount */ 65extern struct file_operations cifs_file_direct_ops; /* if directio mount */
66extern struct file_operations cifs_file_nobrl_ops;
67extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
66extern int cifs_open(struct inode *inode, struct file *file); 68extern int cifs_open(struct inode *inode, struct file *file);
67extern int cifs_close(struct inode *inode, struct file *file); 69extern int cifs_close(struct inode *inode, struct file *file);
68extern int cifs_closedir(struct inode *inode, struct file *file); 70extern int cifs_closedir(struct inode *inode, struct file *file);
@@ -97,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
97extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
98extern int cifs_ioctl (struct inode * inode, struct file * filep, 100extern int cifs_ioctl (struct inode * inode, struct file * filep,
99 unsigned int command, unsigned long arg); 101 unsigned int command, unsigned long arg);
100#define CIFS_VERSION "1.39" 102#define CIFS_VERSION "1.40"
101#endif /* _CIFSFS_H */ 103#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1ba08f8c5bc4..7bed27601ce5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -233,6 +233,8 @@ struct cifsTconInfo {
233 atomic_t num_hardlinks; 233 atomic_t num_hardlinks;
234 atomic_t num_symlinks; 234 atomic_t num_symlinks;
235 atomic_t num_locks; 235 atomic_t num_locks;
236 atomic_t num_acl_get;
237 atomic_t num_acl_set;
236#ifdef CONFIG_CIFS_STATS2 238#ifdef CONFIG_CIFS_STATS2
237 unsigned long long time_writes; 239 unsigned long long time_writes;
238 unsigned long long time_reads; 240 unsigned long long time_reads;
@@ -285,6 +287,7 @@ struct cifs_search_info {
285 unsigned endOfSearch:1; 287 unsigned endOfSearch:1;
286 unsigned emptyDir:1; 288 unsigned emptyDir:1;
287 unsigned unicode:1; 289 unsigned unicode:1;
290 unsigned smallBuf:1; /* so we know which buf_release function to call */
288}; 291};
289 292
290struct cifsFileInfo { 293struct cifsFileInfo {
@@ -420,7 +423,12 @@ struct dir_notify_req {
420#define MID_RESPONSE_RECEIVED 4 423#define MID_RESPONSE_RECEIVED 4
421#define MID_RETRY_NEEDED 8 /* session closed while this request out */ 424#define MID_RETRY_NEEDED 8 /* session closed while this request out */
422#define MID_NO_RESP_NEEDED 0x10 425#define MID_NO_RESP_NEEDED 0x10
423#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */ 426
427/* Types of response buffer returned from SendReceive2 */
428#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
429#define CIFS_SMALL_BUFFER 1
430#define CIFS_LARGE_BUFFER 2
431#define CIFS_IOVEC 4 /* array of response buffers */
424 432
425/* 433/*
426 ***************************************************************** 434 *****************************************************************
@@ -505,8 +513,12 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
505GLOBAL_EXTERN atomic_t tconInfoReconnectCount; 513GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
506 514
507/* Various Debug counters to remove someday (BB) */ 515/* Various Debug counters to remove someday (BB) */
508GLOBAL_EXTERN atomic_t bufAllocCount; 516GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */
509GLOBAL_EXTERN atomic_t smBufAllocCount; 517#ifdef CONFIG_CIFS_STATS2
518GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
519GLOBAL_EXTERN atomic_t totSmBufAllocCount;
520#endif
521GLOBAL_EXTERN atomic_t smBufAllocCount;
510GLOBAL_EXTERN atomic_t midCount; 522GLOBAL_EXTERN atomic_t midCount;
511 523
512/* Misc globals */ 524/* Misc globals */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 48a05b9df7eb..cc2471094ca5 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/*****************************************************************
@@ -524,7 +528,7 @@ typedef union smb_com_session_setup_andx {
524 /* STRING PrimaryDomain */ 528 /* STRING PrimaryDomain */
525 /* STRING NativeOS */ 529 /* STRING NativeOS */
526 /* STRING NativeLanMan */ 530 /* STRING NativeLanMan */
527 } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */ 531 } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
528 532
529 struct { /* default (NTLM) response format */ 533 struct { /* default (NTLM) response format */
530 struct smb_hdr hdr; /* wct = 3 */ 534 struct smb_hdr hdr; /* wct = 3 */
@@ -536,7 +540,7 @@ typedef union smb_com_session_setup_andx {
536 unsigned char NativeOS[1]; /* followed by */ 540 unsigned char NativeOS[1]; /* followed by */
537/* unsigned char * NativeLanMan; */ 541/* unsigned char * NativeLanMan; */
538/* unsigned char * PrimaryDomain; */ 542/* unsigned char * PrimaryDomain; */
539 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */ 543 } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
540} __attribute__((packed)) SESSION_SETUP_ANDX; 544} __attribute__((packed)) SESSION_SETUP_ANDX;
541 545
542#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" 546#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
@@ -603,7 +607,9 @@ typedef struct smb_com_logoff_andx_rsp {
603 __u16 ByteCount; 607 __u16 ByteCount;
604} __attribute__((packed)) LOGOFF_ANDX_RSP; 608} __attribute__((packed)) LOGOFF_ANDX_RSP;
605 609
606typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */ 610typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
611 tree_connect PDU to effect disconnect */
612 /* tdis is probably simplest SMB PDU */
607 struct { 613 struct {
608 struct smb_hdr hdr; /* wct = 0 */ 614 struct smb_hdr hdr; /* wct = 0 */
609 __u16 ByteCount; /* bcc = 0 */ 615 __u16 ByteCount; /* bcc = 0 */
@@ -1001,10 +1007,49 @@ typedef struct smb_com_setattr_rsp {
1001 1007
1002/* empty wct response to setattr */ 1008/* empty wct response to setattr */
1003 1009
1004/***************************************************/ 1010/*******************************************************/
1005/* NT Transact structure defintions follow */ 1011/* NT Transact structure defintions follow */
1006/* Currently only ioctl and notify are implemented */ 1012/* Currently only ioctl, acl (get security descriptor) */
1007/***************************************************/ 1013/* and notify are implemented */
1014/*******************************************************/
1015typedef struct smb_com_ntransact_req {
1016 struct smb_hdr hdr; /* wct >= 19 */
1017 __u8 MaxSetupCount;
1018 __u16 Reserved;
1019 __le32 TotalParameterCount;
1020 __le32 TotalDataCount;
1021 __le32 MaxParameterCount;
1022 __le32 MaxDataCount;
1023 __le32 ParameterCount;
1024 __le32 ParameterOffset;
1025 __le32 DataCount;
1026 __le32 DataOffset;
1027 __u8 SetupCount; /* four setup words follow subcommand */
1028 /* SNIA spec incorrectly included spurious pad here */
1029 __le16 SubCommand; /* 2 = IOCTL/FSCTL */
1030 /* SetupCount words follow then */
1031 __le16 ByteCount;
1032 __u8 Pad[3];
1033 __u8 Parms[0];
1034} __attribute__((packed)) NTRANSACT_REQ;
1035
1036typedef struct smb_com_ntransact_rsp {
1037 struct smb_hdr hdr; /* wct = 18 */
1038 __u8 Reserved[3];
1039 __le32 TotalParameterCount;
1040 __le32 TotalDataCount;
1041 __le32 ParameterCount;
1042 __le32 ParameterOffset;
1043 __le32 ParameterDisplacement;
1044 __le32 DataCount;
1045 __le32 DataOffset;
1046 __le32 DataDisplacement;
1047 __u8 SetupCount; /* 0 */
1048 __u16 ByteCount;
1049 /* __u8 Pad[3]; */
1050 /* parms and data follow */
1051} __attribute__((packed)) NTRANSACT_RSP;
1052
1008typedef struct smb_com_transaction_ioctl_req { 1053typedef struct smb_com_transaction_ioctl_req {
1009 struct smb_hdr hdr; /* wct = 23 */ 1054 struct smb_hdr hdr; /* wct = 23 */
1010 __u8 MaxSetupCount; 1055 __u8 MaxSetupCount;
@@ -1019,11 +1064,11 @@ typedef struct smb_com_transaction_ioctl_req {
1019 __le32 DataOffset; 1064 __le32 DataOffset;
1020 __u8 SetupCount; /* four setup words follow subcommand */ 1065 __u8 SetupCount; /* four setup words follow subcommand */
1021 /* SNIA spec incorrectly included spurious pad here */ 1066 /* SNIA spec incorrectly included spurious pad here */
1022 __le16 SubCommand;/* 2 = IOCTL/FSCTL */ 1067 __le16 SubCommand; /* 2 = IOCTL/FSCTL */
1023 __le32 FunctionCode; 1068 __le32 FunctionCode;
1024 __u16 Fid; 1069 __u16 Fid;
1025 __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/ 1070 __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
1026 __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/ 1071 __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
1027 __le16 ByteCount; 1072 __le16 ByteCount;
1028 __u8 Pad[3]; 1073 __u8 Pad[3];
1029 __u8 Data[1]; 1074 __u8 Data[1];
@@ -1043,9 +1088,35 @@ typedef struct smb_com_transaction_ioctl_rsp {
1043 __u8 SetupCount; /* 1 */ 1088 __u8 SetupCount; /* 1 */
1044 __le16 ReturnedDataLen; 1089 __le16 ReturnedDataLen;
1045 __u16 ByteCount; 1090 __u16 ByteCount;
1046 __u8 Pad[3];
1047} __attribute__((packed)) TRANSACT_IOCTL_RSP; 1091} __attribute__((packed)) TRANSACT_IOCTL_RSP;
1048 1092
1093#define CIFS_ACL_OWNER 1
1094#define CIFS_ACL_GROUP 2
1095#define CIFS_ACL_DACL 4
1096#define CIFS_ACL_SACL 8
1097
1098typedef struct smb_com_transaction_qsec_req {
1099 struct smb_hdr hdr; /* wct = 19 */
1100 __u8 MaxSetupCount;
1101 __u16 Reserved;
1102 __le32 TotalParameterCount;
1103 __le32 TotalDataCount;
1104 __le32 MaxParameterCount;
1105 __le32 MaxDataCount;
1106 __le32 ParameterCount;
1107 __le32 ParameterOffset;
1108 __le32 DataCount;
1109 __le32 DataOffset;
1110 __u8 SetupCount; /* no setup words follow subcommand */
1111 /* SNIA spec incorrectly included spurious pad here */
1112 __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
1113 __le16 ByteCount; /* bcc = 3 + 8 */
1114 __u8 Pad[3];
1115 __u16 Fid;
1116 __u16 Reserved2;
1117 __le32 AclFlags;
1118} __attribute__((packed)) QUERY_SEC_DESC_REQ;
1119
1049typedef struct smb_com_transaction_change_notify_req { 1120typedef struct smb_com_transaction_change_notify_req {
1050 struct smb_hdr hdr; /* wct = 23 */ 1121 struct smb_hdr hdr; /* wct = 23 */
1051 __u8 MaxSetupCount; 1122 __u8 MaxSetupCount;
@@ -1066,10 +1137,12 @@ typedef struct smb_com_transaction_change_notify_req {
1066 __u8 WatchTree; /* 1 = Monitor subdirectories */ 1137 __u8 WatchTree; /* 1 = Monitor subdirectories */
1067 __u8 Reserved2; 1138 __u8 Reserved2;
1068 __le16 ByteCount; 1139 __le16 ByteCount;
1069/* __u8 Pad[3];*/ 1140/* __u8 Pad[3];*/
1070/* __u8 Data[1];*/ 1141/* __u8 Data[1];*/
1071} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; 1142} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
1072 1143
1144/* BB eventually change to use generic ntransact rsp struct
1145 and validation routine */
1073typedef struct smb_com_transaction_change_notify_rsp { 1146typedef struct smb_com_transaction_change_notify_rsp {
1074 struct smb_hdr hdr; /* wct = 18 */ 1147 struct smb_hdr hdr; /* wct = 18 */
1075 __u8 Reserved[3]; 1148 __u8 Reserved[3];
@@ -2025,6 +2098,12 @@ typedef struct {
2025} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ 2098} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
2026 2099
2027 2100
2101struct win_dev {
2102 unsigned char type[8]; /* IntxCHR or IntxBLK */
2103 __le64 major;
2104 __le64 minor;
2105} __attribute__((packed));
2106
2028struct gea { 2107struct gea {
2029 unsigned char name_len; 2108 unsigned char name_len;
2030 char name[1]; 2109 char name[1];
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f4c5ce..3c03aadaff0c 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);
@@ -297,6 +299,9 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
297 const char *fileName, const char * ea_name, 299 const char *fileName, const char * ea_name,
298 const void * ea_value, const __u16 ea_value_len, 300 const void * ea_value, const __u16 ea_value_len,
299 const struct nls_table *nls_codepage, int remap_special_chars); 301 const struct nls_table *nls_codepage, int remap_special_chars);
302extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
303 __u16 fid, char *acl_inf, const int buflen,
304 const int acl_type /* ACCESS vs. DEFAULT */);
300extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, 305extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
301 const unsigned char *searchName, 306 const unsigned char *searchName,
302 char *acl_inf, const int buflen,const int acl_type, 307 char *acl_inf, const int buflen,const int acl_type,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a53c596e1082..217323b0c896 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -37,6 +37,7 @@
37#include "cifsproto.h" 37#include "cifsproto.h"
38#include "cifs_unicode.h" 38#include "cifs_unicode.h"
39#include "cifs_debug.h" 39#include "cifs_debug.h"
40#include "cifsacl.h"
40 41
41#ifdef CONFIG_CIFS_POSIX 42#ifdef CONFIG_CIFS_POSIX
42static struct { 43static struct {
@@ -90,6 +91,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
90 check for tcp and smb session status done differently 91 check for tcp and smb session status done differently
91 for those three - in the calling routine */ 92 for those three - in the calling routine */
92 if(tcon) { 93 if(tcon) {
94 if(tcon->tidStatus == CifsExiting) {
95 /* only tree disconnect, open, and write,
96 (and ulogoff which does not have tcon)
97 are allowed as we start force umount */
98 if((smb_command != SMB_COM_WRITE_ANDX) &&
99 (smb_command != SMB_COM_OPEN_ANDX) &&
100 (smb_command != SMB_COM_TREE_DISCONNECT)) {
101 cFYI(1,("can not send cmd %d while umounting",
102 smb_command));
103 return -ENODEV;
104 }
105 }
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 106 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){ 107 (tcon->ses->server)){
95 struct nls_table *nls_codepage; 108 struct nls_table *nls_codepage;
@@ -187,6 +200,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
187 check for tcp and smb session status done differently 200 check for tcp and smb session status done differently
188 for those three - in the calling routine */ 201 for those three - in the calling routine */
189 if(tcon) { 202 if(tcon) {
203 if(tcon->tidStatus == CifsExiting) {
204 /* only tree disconnect, open, and write,
205 (and ulogoff which does not have tcon)
206 are allowed as we start force umount */
207 if((smb_command != SMB_COM_WRITE_ANDX) &&
208 (smb_command != SMB_COM_OPEN_ANDX) &&
209 (smb_command != SMB_COM_TREE_DISCONNECT)) {
210 cFYI(1,("can not send cmd %d while umounting",
211 smb_command));
212 return -ENODEV;
213 }
214 }
215
190 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 216 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
191 (tcon->ses->server)){ 217 (tcon->ses->server)){
192 struct nls_table *nls_codepage; 218 struct nls_table *nls_codepage;
@@ -347,8 +373,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
347 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, 373 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
348 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
349 if (rc == 0) { 375 if (rc == 0) {
350 server->secMode = pSMBr->SecurityMode; 376 server->secMode = pSMBr->SecurityMode;
351 server->secType = NTLM; /* BB override default for 377 if((server->secMode & SECMODE_USER) == 0)
378 cFYI(1,("share mode security"));
379 server->secType = NTLM; /* BB override default for
352 NTLMv2 or kerberos v5 */ 380 NTLMv2 or kerberos v5 */
353 /* one byte - no need to convert this or EncryptionKeyLen 381 /* one byte - no need to convert this or EncryptionKeyLen
354 from little endian */ 382 from little endian */
@@ -358,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
358 min(le32_to_cpu(pSMBr->MaxBufferSize), 386 min(le32_to_cpu(pSMBr->MaxBufferSize),
359 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 387 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
360 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 388 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
361 cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); 389 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
362 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 390 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
363 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 391 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
364 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); 392 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
@@ -386,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
386 (server->server_GUID, 414 (server->server_GUID,
387 pSMBr->u.extended_response. 415 pSMBr->u.extended_response.
388 GUID, 16) != 0) { 416 GUID, 16) != 0) {
389 cFYI(1, 417 cFYI(1, ("server UID changed"));
390 ("UID of server does not match previous connection to same ip address"));
391 memcpy(server-> 418 memcpy(server->
392 server_GUID, 419 server_GUID,
393 pSMBr->u. 420 pSMBr->u.
@@ -933,21 +960,19 @@ openRetry:
933 return rc; 960 return rc;
934} 961}
935 962
936/* If no buffer passed in, then caller wants to do the copy
937 as in the case of readpages so the SMB buffer must be
938 freed by the caller */
939
940int 963int
941CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 964CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
942 const int netfid, const unsigned int count, 965 const int netfid, const unsigned int count,
943 const __u64 lseek, unsigned int *nbytes, char **buf) 966 const __u64 lseek, unsigned int *nbytes, char **buf,
967 int * pbuf_type)
944{ 968{
945 int rc = -EACCES; 969 int rc = -EACCES;
946 READ_REQ *pSMB = NULL; 970 READ_REQ *pSMB = NULL;
947 READ_RSP *pSMBr = NULL; 971 READ_RSP *pSMBr = NULL;
948 char *pReadData = NULL; 972 char *pReadData = NULL;
949 int bytes_returned;
950 int wct; 973 int wct;
974 int resp_buf_type = 0;
975 struct kvec iov[1];
951 976
952 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 977 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
953 if(tcon->ses->capabilities & CAP_LARGE_FILES) 978 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -956,8 +981,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
956 wct = 10; /* old style read */ 981 wct = 10; /* old style read */
957 982
958 *nbytes = 0; 983 *nbytes = 0;
959 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, 984 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
960 (void **) &pSMBr);
961 if (rc) 985 if (rc)
962 return rc; 986 return rc;
963 987
@@ -965,13 +989,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
965 if (tcon->ses->server == NULL) 989 if (tcon->ses->server == NULL)
966 return -ECONNABORTED; 990 return -ECONNABORTED;
967 991
968 pSMB->AndXCommand = 0xFF; /* none */ 992 pSMB->AndXCommand = 0xFF; /* none */
969 pSMB->Fid = netfid; 993 pSMB->Fid = netfid;
970 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 994 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
971 if(wct == 12) 995 if(wct == 12)
972 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 996 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
973 else if((lseek >> 32) > 0) /* can not handle this big offset for old */ 997 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
974 return -EIO; 998 return -EIO;
975 999
976 pSMB->Remaining = 0; 1000 pSMB->Remaining = 0;
977 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 1001 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -980,14 +1004,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
980 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ 1004 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
981 else { 1005 else {
982 /* old style read */ 1006 /* old style read */
983 struct smb_com_readx_req * pSMBW = 1007 struct smb_com_readx_req * pSMBW =
984 (struct smb_com_readx_req *)pSMB; 1008 (struct smb_com_readx_req *)pSMB;
985 pSMBW->ByteCount = 0; 1009 pSMBW->ByteCount = 0;
986 } 1010 }
987 1011
988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1012 iov[0].iov_base = (char *)pSMB;
989 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1013 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1014 rc = SendReceive2(xid, tcon->ses, iov,
1015 1 /* num iovecs */,
1016 &resp_buf_type, 0);
990 cifs_stats_inc(&tcon->num_reads); 1017 cifs_stats_inc(&tcon->num_reads);
1018 pSMBr = (READ_RSP *)iov[0].iov_base;
991 if (rc) { 1019 if (rc) {
992 cERROR(1, ("Send error in read = %d", rc)); 1020 cERROR(1, ("Send error in read = %d", rc));
993 } else { 1021 } else {
@@ -997,33 +1025,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
997 *nbytes = data_length; 1025 *nbytes = data_length;
998 1026
999 /*check that DataLength would not go beyond end of SMB */ 1027 /*check that DataLength would not go beyond end of SMB */
1000 if ((data_length > CIFSMaxBufSize) 1028 if ((data_length > CIFSMaxBufSize)
1001 || (data_length > count)) { 1029 || (data_length > count)) {
1002 cFYI(1,("bad length %d for count %d",data_length,count)); 1030 cFYI(1,("bad length %d for count %d",data_length,count));
1003 rc = -EIO; 1031 rc = -EIO;
1004 *nbytes = 0; 1032 *nbytes = 0;
1005 } else { 1033 } else {
1006 pReadData = 1034 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1007 (char *) (&pSMBr->hdr.Protocol) +
1008 le16_to_cpu(pSMBr->DataOffset); 1035 le16_to_cpu(pSMBr->DataOffset);
1009/* if(rc = copy_to_user(buf, pReadData, data_length)) { 1036/* if(rc = copy_to_user(buf, pReadData, data_length)) {
1010 cERROR(1,("Faulting on read rc = %d",rc)); 1037 cERROR(1,("Faulting on read rc = %d",rc));
1011 rc = -EFAULT; 1038 rc = -EFAULT;
1012 }*/ /* can not use copy_to_user when using page cache*/ 1039 }*/ /* can not use copy_to_user when using page cache*/
1013 if(*buf) 1040 if(*buf)
1014 memcpy(*buf,pReadData,data_length); 1041 memcpy(*buf,pReadData,data_length);
1015 } 1042 }
1016 } 1043 }
1017 if(*buf)
1018 cifs_buf_release(pSMB);
1019 else
1020 *buf = (char *)pSMB;
1021 1044
1022 /* Note: On -EAGAIN error only caller can retry on handle based calls 1045 cifs_small_buf_release(pSMB);
1046 if(*buf) {
1047 if(resp_buf_type == CIFS_SMALL_BUFFER)
1048 cifs_small_buf_release(iov[0].iov_base);
1049 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1050 cifs_buf_release(iov[0].iov_base);
1051 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1052 *buf = iov[0].iov_base;
1053 if(resp_buf_type == CIFS_SMALL_BUFFER)
1054 *pbuf_type = CIFS_SMALL_BUFFER;
1055 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1056 *pbuf_type = CIFS_LARGE_BUFFER;
1057 }
1058
1059 /* Note: On -EAGAIN error only caller can retry on handle based calls
1023 since file handle passed in no longer valid */ 1060 since file handle passed in no longer valid */
1024 return rc; 1061 return rc;
1025} 1062}
1026 1063
1064
1027int 1065int
1028CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 1066CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1029 const int netfid, const unsigned int count, 1067 const int netfid, const unsigned int count,
@@ -1130,7 +1168,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1130 return rc; 1168 return rc;
1131} 1169}
1132 1170
1133#ifdef CONFIG_CIFS_EXPERIMENTAL
1134int 1171int
1135CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1172CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1136 const int netfid, const unsigned int count, 1173 const int netfid, const unsigned int count,
@@ -1139,10 +1176,12 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1139{ 1176{
1140 int rc = -EACCES; 1177 int rc = -EACCES;
1141 WRITE_REQ *pSMB = NULL; 1178 WRITE_REQ *pSMB = NULL;
1142 int bytes_returned, wct; 1179 int wct;
1143 int smb_hdr_len; 1180 int smb_hdr_len;
1181 int resp_buf_type = 0;
1182
1183 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1144 1184
1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1146 if(tcon->ses->capabilities & CAP_LARGE_FILES) 1185 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1147 wct = 14; 1186 wct = 14;
1148 else 1187 else
@@ -1183,22 +1222,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1183 pSMBW->ByteCount = cpu_to_le16(count + 5); 1222 pSMBW->ByteCount = cpu_to_le16(count + 5);
1184 } 1223 }
1185 iov[0].iov_base = pSMB; 1224 iov[0].iov_base = pSMB;
1186 iov[0].iov_len = smb_hdr_len + 4; 1225 if(wct == 14)
1226 iov[0].iov_len = smb_hdr_len + 4;
1227 else /* wct == 12 pad bigger by four bytes */
1228 iov[0].iov_len = smb_hdr_len + 8;
1229
1187 1230
1188 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned, 1231 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1189 long_op); 1232 long_op);
1190 cifs_stats_inc(&tcon->num_writes); 1233 cifs_stats_inc(&tcon->num_writes);
1191 if (rc) { 1234 if (rc) {
1192 cFYI(1, ("Send error Write2 = %d", rc)); 1235 cFYI(1, ("Send error Write2 = %d", rc));
1193 *nbytes = 0; 1236 *nbytes = 0;
1237 } else if(resp_buf_type == 0) {
1238 /* presumably this can not happen, but best to be safe */
1239 rc = -EIO;
1240 *nbytes = 0;
1194 } else { 1241 } else {
1195 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; 1242 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1196 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1243 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1197 *nbytes = (*nbytes) << 16; 1244 *nbytes = (*nbytes) << 16;
1198 *nbytes += le16_to_cpu(pSMBr->Count); 1245 *nbytes += le16_to_cpu(pSMBr->Count);
1199 } 1246 }
1200 1247
1201 cifs_small_buf_release(pSMB); 1248 cifs_small_buf_release(pSMB);
1249 if(resp_buf_type == CIFS_SMALL_BUFFER)
1250 cifs_small_buf_release(iov[0].iov_base);
1251 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1252 cifs_buf_release(iov[0].iov_base);
1202 1253
1203 /* Note: On -EAGAIN error only caller can retry on handle based calls 1254 /* Note: On -EAGAIN error only caller can retry on handle based calls
1204 since file handle passed in no longer valid */ 1255 since file handle passed in no longer valid */
@@ -1207,8 +1258,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1207} 1258}
1208 1259
1209 1260
1210#endif /* CIFS_EXPERIMENTAL */
1211
1212int 1261int
1213CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1262CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1214 const __u16 smb_file_id, const __u64 len, 1263 const __u16 smb_file_id, const __u64 len,
@@ -1553,7 +1602,7 @@ createSymLinkRetry:
1553 1602
1554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1603 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1555 name_len = 1604 name_len =
1556 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX 1605 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1557 /* find define for this maxpathcomponent */ 1606 /* find define for this maxpathcomponent */
1558 , nls_codepage); 1607 , nls_codepage);
1559 name_len++; /* trailing null */ 1608 name_len++; /* trailing null */
@@ -1577,7 +1626,7 @@ createSymLinkRetry:
1577 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 1626 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1627 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1579 name_len_target = 1628 name_len_target =
1580 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX 1629 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1581 /* find define for this maxpathcomponent */ 1630 /* find define for this maxpathcomponent */
1582 , nls_codepage); 1631 , nls_codepage);
1583 name_len_target++; /* trailing null */ 1632 name_len_target++; /* trailing null */
@@ -1803,7 +1852,7 @@ querySymLinkRetry:
1803 1852
1804 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1853 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1805 name_len = 1854 name_len =
1806 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 1855 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1807 /* find define for this maxpathcomponent */ 1856 /* find define for this maxpathcomponent */
1808 , nls_codepage); 1857 , nls_codepage);
1809 name_len++; /* trailing null */ 1858 name_len++; /* trailing null */
@@ -1860,7 +1909,7 @@ querySymLinkRetry:
1860 min_t(const int, buflen,count) / 2); 1909 min_t(const int, buflen,count) / 2);
1861 /* BB FIXME investigate remapping reserved chars here */ 1910 /* BB FIXME investigate remapping reserved chars here */
1862 cifs_strfromUCS_le(symlinkinfo, 1911 cifs_strfromUCS_le(symlinkinfo,
1863 (wchar_t *) ((char *)&pSMBr->hdr.Protocol + 1912 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1864 data_offset), 1913 data_offset),
1865 name_len, nls_codepage); 1914 name_len, nls_codepage);
1866 } else { 1915 } else {
@@ -1879,6 +1928,90 @@ querySymLinkRetry:
1879 return rc; 1928 return rc;
1880} 1929}
1881 1930
1931/* Initialize NT TRANSACT SMB into small smb request buffer.
1932 This assumes that all NT TRANSACTS that we init here have
1933 total parm and data under about 400 bytes (to fit in small cifs
1934 buffer size), which is the case so far, it easily fits. NB:
1935 Setup words themselves and ByteCount
1936 MaxSetupCount (size of returned setup area) and
1937 MaxParameterCount (returned parms size) must be set by caller */
1938static int
1939smb_init_ntransact(const __u16 sub_command, const int setup_count,
1940 const int parm_len, struct cifsTconInfo *tcon,
1941 void ** ret_buf)
1942{
1943 int rc;
1944 __u32 temp_offset;
1945 struct smb_com_ntransact_req * pSMB;
1946
1947 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
1948 (void **)&pSMB);
1949 if (rc)
1950 return rc;
1951 *ret_buf = (void *)pSMB;
1952 pSMB->Reserved = 0;
1953 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
1954 pSMB->TotalDataCount = 0;
1955 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
1956 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1957 pSMB->ParameterCount = pSMB->TotalParameterCount;
1958 pSMB->DataCount = pSMB->TotalDataCount;
1959 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
1960 (setup_count * 2) - 4 /* for rfc1001 length itself */;
1961 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
1962 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
1963 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
1964 pSMB->SubCommand = cpu_to_le16(sub_command);
1965 return 0;
1966}
1967
1968static int
1969validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
1970 int * pdatalen, int * pparmlen)
1971{
1972 char * end_of_smb;
1973 __u32 data_count, data_offset, parm_count, parm_offset;
1974 struct smb_com_ntransact_rsp * pSMBr;
1975
1976 if(buf == NULL)
1977 return -EINVAL;
1978
1979 pSMBr = (struct smb_com_ntransact_rsp *)buf;
1980
1981 /* ByteCount was converted from little endian in SendReceive */
1982 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
1983 (char *)&pSMBr->ByteCount;
1984
1985
1986 data_offset = le32_to_cpu(pSMBr->DataOffset);
1987 data_count = le32_to_cpu(pSMBr->DataCount);
1988 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
1989 parm_count = le32_to_cpu(pSMBr->ParameterCount);
1990
1991 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
1992 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
1993
1994 /* should we also check that parm and data areas do not overlap? */
1995 if(*ppparm > end_of_smb) {
1996 cFYI(1,("parms start after end of smb"));
1997 return -EINVAL;
1998 } else if(parm_count + *ppparm > end_of_smb) {
1999 cFYI(1,("parm end after end of smb"));
2000 return -EINVAL;
2001 } else if(*ppdata > end_of_smb) {
2002 cFYI(1,("data starts after end of smb"));
2003 return -EINVAL;
2004 } else if(data_count + *ppdata > end_of_smb) {
2005 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2006 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2007 return -EINVAL;
2008 } else if(parm_count + data_count > pSMBr->ByteCount) {
2009 cFYI(1,("parm count and data count larger than SMB"));
2010 return -EINVAL;
2011 }
2012 return 0;
2013}
2014
1882int 2015int
1883CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, 2016CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1884 const unsigned char *searchName, 2017 const unsigned char *searchName,
@@ -1901,7 +2034,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1901 pSMB->TotalDataCount = 0; 2034 pSMB->TotalDataCount = 0;
1902 pSMB->MaxParameterCount = cpu_to_le32(2); 2035 pSMB->MaxParameterCount = cpu_to_le32(2);
1903 /* BB find exact data count max from sess structure BB */ 2036 /* BB find exact data count max from sess structure BB */
1904 pSMB->MaxDataCount = cpu_to_le32(4000); 2037 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2038 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1905 pSMB->MaxSetupCount = 4; 2039 pSMB->MaxSetupCount = 4;
1906 pSMB->Reserved = 0; 2040 pSMB->Reserved = 0;
1907 pSMB->ParameterOffset = 0; 2041 pSMB->ParameterOffset = 0;
@@ -1928,7 +2062,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1928 rc = -EIO; /* bad smb */ 2062 rc = -EIO; /* bad smb */
1929 else { 2063 else {
1930 if(data_count && (data_count < 2048)) { 2064 if(data_count && (data_count < 2048)) {
1931 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount; 2065 char * end_of_smb = 2 /* sizeof byte count */ +
2066 pSMBr->ByteCount +
2067 (char *)&pSMBr->ByteCount;
1932 2068
1933 struct reparse_data * reparse_buf = (struct reparse_data *) 2069 struct reparse_data * reparse_buf = (struct reparse_data *)
1934 ((char *)&pSMBr->hdr.Protocol + data_offset); 2070 ((char *)&pSMBr->hdr.Protocol + data_offset);
@@ -1951,7 +2087,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1951 reparse_buf->TargetNameOffset), 2087 reparse_buf->TargetNameOffset),
1952 min(buflen/2, reparse_buf->TargetNameLen / 2)); 2088 min(buflen/2, reparse_buf->TargetNameLen / 2));
1953 cifs_strfromUCS_le(symlinkinfo, 2089 cifs_strfromUCS_le(symlinkinfo,
1954 (wchar_t *) (reparse_buf->LinkNamesBuf + 2090 (__le16 *) (reparse_buf->LinkNamesBuf +
1955 reparse_buf->TargetNameOffset), 2091 reparse_buf->TargetNameOffset),
1956 name_len, nls_codepage); 2092 name_len, nls_codepage);
1957 } else { /* ASCII names */ 2093 } else { /* ASCII names */
@@ -1983,9 +2119,9 @@ qreparse_out:
1983static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) 2119static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1984{ 2120{
1985 /* u8 cifs fields do not need le conversion */ 2121 /* u8 cifs fields do not need le conversion */
1986 ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 2122 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
1987 ace->e_tag = (__u16)cifs_ace->cifs_e_tag; 2123 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
1988 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid); 2124 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
1989 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */ 2125 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1990 2126
1991 return; 2127 return;
@@ -2037,7 +2173,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2037 } else if(size > buflen) { 2173 } else if(size > buflen) {
2038 return -ERANGE; 2174 return -ERANGE;
2039 } else /* buffer big enough */ { 2175 } else /* buffer big enough */ {
2040 local_acl->a_version = POSIX_ACL_XATTR_VERSION; 2176 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2041 for(i = 0;i < count ;i++) { 2177 for(i = 0;i < count ;i++) {
2042 cifs_convert_ace(&local_acl->a_entries[i],pACE); 2178 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2043 pACE ++; 2179 pACE ++;
@@ -2051,14 +2187,14 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2051{ 2187{
2052 __u16 rc = 0; /* 0 = ACL converted ok */ 2188 __u16 rc = 0; /* 0 = ACL converted ok */
2053 2189
2054 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm); 2190 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2055 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag); 2191 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2056 /* BB is there a better way to handle the large uid? */ 2192 /* BB is there a better way to handle the large uid? */
2057 if(local_ace->e_id == -1) { 2193 if(local_ace->e_id == cpu_to_le32(-1)) {
2058 /* Probably no need to le convert -1 on any arch but can not hurt */ 2194 /* Probably no need to le convert -1 on any arch but can not hurt */
2059 cifs_ace->cifs_uid = cpu_to_le64(-1); 2195 cifs_ace->cifs_uid = cpu_to_le64(-1);
2060 } else 2196 } else
2061 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id); 2197 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2062 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/ 2198 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2063 return rc; 2199 return rc;
2064} 2200}
@@ -2078,16 +2214,17 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl
2078 2214
2079 count = posix_acl_xattr_count((size_t)buflen); 2215 count = posix_acl_xattr_count((size_t)buflen);
2080 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d", 2216 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2081 count,buflen,local_acl->a_version)); 2217 count, buflen, le32_to_cpu(local_acl->a_version)));
2082 if(local_acl->a_version != 2) { 2218 if(le32_to_cpu(local_acl->a_version) != 2) {
2083 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version)); 2219 cFYI(1,("unknown POSIX ACL version %d",
2220 le32_to_cpu(local_acl->a_version)));
2084 return 0; 2221 return 0;
2085 } 2222 }
2086 cifs_acl->version = cpu_to_le16(1); 2223 cifs_acl->version = cpu_to_le16(1);
2087 if(acl_type == ACL_TYPE_ACCESS) 2224 if(acl_type == ACL_TYPE_ACCESS)
2088 cifs_acl->access_entry_count = count; 2225 cifs_acl->access_entry_count = cpu_to_le16(count);
2089 else if(acl_type == ACL_TYPE_DEFAULT) 2226 else if(acl_type == ACL_TYPE_DEFAULT)
2090 cifs_acl->default_entry_count = count; 2227 cifs_acl->default_entry_count = cpu_to_le16(count);
2091 else { 2228 else {
2092 cFYI(1,("unknown ACL type %d",acl_type)); 2229 cFYI(1,("unknown ACL type %d",acl_type));
2093 return 0; 2230 return 0;
@@ -2171,6 +2308,7 @@ queryAclRetry:
2171 2308
2172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2309 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2310 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2311 cifs_stats_inc(&tcon->num_acl_get);
2174 if (rc) { 2312 if (rc) {
2175 cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); 2313 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2176 } else { 2314 } else {
@@ -2358,6 +2496,92 @@ GetExtAttrOut:
2358 2496
2359#endif /* CONFIG_POSIX */ 2497#endif /* CONFIG_POSIX */
2360 2498
2499
2500/* security id for everyone */
2501const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2502/* group users */
2503const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2504
2505/* Convert CIFS ACL to POSIX form */
2506static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2507{
2508 return 0;
2509}
2510
2511/* Get Security Descriptor (by handle) from remote server for a file or dir */
2512int
2513CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2514 /* BB fix up return info */ char *acl_inf, const int buflen,
2515 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2516{
2517 int rc = 0;
2518 int buf_type = 0;
2519 QUERY_SEC_DESC_REQ * pSMB;
2520 struct kvec iov[1];
2521
2522 cFYI(1, ("GetCifsACL"));
2523
2524 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2525 8 /* parm len */, tcon, (void **) &pSMB);
2526 if (rc)
2527 return rc;
2528
2529 pSMB->MaxParameterCount = cpu_to_le32(4);
2530 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2531 pSMB->MaxSetupCount = 0;
2532 pSMB->Fid = fid; /* file handle always le */
2533 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2534 CIFS_ACL_DACL);
2535 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2536 pSMB->hdr.smb_buf_length += 11;
2537 iov[0].iov_base = (char *)pSMB;
2538 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2539
2540 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2541 cifs_stats_inc(&tcon->num_acl_get);
2542 if (rc) {
2543 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2544 } else { /* decode response */
2545 struct cifs_sid * psec_desc;
2546 __le32 * parm;
2547 int parm_len;
2548 int data_len;
2549 int acl_len;
2550 struct smb_com_ntransact_rsp * pSMBr;
2551
2552/* validate_nttransact */
2553 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2554 (char **)&psec_desc,
2555 &parm_len, &data_len);
2556
2557 if(rc)
2558 goto qsec_out;
2559 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2560
2561 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2562
2563 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2564 rc = -EIO; /* bad smb */
2565 goto qsec_out;
2566 }
2567
2568/* BB check that data area is minimum length and as big as acl_len */
2569
2570 acl_len = le32_to_cpu(*(__le32 *)parm);
2571 /* BB check if(acl_len > bufsize) */
2572
2573 parse_sec_desc(psec_desc, acl_len);
2574 }
2575qsec_out:
2576 if(buf_type == CIFS_SMALL_BUFFER)
2577 cifs_small_buf_release(iov[0].iov_base);
2578 else if(buf_type == CIFS_LARGE_BUFFER)
2579 cifs_buf_release(iov[0].iov_base);
2580 cifs_small_buf_release(pSMB);
2581 return rc;
2582}
2583
2584
2361/* Legacy Query Path Information call for lookup to old servers such 2585/* Legacy Query Path Information call for lookup to old servers such
2362 as Win9x/WinME */ 2586 as Win9x/WinME */
2363int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, 2587int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -3203,7 +3427,7 @@ getDFSRetry:
3203 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset); 3427 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3204 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 3428 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3205 cifs_strfromUCS_le(*targetUNCs, 3429 cifs_strfromUCS_le(*targetUNCs,
3206 (wchar_t *) temp, name_len, nls_codepage); 3430 (__le16 *) temp, name_len, nls_codepage);
3207 } else { 3431 } else {
3208 strncpy(*targetUNCs,temp,name_len); 3432 strncpy(*targetUNCs,temp,name_len);
3209 } 3433 }
@@ -4256,7 +4480,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4256{ 4480{
4257 int rc = 0; 4481 int rc = 0;
4258 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4482 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4259 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4483 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4260 struct dir_notify_req *dnotify_req; 4484 struct dir_notify_req *dnotify_req;
4261 int bytes_returned; 4485 int bytes_returned;
4262 4486
@@ -4271,6 +4495,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4271 pSMB->MaxParameterCount = cpu_to_le32(2); 4495 pSMB->MaxParameterCount = cpu_to_le32(2);
4272 /* BB find exact data count max from sess structure BB */ 4496 /* BB find exact data count max from sess structure BB */
4273 pSMB->MaxDataCount = 0; /* same in little endian or be */ 4497 pSMB->MaxDataCount = 0; /* same in little endian or be */
4498/* BB VERIFY verify which is correct for above BB */
4499 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4500 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4501
4274 pSMB->MaxSetupCount = 4; 4502 pSMB->MaxSetupCount = 4;
4275 pSMB->Reserved = 0; 4503 pSMB->Reserved = 0;
4276 pSMB->ParameterOffset = 0; 4504 pSMB->ParameterOffset = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2cb620716bc1..88f60aa52058 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -76,12 +76,19 @@ struct smb_vol {
76 unsigned setuids:1; 76 unsigned setuids:1;
77 unsigned noperm:1; 77 unsigned noperm:1;
78 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ 78 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
79 unsigned cifs_acl:1;
79 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ 80 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
80 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 81 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
81 unsigned direct_io:1; 82 unsigned direct_io:1;
82 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 83 unsigned remap:1; /* set to remap seven reserved chars in filenames */
83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 84 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
84 unsigned sfu_emul:1; 85 unsigned sfu_emul:1;
86 unsigned krb5:1;
87 unsigned ntlm:1;
88 unsigned ntlmv2:1;
89 unsigned nullauth:1; /* attempt to authenticate with null user */
90 unsigned sign:1;
91 unsigned seal:1; /* encrypt */
85 unsigned nocase; /* request case insensitive filenames */ 92 unsigned nocase; /* request case insensitive filenames */
86 unsigned nobrl; /* disable sending byte range locks to srv */ 93 unsigned nobrl; /* disable sending byte range locks to srv */
87 unsigned int rsize; 94 unsigned int rsize;
@@ -508,7 +515,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
508 /* else length ok */ 515 /* else length ok */
509 reconnect = 0; 516 reconnect = 0;
510 517
511 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { 518 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
512 isLargeBuf = TRUE; 519 isLargeBuf = TRUE;
513 memcpy(bigbuf, smallbuf, 4); 520 memcpy(bigbuf, smallbuf, 4);
514 smb_buffer = bigbuf; 521 smb_buffer = bigbuf;
@@ -777,7 +784,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
777 784
778 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 785 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
779 vol->rw = TRUE; 786 vol->rw = TRUE;
780 787 vol->ntlm = TRUE;
781 /* default is always to request posix paths. */ 788 /* default is always to request posix paths. */
782 vol->posix_paths = 1; 789 vol->posix_paths = 1;
783 790
@@ -903,6 +910,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
903 printk(KERN_WARNING "CIFS: ip address too long\n"); 910 printk(KERN_WARNING "CIFS: ip address too long\n");
904 return 1; 911 return 1;
905 } 912 }
913 } else if (strnicmp(data, "sec", 3) == 0) {
914 if (!value || !*value) {
915 cERROR(1,("no security value specified"));
916 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->sign = 1;
919 vol->krb5 = 1;
920 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->seal = 1;
922 vol->krb5 = 1; */
923 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->krb5 = 1;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->ntlmv2 = 1;
929 vol->sign = 1;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->ntlmv2 = 1;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->ntlm = 1;
934 vol->sign = 1;
935 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */
937 vol->ntlm = 1;
938 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 vol->ntlm = 0;
940 } else if (strnicmp(value, "none", 4) == 0) {
941 vol->nullauth = 1;
942 } else {
943 cERROR(1,("bad security option: %s", value));
944 return 1;
945 }
906 } else if ((strnicmp(data, "unc", 3) == 0) 946 } else if ((strnicmp(data, "unc", 3) == 0)
907 || (strnicmp(data, "target", 6) == 0) 947 || (strnicmp(data, "target", 6) == 0)
908 || (strnicmp(data, "path", 4) == 0)) { 948 || (strnicmp(data, "path", 4) == 0)) {
@@ -1120,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1120 vol->server_ino = 1; 1160 vol->server_ino = 1;
1121 } else if (strnicmp(data, "noserverino",9) == 0) { 1161 } else if (strnicmp(data, "noserverino",9) == 0) {
1122 vol->server_ino = 0; 1162 vol->server_ino = 0;
1163 } else if (strnicmp(data, "cifsacl",7) == 0) {
1164 vol->cifs_acl = 1;
1165 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1166 vol->cifs_acl = 0;
1123 } else if (strnicmp(data, "acl",3) == 0) { 1167 } else if (strnicmp(data, "acl",3) == 0) {
1124 vol->no_psx_acl = 0; 1168 vol->no_psx_acl = 0;
1125 } else if (strnicmp(data, "noacl",5) == 0) { 1169 } else if (strnicmp(data, "noacl",5) == 0) {
@@ -1546,7 +1590,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1546 cFYI(1, ("Username: %s ", volume_info.username)); 1590 cFYI(1, ("Username: %s ", volume_info.username));
1547 1591
1548 } else { 1592 } else {
1549 cifserror("No username specified "); 1593 cifserror("No username specified");
1550 /* In userspace mount helper we can get user name from alternate 1594 /* In userspace mount helper we can get user name from alternate
1551 locations such as env variables and files on disk */ 1595 locations such as env variables and files on disk */
1552 kfree(volume_info.UNC); 1596 kfree(volume_info.UNC);
@@ -1587,7 +1631,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1587 return -EINVAL; 1631 return -EINVAL;
1588 } else /* which servers DFS root would we conect to */ { 1632 } else /* which servers DFS root would we conect to */ {
1589 cERROR(1, 1633 cERROR(1,
1590 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); 1634 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1591 kfree(volume_info.UNC); 1635 kfree(volume_info.UNC);
1592 kfree(volume_info.password); 1636 kfree(volume_info.password);
1593 FreeXid(xid); 1637 FreeXid(xid);
@@ -1626,7 +1670,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1626 1670
1627 1671
1628 if (srvTcp) { 1672 if (srvTcp) {
1629 cFYI(1, ("Existing tcp session with server found ")); 1673 cFYI(1, ("Existing tcp session with server found"));
1630 } else { /* create socket */ 1674 } else { /* create socket */
1631 if(volume_info.port) 1675 if(volume_info.port)
1632 sin_server.sin_port = htons(volume_info.port); 1676 sin_server.sin_port = htons(volume_info.port);
@@ -1689,11 +1733,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1689 1733
1690 if (existingCifsSes) { 1734 if (existingCifsSes) {
1691 pSesInfo = existingCifsSes; 1735 pSesInfo = existingCifsSes;
1692 cFYI(1, ("Existing smb sess found ")); 1736 cFYI(1, ("Existing smb sess found"));
1693 kfree(volume_info.password); 1737 kfree(volume_info.password);
1694 /* volume_info.UNC freed at end of function */ 1738 /* volume_info.UNC freed at end of function */
1695 } else if (!rc) { 1739 } else if (!rc) {
1696 cFYI(1, ("Existing smb sess not found ")); 1740 cFYI(1, ("Existing smb sess not found"));
1697 pSesInfo = sesInfoAlloc(); 1741 pSesInfo = sesInfoAlloc();
1698 if (pSesInfo == NULL) 1742 if (pSesInfo == NULL)
1699 rc = -ENOMEM; 1743 rc = -ENOMEM;
@@ -1751,7 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1751 cifs_sb->mnt_gid = volume_info.linux_gid; 1795 cifs_sb->mnt_gid = volume_info.linux_gid;
1752 cifs_sb->mnt_file_mode = volume_info.file_mode; 1796 cifs_sb->mnt_file_mode = volume_info.file_mode;
1753 cifs_sb->mnt_dir_mode = volume_info.dir_mode; 1797 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1754 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); 1798 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1799 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1755 1800
1756 if(volume_info.noperm) 1801 if(volume_info.noperm)
1757 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; 1802 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
@@ -1767,6 +1812,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1767 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; 1812 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1768 if(volume_info.nobrl) 1813 if(volume_info.nobrl)
1769 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; 1814 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1815 if(volume_info.cifs_acl)
1816 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1770 1817
1771 if(volume_info.direct_io) { 1818 if(volume_info.direct_io) {
1772 cFYI(1,("mounting share using direct i/o")); 1819 cFYI(1,("mounting share using direct i/o"));
@@ -1777,7 +1824,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, 1824 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1778 volume_info.username); 1825 volume_info.username);
1779 if (tcon) { 1826 if (tcon) {
1780 cFYI(1, ("Found match on UNC path ")); 1827 cFYI(1, ("Found match on UNC path"));
1781 /* we can have only one retry value for a connection 1828 /* we can have only one retry value for a connection
1782 to a share so for resources mounted more than once 1829 to a share so for resources mounted more than once
1783 to the same server share the last value passed in 1830 to the same server share the last value passed in
@@ -1926,7 +1973,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1926 __u32 capabilities; 1973 __u32 capabilities;
1927 __u16 count; 1974 __u16 count;
1928 1975
1929 cFYI(1, ("In sesssetup ")); 1976 cFYI(1, ("In sesssetup"));
1930 if(ses == NULL) 1977 if(ses == NULL)
1931 return -EINVAL; 1978 return -EINVAL;
1932 user = ses->userName; 1979 user = ses->userName;
@@ -1986,32 +2033,32 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1986 bytes_returned = 0; /* skill null user */ 2033 bytes_returned = 0; /* skill null user */
1987 else 2034 else
1988 bytes_returned = 2035 bytes_returned =
1989 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, 2036 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
1990 nls_codepage); 2037 nls_codepage);
1991 /* convert number of 16 bit words to bytes */ 2038 /* convert number of 16 bit words to bytes */
1992 bcc_ptr += 2 * bytes_returned; 2039 bcc_ptr += 2 * bytes_returned;
1993 bcc_ptr += 2; /* trailing null */ 2040 bcc_ptr += 2; /* trailing null */
1994 if (domain == NULL) 2041 if (domain == NULL)
1995 bytes_returned = 2042 bytes_returned =
1996 cifs_strtoUCS((wchar_t *) bcc_ptr, 2043 cifs_strtoUCS((__le16 *) bcc_ptr,
1997 "CIFS_LINUX_DOM", 32, nls_codepage); 2044 "CIFS_LINUX_DOM", 32, nls_codepage);
1998 else 2045 else
1999 bytes_returned = 2046 bytes_returned =
2000 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2047 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2001 nls_codepage); 2048 nls_codepage);
2002 bcc_ptr += 2 * bytes_returned; 2049 bcc_ptr += 2 * bytes_returned;
2003 bcc_ptr += 2; 2050 bcc_ptr += 2;
2004 bytes_returned = 2051 bytes_returned =
2005 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2052 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2006 32, nls_codepage); 2053 32, nls_codepage);
2007 bcc_ptr += 2 * bytes_returned; 2054 bcc_ptr += 2 * bytes_returned;
2008 bytes_returned = 2055 bytes_returned =
2009 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 2056 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2010 32, nls_codepage); 2057 32, nls_codepage);
2011 bcc_ptr += 2 * bytes_returned; 2058 bcc_ptr += 2 * bytes_returned;
2012 bcc_ptr += 2; 2059 bcc_ptr += 2;
2013 bytes_returned = 2060 bytes_returned =
2014 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2061 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2015 64, nls_codepage); 2062 64, nls_codepage);
2016 bcc_ptr += 2 * bytes_returned; 2063 bcc_ptr += 2 * bytes_returned;
2017 bcc_ptr += 2; 2064 bcc_ptr += 2;
@@ -2081,7 +2128,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2081 if(ses->serverOS == NULL) 2128 if(ses->serverOS == NULL)
2082 goto sesssetup_nomem; 2129 goto sesssetup_nomem;
2083 cifs_strfromUCS_le(ses->serverOS, 2130 cifs_strfromUCS_le(ses->serverOS,
2084 (wchar_t *)bcc_ptr, len,nls_codepage); 2131 (__le16 *)bcc_ptr, len,nls_codepage);
2085 bcc_ptr += 2 * (len + 1); 2132 bcc_ptr += 2 * (len + 1);
2086 remaining_words -= len + 1; 2133 remaining_words -= len + 1;
2087 ses->serverOS[2 * len] = 0; 2134 ses->serverOS[2 * len] = 0;
@@ -2093,7 +2140,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2093 if(ses->serverNOS == NULL) 2140 if(ses->serverNOS == NULL)
2094 goto sesssetup_nomem; 2141 goto sesssetup_nomem;
2095 cifs_strfromUCS_le(ses->serverNOS, 2142 cifs_strfromUCS_le(ses->serverNOS,
2096 (wchar_t *)bcc_ptr,len,nls_codepage); 2143 (__le16 *)bcc_ptr,len,nls_codepage);
2097 bcc_ptr += 2 * (len + 1); 2144 bcc_ptr += 2 * (len + 1);
2098 ses->serverNOS[2 * len] = 0; 2145 ses->serverNOS[2 * len] = 0;
2099 ses->serverNOS[1 + (2 * len)] = 0; 2146 ses->serverNOS[1 + (2 * len)] = 0;
@@ -2111,7 +2158,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2111 if(ses->serverDomain == NULL) 2158 if(ses->serverDomain == NULL)
2112 goto sesssetup_nomem; 2159 goto sesssetup_nomem;
2113 cifs_strfromUCS_le(ses->serverDomain, 2160 cifs_strfromUCS_le(ses->serverDomain,
2114 (wchar_t *)bcc_ptr,len,nls_codepage); 2161 (__le16 *)bcc_ptr,len,nls_codepage);
2115 bcc_ptr += 2 * (len + 1); 2162 bcc_ptr += 2 * (len + 1);
2116 ses->serverDomain[2*len] = 0; 2163 ses->serverDomain[2*len] = 0;
2117 ses->serverDomain[1+(2*len)] = 0; 2164 ses->serverDomain[1+(2*len)] = 0;
@@ -2255,30 +2302,30 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2255 bcc_ptr++; 2302 bcc_ptr++;
2256 } 2303 }
2257 bytes_returned = 2304 bytes_returned =
2258 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage); 2305 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2259 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */ 2306 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2260 bcc_ptr += 2; /* trailing null */ 2307 bcc_ptr += 2; /* trailing null */
2261 if (domain == NULL) 2308 if (domain == NULL)
2262 bytes_returned = 2309 bytes_returned =
2263 cifs_strtoUCS((wchar_t *) bcc_ptr, 2310 cifs_strtoUCS((__le16 *) bcc_ptr,
2264 "CIFS_LINUX_DOM", 32, nls_codepage); 2311 "CIFS_LINUX_DOM", 32, nls_codepage);
2265 else 2312 else
2266 bytes_returned = 2313 bytes_returned =
2267 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2314 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2268 nls_codepage); 2315 nls_codepage);
2269 bcc_ptr += 2 * bytes_returned; 2316 bcc_ptr += 2 * bytes_returned;
2270 bcc_ptr += 2; 2317 bcc_ptr += 2;
2271 bytes_returned = 2318 bytes_returned =
2272 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2319 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2273 32, nls_codepage); 2320 32, nls_codepage);
2274 bcc_ptr += 2 * bytes_returned; 2321 bcc_ptr += 2 * bytes_returned;
2275 bytes_returned = 2322 bytes_returned =
2276 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2323 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2277 nls_codepage); 2324 nls_codepage);
2278 bcc_ptr += 2 * bytes_returned; 2325 bcc_ptr += 2 * bytes_returned;
2279 bcc_ptr += 2; 2326 bcc_ptr += 2;
2280 bytes_returned = 2327 bytes_returned =
2281 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2328 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2282 64, nls_codepage); 2329 64, nls_codepage);
2283 bcc_ptr += 2 * bytes_returned; 2330 bcc_ptr += 2 * bytes_returned;
2284 bcc_ptr += 2; 2331 bcc_ptr += 2;
@@ -2357,7 +2404,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2357 ses->serverOS = 2404 ses->serverOS =
2358 kzalloc(2 * (len + 1), GFP_KERNEL); 2405 kzalloc(2 * (len + 1), GFP_KERNEL);
2359 cifs_strfromUCS_le(ses->serverOS, 2406 cifs_strfromUCS_le(ses->serverOS,
2360 (wchar_t *) 2407 (__le16 *)
2361 bcc_ptr, len, 2408 bcc_ptr, len,
2362 nls_codepage); 2409 nls_codepage);
2363 bcc_ptr += 2 * (len + 1); 2410 bcc_ptr += 2 * (len + 1);
@@ -2372,7 +2419,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2372 kzalloc(2 * (len + 1), 2419 kzalloc(2 * (len + 1),
2373 GFP_KERNEL); 2420 GFP_KERNEL);
2374 cifs_strfromUCS_le(ses->serverNOS, 2421 cifs_strfromUCS_le(ses->serverNOS,
2375 (wchar_t *)bcc_ptr, 2422 (__le16 *)bcc_ptr,
2376 len, 2423 len,
2377 nls_codepage); 2424 nls_codepage);
2378 bcc_ptr += 2 * (len + 1); 2425 bcc_ptr += 2 * (len + 1);
@@ -2384,9 +2431,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2384 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2431 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2385 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); 2432 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2386 cifs_strfromUCS_le(ses->serverDomain, 2433 cifs_strfromUCS_le(ses->serverDomain,
2387 (wchar_t *)bcc_ptr, 2434 (__le16 *)bcc_ptr,
2388 len, 2435 len, nls_codepage);
2389 nls_codepage);
2390 bcc_ptr += 2*(len+1); 2436 bcc_ptr += 2*(len+1);
2391 ses->serverDomain[2*len] = 0; 2437 ses->serverDomain[2*len] = 0;
2392 ses->serverDomain[1+(2*len)] = 0; 2438 ses->serverDomain[1+(2*len)] = 0;
@@ -2560,16 +2606,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2560 } 2606 }
2561 2607
2562 bytes_returned = 2608 bytes_returned =
2563 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2609 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2564 32, nls_codepage); 2610 32, nls_codepage);
2565 bcc_ptr += 2 * bytes_returned; 2611 bcc_ptr += 2 * bytes_returned;
2566 bytes_returned = 2612 bytes_returned =
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2613 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2568 nls_codepage); 2614 nls_codepage);
2569 bcc_ptr += 2 * bytes_returned; 2615 bcc_ptr += 2 * bytes_returned;
2570 bcc_ptr += 2; /* null terminate Linux version */ 2616 bcc_ptr += 2; /* null terminate Linux version */
2571 bytes_returned = 2617 bytes_returned =
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2618 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2573 64, nls_codepage); 2619 64, nls_codepage);
2574 bcc_ptr += 2 * bytes_returned; 2620 bcc_ptr += 2 * bytes_returned;
2575 *(bcc_ptr + 1) = 0; 2621 *(bcc_ptr + 1) = 0;
@@ -2673,7 +2719,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2673 ses->serverOS = 2719 ses->serverOS =
2674 kzalloc(2 * (len + 1), GFP_KERNEL); 2720 kzalloc(2 * (len + 1), GFP_KERNEL);
2675 cifs_strfromUCS_le(ses->serverOS, 2721 cifs_strfromUCS_le(ses->serverOS,
2676 (wchar_t *) 2722 (__le16 *)
2677 bcc_ptr, len, 2723 bcc_ptr, len,
2678 nls_codepage); 2724 nls_codepage);
2679 bcc_ptr += 2 * (len + 1); 2725 bcc_ptr += 2 * (len + 1);
@@ -2690,7 +2736,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2690 GFP_KERNEL); 2736 GFP_KERNEL);
2691 cifs_strfromUCS_le(ses-> 2737 cifs_strfromUCS_le(ses->
2692 serverNOS, 2738 serverNOS,
2693 (wchar_t *) 2739 (__le16 *)
2694 bcc_ptr, 2740 bcc_ptr,
2695 len, 2741 len,
2696 nls_codepage); 2742 nls_codepage);
@@ -2708,23 +2754,15 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2708 1), 2754 1),
2709 GFP_KERNEL); 2755 GFP_KERNEL);
2710 cifs_strfromUCS_le 2756 cifs_strfromUCS_le
2711 (ses-> 2757 (ses->serverDomain,
2712 serverDomain, 2758 (__le16 *)bcc_ptr,
2713 (wchar_t *) 2759 len, nls_codepage);
2714 bcc_ptr, len,
2715 nls_codepage);
2716 bcc_ptr += 2760 bcc_ptr +=
2717 2 * (len + 1); 2761 2 * (len + 1);
2718 ses-> 2762 ses->serverDomain[2*len]
2719 serverDomain[2
2720 * len]
2721 = 0; 2763 = 0;
2722 ses-> 2764 ses->serverDomain
2723 serverDomain[1 2765 [1 + (2 * len)]
2724 +
2725 (2
2726 *
2727 len)]
2728 = 0; 2766 = 0;
2729 } /* else no more room so create dummy domain string */ 2767 } /* else no more room so create dummy domain string */
2730 else 2768 else
@@ -2903,7 +2941,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2903 SecurityBlob->DomainName.MaximumLength = 0; 2941 SecurityBlob->DomainName.MaximumLength = 0;
2904 } else { 2942 } else {
2905 __u16 len = 2943 __u16 len =
2906 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2944 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2907 nls_codepage); 2945 nls_codepage);
2908 len *= 2; 2946 len *= 2;
2909 SecurityBlob->DomainName.MaximumLength = 2947 SecurityBlob->DomainName.MaximumLength =
@@ -2921,7 +2959,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2921 SecurityBlob->UserName.MaximumLength = 0; 2959 SecurityBlob->UserName.MaximumLength = 0;
2922 } else { 2960 } else {
2923 __u16 len = 2961 __u16 len =
2924 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64, 2962 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
2925 nls_codepage); 2963 nls_codepage);
2926 len *= 2; 2964 len *= 2;
2927 SecurityBlob->UserName.MaximumLength = 2965 SecurityBlob->UserName.MaximumLength =
@@ -2934,7 +2972,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2934 cpu_to_le16(len); 2972 cpu_to_le16(len);
2935 } 2973 }
2936 2974
2937 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage); 2975 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
2938 SecurityBlob->WorkstationName.Length *= 2; 2976 SecurityBlob->WorkstationName.Length *= 2;
2939 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length); 2977 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2940 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength); 2978 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
@@ -2947,16 +2985,16 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2947 bcc_ptr++; 2985 bcc_ptr++;
2948 } 2986 }
2949 bytes_returned = 2987 bytes_returned =
2950 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2988 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2951 32, nls_codepage); 2989 32, nls_codepage);
2952 bcc_ptr += 2 * bytes_returned; 2990 bcc_ptr += 2 * bytes_returned;
2953 bytes_returned = 2991 bytes_returned =
2954 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2992 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2955 nls_codepage); 2993 nls_codepage);
2956 bcc_ptr += 2 * bytes_returned; 2994 bcc_ptr += 2 * bytes_returned;
2957 bcc_ptr += 2; /* null term version string */ 2995 bcc_ptr += 2; /* null term version string */
2958 bytes_returned = 2996 bytes_returned =
2959 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2997 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2960 64, nls_codepage); 2998 64, nls_codepage);
2961 bcc_ptr += 2 * bytes_returned; 2999 bcc_ptr += 2 * bytes_returned;
2962 *(bcc_ptr + 1) = 0; 3000 *(bcc_ptr + 1) = 0;
@@ -3069,7 +3107,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3069 ses->serverOS = 3107 ses->serverOS =
3070 kzalloc(2 * (len + 1), GFP_KERNEL); 3108 kzalloc(2 * (len + 1), GFP_KERNEL);
3071 cifs_strfromUCS_le(ses->serverOS, 3109 cifs_strfromUCS_le(ses->serverOS,
3072 (wchar_t *) 3110 (__le16 *)
3073 bcc_ptr, len, 3111 bcc_ptr, len,
3074 nls_codepage); 3112 nls_codepage);
3075 bcc_ptr += 2 * (len + 1); 3113 bcc_ptr += 2 * (len + 1);
@@ -3086,7 +3124,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3086 GFP_KERNEL); 3124 GFP_KERNEL);
3087 cifs_strfromUCS_le(ses-> 3125 cifs_strfromUCS_le(ses->
3088 serverNOS, 3126 serverNOS,
3089 (wchar_t *) 3127 (__le16 *)
3090 bcc_ptr, 3128 bcc_ptr,
3091 len, 3129 len,
3092 nls_codepage); 3130 nls_codepage);
@@ -3105,7 +3143,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3105 cifs_strfromUCS_le 3143 cifs_strfromUCS_le
3106 (ses-> 3144 (ses->
3107 serverDomain, 3145 serverDomain,
3108 (wchar_t *) 3146 (__le16 *)
3109 bcc_ptr, len, 3147 bcc_ptr, len,
3110 nls_codepage); 3148 nls_codepage);
3111 bcc_ptr += 3149 bcc_ptr +=
@@ -3211,9 +3249,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3211 3249
3212 pSMB->AndXCommand = 0xFF; 3250 pSMB->AndXCommand = 0xFF;
3213 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); 3251 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3214 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3215 bcc_ptr = &pSMB->Password[0]; 3252 bcc_ptr = &pSMB->Password[0];
3216 bcc_ptr++; /* skip password */ 3253 if((ses->server->secMode) & SECMODE_USER) {
3254 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3255 bcc_ptr++; /* skip password */
3256 } else {
3257 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
3258 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3259 specified as required (when that support is added to
3260 the vfs in the future) as only NTLM or the much
3261 weaker LANMAN (which we do not send) is accepted
3262 by Samba (not sure whether other servers allow
3263 NTLMv2 password here) */
3264 SMBNTencrypt(ses->password,
3265 ses->server->cryptKey,
3266 bcc_ptr);
3267
3268 bcc_ptr += CIFS_SESSION_KEY_SIZE;
3269 *bcc_ptr = 0;
3270 bcc_ptr++; /* align */
3271 }
3217 3272
3218 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 3273 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3219 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 3274 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -3227,11 +3282,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3227 if (ses->capabilities & CAP_UNICODE) { 3282 if (ses->capabilities & CAP_UNICODE) {
3228 smb_buffer->Flags2 |= SMBFLG2_UNICODE; 3283 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3229 length = 3284 length =
3230 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage); 3285 cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
3231 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ 3286 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3232 bcc_ptr += 2; /* skip trailing null */ 3287 bcc_ptr += 2; /* skip trailing null */
3233 } else { /* ASCII */ 3288 } else { /* ASCII */
3234
3235 strcpy(bcc_ptr, tree); 3289 strcpy(bcc_ptr, tree);
3236 bcc_ptr += strlen(tree) + 1; 3290 bcc_ptr += strlen(tree) + 1;
3237 } 3291 }
@@ -3263,7 +3317,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3263 tcon->nativeFileSystem = 3317 tcon->nativeFileSystem =
3264 kzalloc(length + 2, GFP_KERNEL); 3318 kzalloc(length + 2, GFP_KERNEL);
3265 cifs_strfromUCS_le(tcon->nativeFileSystem, 3319 cifs_strfromUCS_le(tcon->nativeFileSystem,
3266 (wchar_t *) bcc_ptr, 3320 (__le16 *) bcc_ptr,
3267 length, nls_codepage); 3321 length, nls_codepage);
3268 bcc_ptr += 2 * length; 3322 bcc_ptr += 2 * length;
3269 bcc_ptr[0] = 0; /* null terminate the string */ 3323 bcc_ptr[0] = 0; /* null terminate the string */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 8dfe717a332a..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 &
@@ -228,8 +228,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
228 else { 228 else {
229 rc = cifs_get_inode_info(&newinode, full_path, 229 rc = cifs_get_inode_info(&newinode, full_path,
230 buf, inode->i_sb,xid); 230 buf, inode->i_sb,xid);
231 if(newinode) 231 if(newinode) {
232 newinode->i_mode = mode; 232 newinode->i_mode = mode;
233 if((oplock & CIFS_CREATE_ACTION) &&
234 (cifs_sb->mnt_cifs_flags &
235 CIFS_MOUNT_SET_UID)) {
236 newinode->i_uid = current->fsuid;
237 newinode->i_gid = current->fsgid;
238 }
239 }
233 } 240 }
234 241
235 if (rc != 0) { 242 if (rc != 0) {
@@ -292,7 +299,8 @@ cifs_create_out:
292 return rc; 299 return rc;
293} 300}
294 301
295int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) 302int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
303 dev_t device_number)
296{ 304{
297 int rc = -EPERM; 305 int rc = -EPERM;
298 int xid; 306 int xid;
@@ -317,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
317 else if (pTcon->ses->capabilities & CAP_UNIX) { 325 else if (pTcon->ses->capabilities & CAP_UNIX) {
318 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 326 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
319 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 327 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
320 mode,(__u64)current->euid,(__u64)current->egid, 328 mode,(__u64)current->fsuid,(__u64)current->fsgid,
321 device_number, cifs_sb->local_nls, 329 device_number, cifs_sb->local_nls,
322 cifs_sb->mnt_cifs_flags & 330 cifs_sb->mnt_cifs_flags &
323 CIFS_MOUNT_MAP_SPECIAL_CHR); 331 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -368,7 +376,34 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
368 376
369 if(!rc) { 377 if(!rc) {
370 /* BB Do not bother to decode buf since no 378 /* BB Do not bother to decode buf since no
371 local inode yet to put timestamps in */ 379 local inode yet to put timestamps in,
380 but we can reuse it safely */
381 int bytes_written;
382 struct win_dev *pdev;
383 pdev = (struct win_dev *)buf;
384 if(S_ISCHR(mode)) {
385 memcpy(pdev->type, "IntxCHR", 8);
386 pdev->major =
387 cpu_to_le64(MAJOR(device_number));
388 pdev->minor =
389 cpu_to_le64(MINOR(device_number));
390 rc = CIFSSMBWrite(xid, pTcon,
391 fileHandle,
392 sizeof(struct win_dev),
393 0, &bytes_written, (char *)pdev,
394 NULL, 0);
395 } else if(S_ISBLK(mode)) {
396 memcpy(pdev->type, "IntxBLK", 8);
397 pdev->major =
398 cpu_to_le64(MAJOR(device_number));
399 pdev->minor =
400 cpu_to_le64(MINOR(device_number));
401 rc = CIFSSMBWrite(xid, pTcon,
402 fileHandle,
403 sizeof(struct win_dev),
404 0, &bytes_written, (char *)pdev,
405 NULL, 0);
406 } /* else if(S_ISFIFO */
372 CIFSSMBClose(xid, pTcon, fileHandle); 407 CIFSSMBClose(xid, pTcon, fileHandle);
373 d_drop(direntry); 408 d_drop(direntry);
374 } 409 }
@@ -437,12 +472,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
437 direntry->d_op = &cifs_dentry_ops; 472 direntry->d_op = &cifs_dentry_ops;
438 d_add(direntry, newInode); 473 d_add(direntry, newInode);
439 474
440 /* since paths are not looked up by component - the parent directories are presumed to be good here */ 475 /* since paths are not looked up by component - the parent
476 directories are presumed to be good here */
441 renew_parental_timestamps(direntry); 477 renew_parental_timestamps(direntry);
442 478
443 } else if (rc == -ENOENT) { 479 } else if (rc == -ENOENT) {
444 rc = 0; 480 rc = 0;
481 direntry->d_time = jiffies;
482 if (pTcon->nocase)
483 direntry->d_op = &cifs_ci_dentry_ops;
484 else
485 direntry->d_op = &cifs_dentry_ops;
445 d_add(direntry, NULL); 486 d_add(direntry, NULL);
487 /* if it was once a directory (but how can we tell?) we could do
488 shrink_dcache_parent(direntry); */
446 } else { 489 } else {
447 cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", 490 cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
448 rc,full_path)); 491 rc,full_path));
@@ -461,21 +504,20 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
461{ 504{
462 int isValid = 1; 505 int isValid = 1;
463 506
464/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
465
466 if (direntry->d_inode) { 507 if (direntry->d_inode) {
467 if (cifs_revalidate(direntry)) { 508 if (cifs_revalidate(direntry)) {
468 /* unlock_kernel(); */
469 return 0; 509 return 0;
470 } 510 }
471 } else { 511 } else {
472 cFYI(1, 512 cFYI(1, ("neg dentry 0x%p name = %s",
473 ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p", 513 direntry, direntry->d_name.name));
474 direntry->d_name.name, direntry)); 514 if(time_after(jiffies, direntry->d_time + HZ) ||
515 !lookupCacheEnabled) {
516 d_drop(direntry);
517 isValid = 0;
518 }
475 } 519 }
476 520
477/* unlock_kernel(); */
478
479 return isValid; 521 return isValid;
480} 522}
481 523
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index da4f5e10b3cc..77c990f0cb98 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -127,8 +127,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
127 if (file->f_dentry->d_inode->i_mapping) { 127 if (file->f_dentry->d_inode->i_mapping) {
128 /* BB no need to lock inode until after invalidate 128 /* BB no need to lock inode until after invalidate
129 since namei code should already have it locked? */ 129 since namei code should already have it locked? */
130 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping); 130 filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
131 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
132 } 131 }
133 cFYI(1, ("invalidating remote inode since open detected it " 132 cFYI(1, ("invalidating remote inode since open detected it "
134 "changed")); 133 "changed"));
@@ -419,8 +418,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
419 pCifsInode = CIFS_I(inode); 418 pCifsInode = CIFS_I(inode);
420 if (pCifsInode) { 419 if (pCifsInode) {
421 if (can_flush) { 420 if (can_flush) {
422 filemap_fdatawrite(inode->i_mapping); 421 filemap_write_and_wait(inode->i_mapping);
423 filemap_fdatawait(inode->i_mapping);
424 /* temporarily disable caching while we 422 /* temporarily disable caching while we
425 go to server to get inode info */ 423 go to server to get inode info */
426 pCifsInode->clientCanCacheAll = FALSE; 424 pCifsInode->clientCanCacheAll = FALSE;
@@ -489,8 +487,10 @@ int cifs_close(struct inode *inode, struct file *file)
489 the struct would be in each open file, 487 the struct would be in each open file,
490 but this should give enough time to 488 but this should give enough time to
491 clear the socket */ 489 clear the socket */
490 write_unlock(&file->f_owner.lock);
492 cERROR(1,("close with pending writes")); 491 cERROR(1,("close with pending writes"));
493 msleep(timeout); 492 msleep(timeout);
493 write_lock(&file->f_owner.lock);
494 timeout *= 4; 494 timeout *= 4;
495 } 495 }
496 write_unlock(&file->f_owner.lock); 496 write_unlock(&file->f_owner.lock);
@@ -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;
@@ -1746,7 +1754,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1746 1754
1747/* need to free smb_read_data buf before exit */ 1755/* need to free smb_read_data buf before exit */
1748 if (smb_read_data) { 1756 if (smb_read_data) {
1749 cifs_buf_release(smb_read_data); 1757 if(buf_type == CIFS_SMALL_BUFFER)
1758 cifs_small_buf_release(smb_read_data);
1759 else if(buf_type == CIFS_LARGE_BUFFER)
1760 cifs_buf_release(smb_read_data);
1750 smb_read_data = NULL; 1761 smb_read_data = NULL;
1751 } 1762 }
1752 1763
@@ -1825,10 +1836,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1825 open_file = find_writable_file(cifsInode); 1836 open_file = find_writable_file(cifsInode);
1826 1837
1827 if(open_file) { 1838 if(open_file) {
1839 struct cifs_sb_info *cifs_sb;
1840
1828 /* there is not actually a write pending so let 1841 /* there is not actually a write pending so let
1829 this handle go free and allow it to 1842 this handle go free and allow it to
1830 be closable if needed */ 1843 be closable if needed */
1831 atomic_dec(&open_file->wrtPending); 1844 atomic_dec(&open_file->wrtPending);
1845
1846 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1847 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1848 /* since no page cache to corrupt on directio
1849 we can change size safely */
1850 return 1;
1851 }
1852
1832 return 0; 1853 return 0;
1833 } else 1854 } else
1834 return 1; 1855 return 1;
@@ -1873,9 +1894,7 @@ struct address_space_operations cifs_addr_ops = {
1873 .readpage = cifs_readpage, 1894 .readpage = cifs_readpage,
1874 .readpages = cifs_readpages, 1895 .readpages = cifs_readpages,
1875 .writepage = cifs_writepage, 1896 .writepage = cifs_writepage,
1876#ifdef CONFIG_CIFS_EXPERIMENTAL
1877 .writepages = cifs_writepages, 1897 .writepages = cifs_writepages,
1878#endif
1879 .prepare_write = cifs_prepare_write, 1898 .prepare_write = cifs_prepare_write,
1880 .commit_write = cifs_commit_write, 1899 .commit_write = cifs_commit_write,
1881 .set_page_dirty = __set_page_dirty_nobuffers, 1900 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 923d071163b2..59359911f481 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
41 char *tmp_path; 41 char *tmp_path;
42 42
43 pTcon = cifs_sb->tcon; 43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path)); 44 cFYI(1, ("Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
97 inode = *pinode; 97 inode = *pinode;
98 cifsInfo = CIFS_I(inode); 98 cifsInfo = CIFS_I(inode);
99 99
100 cFYI(1, (" Old time %ld ", cifsInfo->time)); 100 cFYI(1, ("Old time %ld ", cifsInfo->time));
101 cifsInfo->time = jiffies; 101 cifsInfo->time = jiffies;
102 cFYI(1, (" New time %ld ", cifsInfo->time)); 102 cFYI(1, ("New time %ld ", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */ 103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1); 104 atomic_set(&cifsInfo->inUse,1);
105 105
@@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
111 inode->i_ctime = 111 inode->i_ctime =
112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); 112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
113 inode->i_mode = le64_to_cpu(findData.Permissions); 113 inode->i_mode = le64_to_cpu(findData.Permissions);
114 /* since we set the inode type below we need to mask off
115 to avoid strange results if bits set above */
116 inode->i_mode &= ~S_IFMT;
114 if (type == UNIX_FILE) { 117 if (type == UNIX_FILE) {
115 inode->i_mode |= S_IFREG; 118 inode->i_mode |= S_IFREG;
116 } else if (type == UNIX_SYMLINK) { 119 } else if (type == UNIX_SYMLINK) {
@@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
129 inode->i_mode |= S_IFIFO; 132 inode->i_mode |= S_IFIFO;
130 } else if (type == UNIX_SOCKET) { 133 } else if (type == UNIX_SOCKET) {
131 inode->i_mode |= S_IFSOCK; 134 inode->i_mode |= S_IFSOCK;
135 } else {
136 /* safest to call it a file if we do not know */
137 inode->i_mode |= S_IFREG;
138 cFYI(1,("unknown type %d",type));
132 } 139 }
133 inode->i_uid = le64_to_cpu(findData.Uid); 140 inode->i_uid = le64_to_cpu(findData.Uid);
134 inode->i_gid = le64_to_cpu(findData.Gid); 141 inode->i_gid = le64_to_cpu(findData.Gid);
@@ -155,34 +162,39 @@ int cifs_get_inode_info_unix(struct inode **pinode,
155 } 162 }
156 163
157 if (num_of_bytes < end_of_file) 164 if (num_of_bytes < end_of_file)
158 cFYI(1, ("allocation size less than end of file ")); 165 cFYI(1, ("allocation size less than end of file"));
159 cFYI(1, 166 cFYI(1,
160 ("Size %ld and blocks %ld", 167 ("Size %ld and blocks %ld",
161 (unsigned long) inode->i_size, inode->i_blocks)); 168 (unsigned long) inode->i_size, inode->i_blocks));
162 if (S_ISREG(inode->i_mode)) { 169 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode ")); 170 cFYI(1, ("File inode"));
164 inode->i_op = &cifs_file_inode_ops; 171 inode->i_op = &cifs_file_inode_ops;
165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 172 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
166 inode->i_fop = &cifs_file_direct_ops; 173 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
167 else 174 inode->i_fop =
175 &cifs_file_direct_nobrl_ops;
176 else
177 inode->i_fop = &cifs_file_direct_ops;
178 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
179 inode->i_fop = &cifs_file_nobrl_ops;
180 else /* not direct, send byte range locks */
168 inode->i_fop = &cifs_file_ops; 181 inode->i_fop = &cifs_file_ops;
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 182
170 inode->i_fop->lock = NULL;
171 inode->i_data.a_ops = &cifs_addr_ops; 183 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */ 184 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf < 185 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE) 186 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL; 187 inode->i_data.a_ops->readpages = NULL;
176 } else if (S_ISDIR(inode->i_mode)) { 188 } else if (S_ISDIR(inode->i_mode)) {
177 cFYI(1, (" Directory inode")); 189 cFYI(1, ("Directory inode"));
178 inode->i_op = &cifs_dir_inode_ops; 190 inode->i_op = &cifs_dir_inode_ops;
179 inode->i_fop = &cifs_dir_ops; 191 inode->i_fop = &cifs_dir_ops;
180 } else if (S_ISLNK(inode->i_mode)) { 192 } else if (S_ISLNK(inode->i_mode)) {
181 cFYI(1, (" Symbolic Link inode ")); 193 cFYI(1, ("Symbolic Link inode"));
182 inode->i_op = &cifs_symlink_inode_ops; 194 inode->i_op = &cifs_symlink_inode_ops;
183 /* tmp_inode->i_fop = */ /* do not need to set to anything */ 195 /* tmp_inode->i_fop = */ /* do not need to set to anything */
184 } else { 196 } else {
185 cFYI(1, (" Init special inode ")); 197 cFYI(1, ("Init special inode"));
186 init_special_inode(inode, inode->i_mode, 198 init_special_inode(inode, inode->i_mode,
187 inode->i_rdev); 199 inode->i_rdev);
188 } 200 }
@@ -190,6 +202,112 @@ int cifs_get_inode_info_unix(struct inode **pinode,
190 return rc; 202 return rc;
191} 203}
192 204
205static int decode_sfu_inode(struct inode * inode, __u64 size,
206 const unsigned char *path,
207 struct cifs_sb_info *cifs_sb, int xid)
208{
209 int rc;
210 int oplock = FALSE;
211 __u16 netfid;
212 struct cifsTconInfo *pTcon = cifs_sb->tcon;
213 char buf[24];
214 unsigned int bytes_read;
215 char * pbuf;
216
217 pbuf = buf;
218
219 if(size == 0) {
220 inode->i_mode |= S_IFIFO;
221 return 0;
222 } else if (size < 8) {
223 return -EINVAL; /* EOPNOTSUPP? */
224 }
225
226 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
227 CREATE_NOT_DIR, &netfid, &oplock, NULL,
228 cifs_sb->local_nls,
229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) {
232 int buf_type = CIFS_NO_BUFFER;
233 /* Read header */
234 rc = CIFSSMBRead(xid, pTcon,
235 netfid,
236 24 /* length */, 0 /* offset */,
237 &bytes_read, &pbuf, &buf_type);
238 if((rc == 0) && (bytes_read >= 8)) {
239 if(memcmp("IntxBLK", pbuf, 8) == 0) {
240 cFYI(1,("Block device"));
241 inode->i_mode |= S_IFBLK;
242 if(bytes_read == 24) {
243 /* we have enough to decode dev num */
244 __u64 mjr; /* major */
245 __u64 mnr; /* minor */
246 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
247 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
248 inode->i_rdev = MKDEV(mjr, mnr);
249 }
250 } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
251 cFYI(1,("Char device"));
252 inode->i_mode |= S_IFCHR;
253 if(bytes_read == 24) {
254 /* we have enough to decode dev num */
255 __u64 mjr; /* major */
256 __u64 mnr; /* minor */
257 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
258 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
259 inode->i_rdev = MKDEV(mjr, mnr);
260 }
261 } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
262 cFYI(1,("Symlink"));
263 inode->i_mode |= S_IFLNK;
264 } else {
265 inode->i_mode |= S_IFREG; /* file? */
266 rc = -EOPNOTSUPP;
267 }
268 } else {
269 inode->i_mode |= S_IFREG; /* then it is a file */
270 rc = -EOPNOTSUPP; /* or some unknown SFU type */
271 }
272 CIFSSMBClose(xid, pTcon, netfid);
273 }
274 return rc;
275
276}
277
278#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
279
280static int get_sfu_uid_mode(struct inode * inode,
281 const unsigned char *path,
282 struct cifs_sb_info *cifs_sb, int xid)
283{
284#ifdef CONFIG_CIFS_XATTR
285 ssize_t rc;
286 char ea_value[4];
287 __u32 mode;
288
289 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
290 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
291 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
292 if(rc < 0)
293 return (int)rc;
294 else if (rc > 3) {
295 mode = le32_to_cpu(*((__le32 *)ea_value));
296 inode->i_mode &= ~SFBITS_MASK;
297 cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
298 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
299 cFYI(1,("special mode bits 0%o", mode));
300 return 0;
301 } else {
302 return 0;
303 }
304#else
305 return -EOPNOTSUPP;
306#endif
307
308
309}
310
193int cifs_get_inode_info(struct inode **pinode, 311int cifs_get_inode_info(struct inode **pinode,
194 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 312 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
195 struct super_block *sb, int xid) 313 struct super_block *sb, int xid)
@@ -202,7 +320,7 @@ int cifs_get_inode_info(struct inode **pinode,
202 char *buf = NULL; 320 char *buf = NULL;
203 321
204 pTcon = cifs_sb->tcon; 322 pTcon = cifs_sb->tcon;
205 cFYI(1,("Getting info on %s ", search_path)); 323 cFYI(1,("Getting info on %s", search_path));
206 324
207 if ((pfindData == NULL) && (*pinode != NULL)) { 325 if ((pfindData == NULL) && (*pinode != NULL)) {
208 if (CIFS_I(*pinode)->clientCanCacheRead) { 326 if (CIFS_I(*pinode)->clientCanCacheRead) {
@@ -303,9 +421,9 @@ int cifs_get_inode_info(struct inode **pinode,
303 inode = *pinode; 421 inode = *pinode;
304 cifsInfo = CIFS_I(inode); 422 cifsInfo = CIFS_I(inode);
305 cifsInfo->cifsAttrs = attr; 423 cifsInfo->cifsAttrs = attr;
306 cFYI(1, (" Old time %ld ", cifsInfo->time)); 424 cFYI(1, ("Old time %ld ", cifsInfo->time));
307 cifsInfo->time = jiffies; 425 cifsInfo->time = jiffies;
308 cFYI(1, (" New time %ld ", cifsInfo->time)); 426 cFYI(1, ("New time %ld ", cifsInfo->time));
309 427
310 /* blksize needs to be multiple of two. So safer to default to 428 /* blksize needs to be multiple of two. So safer to default to
311 blksize and blkbits set in superblock so 2**blkbits and blksize 429 blksize and blkbits set in superblock so 2**blkbits and blksize
@@ -319,13 +437,15 @@ int cifs_get_inode_info(struct inode **pinode,
319 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 437 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
320 inode->i_ctime = 438 inode->i_ctime =
321 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 439 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
322 cFYI(0, (" Attributes came in as 0x%x ", attr)); 440 cFYI(0, ("Attributes came in as 0x%x ", attr));
323 441
324 /* set default mode. will override for dirs below */ 442 /* set default mode. will override for dirs below */
325 if (atomic_read(&cifsInfo->inUse) == 0) 443 if (atomic_read(&cifsInfo->inUse) == 0)
326 /* new inode, can safely set these fields */ 444 /* new inode, can safely set these fields */
327 inode->i_mode = cifs_sb->mnt_file_mode; 445 inode->i_mode = cifs_sb->mnt_file_mode;
328 446 else /* since we set the inode type below we need to mask off
447 to avoid strange results if type changes and both get orred in */
448 inode->i_mode &= ~S_IFMT;
329/* if (attr & ATTR_REPARSE) */ 449/* if (attr & ATTR_REPARSE) */
330 /* We no longer handle these as symlinks because we could not 450 /* We no longer handle these as symlinks because we could not
331 follow them due to the absolute path with drive letter */ 451 follow them due to the absolute path with drive letter */
@@ -340,10 +460,16 @@ int cifs_get_inode_info(struct inode **pinode,
340 (pfindData->EndOfFile == 0)) { 460 (pfindData->EndOfFile == 0)) {
341 inode->i_mode = cifs_sb->mnt_file_mode; 461 inode->i_mode = cifs_sb->mnt_file_mode;
342 inode->i_mode |= S_IFIFO; 462 inode->i_mode |= S_IFIFO;
343/* BB Finish for SFU style symlinks and devies */ 463/* BB Finish for SFU style symlinks and devices */
344/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 464 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
345 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ 465 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
346 466 if (decode_sfu_inode(inode,
467 le64_to_cpu(pfindData->EndOfFile),
468 search_path,
469 cifs_sb, xid)) {
470 cFYI(1,("Unrecognized sfu inode type"));
471 }
472 cFYI(1,("sfu mode 0%o",inode->i_mode));
347 } else { 473 } else {
348 inode->i_mode |= S_IFREG; 474 inode->i_mode |= S_IFREG;
349 /* treat the dos attribute of read-only as read-only 475 /* treat the dos attribute of read-only as read-only
@@ -368,7 +494,10 @@ int cifs_get_inode_info(struct inode **pinode,
368 494
369 /* BB fill in uid and gid here? with help from winbind? 495 /* BB fill in uid and gid here? with help from winbind?
370 or retrieve from NTFS stream extended attribute */ 496 or retrieve from NTFS stream extended attribute */
371 if (atomic_read(&cifsInfo->inUse) == 0) { 497 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
498 /* fill in uid, gid, mode from server ACL */
499 get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
500 } else if (atomic_read(&cifsInfo->inUse) == 0) {
372 inode->i_uid = cifs_sb->mnt_uid; 501 inode->i_uid = cifs_sb->mnt_uid;
373 inode->i_gid = cifs_sb->mnt_gid; 502 inode->i_gid = cifs_sb->mnt_gid;
374 /* set so we do not keep refreshing these fields with 503 /* set so we do not keep refreshing these fields with
@@ -377,24 +506,29 @@ int cifs_get_inode_info(struct inode **pinode,
377 } 506 }
378 507
379 if (S_ISREG(inode->i_mode)) { 508 if (S_ISREG(inode->i_mode)) {
380 cFYI(1, (" File inode ")); 509 cFYI(1, ("File inode"));
381 inode->i_op = &cifs_file_inode_ops; 510 inode->i_op = &cifs_file_inode_ops;
382 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 511 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
383 inode->i_fop = &cifs_file_direct_ops; 512 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
384 else 513 inode->i_fop =
514 &cifs_file_direct_nobrl_ops;
515 else
516 inode->i_fop = &cifs_file_direct_ops;
517 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
518 inode->i_fop = &cifs_file_nobrl_ops;
519 else /* not direct, send byte range locks */
385 inode->i_fop = &cifs_file_ops; 520 inode->i_fop = &cifs_file_ops;
386 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 521
387 inode->i_fop->lock = NULL;
388 inode->i_data.a_ops = &cifs_addr_ops; 522 inode->i_data.a_ops = &cifs_addr_ops;
389 if(pTcon->ses->server->maxBuf < 523 if(pTcon->ses->server->maxBuf <
390 4096 + MAX_CIFS_HDR_SIZE) 524 4096 + MAX_CIFS_HDR_SIZE)
391 inode->i_data.a_ops->readpages = NULL; 525 inode->i_data.a_ops->readpages = NULL;
392 } else if (S_ISDIR(inode->i_mode)) { 526 } else if (S_ISDIR(inode->i_mode)) {
393 cFYI(1, (" Directory inode ")); 527 cFYI(1, ("Directory inode"));
394 inode->i_op = &cifs_dir_inode_ops; 528 inode->i_op = &cifs_dir_inode_ops;
395 inode->i_fop = &cifs_dir_ops; 529 inode->i_fop = &cifs_dir_ops;
396 } else if (S_ISLNK(inode->i_mode)) { 530 } else if (S_ISLNK(inode->i_mode)) {
397 cFYI(1, (" Symbolic Link inode ")); 531 cFYI(1, ("Symbolic Link inode"));
398 inode->i_op = &cifs_symlink_inode_ops; 532 inode->i_op = &cifs_symlink_inode_ops;
399 } else { 533 } else {
400 init_special_inode(inode, inode->i_mode, 534 init_special_inode(inode, inode->i_mode,
@@ -431,7 +565,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
431 struct cifsInodeInfo *cifsInode; 565 struct cifsInodeInfo *cifsInode;
432 FILE_BASIC_INFO *pinfo_buf; 566 FILE_BASIC_INFO *pinfo_buf;
433 567
434 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); 568 cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
435 569
436 xid = GetXid(); 570 xid = GetXid();
437 571
@@ -577,7 +711,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 char *full_path = NULL; 711 char *full_path = NULL;
578 struct inode *newinode = NULL; 712 struct inode *newinode = NULL;
579 713
580 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); 714 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
581 715
582 xid = GetXid(); 716 xid = GetXid();
583 717
@@ -617,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
617 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
618 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 752 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
619 mode, 753 mode,
620 (__u64)current->euid, 754 (__u64)current->fsuid,
621 (__u64)current->egid, 755 (__u64)current->fsgid,
622 0 /* dev_t */, 756 0 /* dev_t */,
623 cifs_sb->local_nls, 757 cifs_sb->local_nls,
624 cifs_sb->mnt_cifs_flags & 758 cifs_sb->mnt_cifs_flags &
@@ -635,6 +769,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
635 /* BB to be implemented via Windows secrty descriptors 769 /* BB to be implemented via Windows secrty descriptors
636 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 770 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
637 -1, -1, local_nls); */ 771 -1, -1, local_nls); */
772 if(direntry->d_inode) {
773 direntry->d_inode->i_mode = mode;
774 direntry->d_inode->i_mode |= S_IFDIR;
775 if(cifs_sb->mnt_cifs_flags &
776 CIFS_MOUNT_SET_UID) {
777 direntry->d_inode->i_uid =
778 current->fsuid;
779 direntry->d_inode->i_gid =
780 current->fsgid;
781 }
782 }
638 } 783 }
639 } 784 }
640 kfree(full_path); 785 kfree(full_path);
@@ -651,7 +796,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
651 char *full_path = NULL; 796 char *full_path = NULL;
652 struct cifsInodeInfo *cifsInode; 797 struct cifsInodeInfo *cifsInode;
653 798
654 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); 799 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
655 800
656 xid = GetXid(); 801 xid = GetXid();
657 802
@@ -896,9 +1041,9 @@ int cifs_revalidate(struct dentry *direntry)
896 } 1041 }
897 1042
898 /* can not grab this sem since kernel filesys locking documentation 1043 /* can not grab this sem since kernel filesys locking documentation
899 indicates i_sem may be taken by the kernel on lookup and rename 1044 indicates i_mutex may be taken by the kernel on lookup and rename
900 which could deadlock if we grab the i_sem here as well */ 1045 which could deadlock if we grab the i_mutex here as well */
901/* down(&direntry->d_inode->i_sem);*/ 1046/* mutex_lock(&direntry->d_inode->i_mutex);*/
902 /* need to write out dirty pages here */ 1047 /* need to write out dirty pages here */
903 if (direntry->d_inode->i_mapping) { 1048 if (direntry->d_inode->i_mapping) {
904 /* do we need to lock inode until after invalidate completes 1049 /* do we need to lock inode until after invalidate completes
@@ -906,17 +1051,23 @@ int cifs_revalidate(struct dentry *direntry)
906 filemap_fdatawrite(direntry->d_inode->i_mapping); 1051 filemap_fdatawrite(direntry->d_inode->i_mapping);
907 } 1052 }
908 if (invalidate_inode) { 1053 if (invalidate_inode) {
909 if (direntry->d_inode->i_mapping) 1054 /* shrink_dcache not necessary now that cifs dentry ops
910 filemap_fdatawait(direntry->d_inode->i_mapping); 1055 are exported for negative dentries */
911 /* may eventually have to do this for open files too */ 1056/* if(S_ISDIR(direntry->d_inode->i_mode))
912 if (list_empty(&(cifsInode->openFileList))) { 1057 shrink_dcache_parent(direntry); */
913 /* Has changed on server - flush read ahead pages */ 1058 if (S_ISREG(direntry->d_inode->i_mode)) {
914 cFYI(1, ("Invalidating read ahead data on " 1059 if (direntry->d_inode->i_mapping)
915 "closed file")); 1060 filemap_fdatawait(direntry->d_inode->i_mapping);
916 invalidate_remote_inode(direntry->d_inode); 1061 /* may eventually have to do this for open files too */
1062 if (list_empty(&(cifsInode->openFileList))) {
1063 /* changed on server - flush read ahead pages */
1064 cFYI(1, ("Invalidating read ahead data on "
1065 "closed file"));
1066 invalidate_remote_inode(direntry->d_inode);
1067 }
917 } 1068 }
918 } 1069 }
919/* up(&direntry->d_inode->i_sem); */ 1070/* mutex_unlock(&direntry->d_inode->i_mutex); */
920 1071
921 kfree(full_path); 1072 kfree(full_path);
922 FreeXid(xid); 1073 FreeXid(xid);
@@ -970,11 +1121,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
970 1121
971 xid = GetXid(); 1122 xid = GetXid();
972 1123
973 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1124 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
974 direntry->d_name.name, attrs->ia_valid)); 1125 direntry->d_name.name, attrs->ia_valid));
1126
975 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
976 pTcon = cifs_sb->tcon; 1128 pTcon = cifs_sb->tcon;
977 1129
1130 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1131 /* check if we have permission to change attrs */
1132 rc = inode_change_ok(direntry->d_inode, attrs);
1133 if(rc < 0) {
1134 FreeXid(xid);
1135 return rc;
1136 } else
1137 rc = 0;
1138 }
1139
978 down(&direntry->d_sb->s_vfs_rename_sem); 1140 down(&direntry->d_sb->s_vfs_rename_sem);
979 full_path = build_path_from_dentry(direntry); 1141 full_path = build_path_from_dentry(direntry);
980 up(&direntry->d_sb->s_vfs_rename_sem); 1142 up(&direntry->d_sb->s_vfs_rename_sem);
@@ -987,8 +1149,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
987 /* BB check if we need to refresh inode from server now ? BB */ 1149 /* BB check if we need to refresh inode from server now ? BB */
988 1150
989 /* need to flush data before changing file size on server */ 1151 /* need to flush data before changing file size on server */
990 filemap_fdatawrite(direntry->d_inode->i_mapping); 1152 filemap_write_and_wait(direntry->d_inode->i_mapping);
991 filemap_fdatawait(direntry->d_inode->i_mapping);
992 1153
993 if (attrs->ia_valid & ATTR_SIZE) { 1154 if (attrs->ia_valid & ATTR_SIZE) {
994 /* To avoid spurious oplock breaks from server, in the case of 1155 /* To avoid spurious oplock breaks from server, in the case of
@@ -1014,7 +1175,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1014 1 /* 45 seconds */); 1175 1 /* 45 seconds */);
1015 cFYI(1,("Wrt seteof rc %d", rc)); 1176 cFYI(1,("Wrt seteof rc %d", rc));
1016 } 1177 }
1017 } 1178 } else
1179 rc = -EINVAL;
1180
1018 if (rc != 0) { 1181 if (rc != 0) {
1019 /* Set file size by pathname rather than by handle 1182 /* Set file size by pathname rather than by handle
1020 either because no valid, writeable file handle for 1183 either because no valid, writeable file handle for
@@ -1086,6 +1249,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1086 cifs_sb->mnt_cifs_flags & 1249 cifs_sb->mnt_cifs_flags &
1087 CIFS_MOUNT_MAP_SPECIAL_CHR); 1250 CIFS_MOUNT_MAP_SPECIAL_CHR);
1088 else if (attrs->ia_valid & ATTR_MODE) { 1251 else if (attrs->ia_valid & ATTR_MODE) {
1252 rc = 0;
1089 if ((mode & S_IWUGO) == 0) /* not writeable */ { 1253 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1090 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) 1254 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1091 time_buf.Attributes = 1255 time_buf.Attributes =
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 34a06692e4fa..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;
@@ -397,12 +404,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
397 if(smb->Command == SMB_COM_LOCKING_ANDX) 404 if(smb->Command == SMB_COM_LOCKING_ANDX)
398 return 0; 405 return 0;
399 else 406 else
400 cERROR(1, ("Rcvd Request not response ")); 407 cERROR(1, ("Rcvd Request not response"));
401 } 408 }
402 } else { /* bad signature or mid */ 409 } else { /* bad signature or mid */
403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) 410 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
404 cERROR(1, 411 cERROR(1,
405 ("Bad protocol string signature header %x ", 412 ("Bad protocol string signature header %x",
406 *(unsigned int *) smb->Protocol)); 413 *(unsigned int *) smb->Protocol));
407 if (mid != smb->Mid) 414 if (mid != smb->Mid)
408 cERROR(1, ("Mids do not match")); 415 cERROR(1, ("Mids do not match"));
@@ -417,7 +424,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
417 __u32 len = smb->smb_buf_length; 424 __u32 len = smb->smb_buf_length;
418 __u32 clc_len; /* calculated length */ 425 __u32 clc_len; /* calculated length */
419 cFYI(0, 426 cFYI(0,
420 ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 427 ("Entering checkSMB with Length: %x, smb_buf_length: %x",
421 length, len)); 428 length, len));
422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || 429 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { 430 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
@@ -451,9 +458,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); 458 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
452 /* Windows XP can return a few bytes too much, presumably 459 /* Windows XP can return a few bytes too much, presumably
453 an illegal pad, at the end of byte range lock responses 460 an illegal pad, at the end of byte range lock responses
454 so we allow for up to eight byte pad, as long as actual 461 so we allow for that three byte pad, as long as actual
455 received length is as long or longer than calculated length */ 462 received length is as long or longer than calculated length */
456 if((4+len > clc_len) && (len <= clc_len + 3)) 463 /* We have now had to extend this more, since there is a
464 case in which it needs to be bigger still to handle a
465 malformed response to transact2 findfirst from WinXP when
466 access denied is returned and thus bcc and wct are zero
467 but server says length is 0x21 bytes too long as if the server
468 forget to reset the smb rfc1001 length when it reset the
469 wct and bcc to minimum size and drop the t2 parms and data */
470 if((4+len > clc_len) && (len <= clc_len + 512))
457 return 0; 471 return 0;
458 else 472 else
459 return 1; 473 return 1;
@@ -678,7 +692,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
678 __u16 temp; 692 __u16 temp;
679 693
680 if(!mapChars) 694 if(!mapChars)
681 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); 695 return cifs_strtoUCS(target, source, PATH_MAX, cp);
682 696
683 for(i = 0, j = 0; i < maxlen; j++) { 697 for(i = 0, j = 0; i < maxlen; j++) {
684 src_char = source[i]; 698 src_char = source[i];
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index f7814689844b..5de74d216fdd 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -330,7 +330,7 @@ static const struct {
330 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { 330 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
331 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { 331 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
332 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { 332 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
333 ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { 333 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
334 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { 334 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
335 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { 335 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
336 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { 336 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
@@ -676,7 +676,7 @@ static const struct {
676 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { 676 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
677 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { 677 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
678 ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { 678 ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
679 ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, { 679 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, {
680 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { 680 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
681 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { 681 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
682 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { 682 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index a86bd1c07602..288cc048d37f 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -142,6 +142,11 @@ static void fill_in_inode(struct inode *tmp_inode,
142 tmp_inode->i_gid = cifs_sb->mnt_gid; 142 tmp_inode->i_gid = cifs_sb->mnt_gid;
143 /* set default mode. will override for dirs below */ 143 /* set default mode. will override for dirs below */
144 tmp_inode->i_mode = cifs_sb->mnt_file_mode; 144 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
145 } else {
146 /* mask off the type bits since it gets set
147 below and we do not want to get two type
148 bits set */
149 tmp_inode->i_mode &= ~S_IFMT;
145 } 150 }
146 151
147 if (attr & ATTR_DIRECTORY) { 152 if (attr & ATTR_DIRECTORY) {
@@ -152,12 +157,18 @@ static void fill_in_inode(struct inode *tmp_inode,
152 } 157 }
153 tmp_inode->i_mode |= S_IFDIR; 158 tmp_inode->i_mode |= S_IFDIR;
154 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 159 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
155 (attr & ATTR_SYSTEM) && (end_of_file == 0)) { 160 (attr & ATTR_SYSTEM)) {
156 *pobject_type = DT_FIFO; 161 if (end_of_file == 0) {
157 tmp_inode->i_mode |= S_IFIFO; 162 *pobject_type = DT_FIFO;
158/* BB Finish for SFU style symlinks and devies */ 163 tmp_inode->i_mode |= S_IFIFO;
159/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 164 } else {
160 (attr & ATTR_SYSTEM) && ) { */ 165 /* rather than get the type here, we mark the
166 inode as needing revalidate and get the real type
167 (blk vs chr vs. symlink) later ie in lookup */
168 *pobject_type = DT_REG;
169 tmp_inode->i_mode |= S_IFREG;
170 cifsInfo->time = 0;
171 }
161/* we no longer mark these because we could not follow them */ 172/* we no longer mark these because we could not follow them */
162/* } else if (attr & ATTR_REPARSE) { 173/* } else if (attr & ATTR_REPARSE) {
163 *pobject_type = DT_LNK; 174 *pobject_type = DT_LNK;
@@ -193,12 +204,17 @@ static void fill_in_inode(struct inode *tmp_inode,
193 if (S_ISREG(tmp_inode->i_mode)) { 204 if (S_ISREG(tmp_inode->i_mode)) {
194 cFYI(1, ("File inode")); 205 cFYI(1, ("File inode"));
195 tmp_inode->i_op = &cifs_file_inode_ops; 206 tmp_inode->i_op = &cifs_file_inode_ops;
196 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 207 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
197 tmp_inode->i_fop = &cifs_file_direct_ops; 208 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
209 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
210 else
211 tmp_inode->i_fop = &cifs_file_direct_ops;
212
213 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
214 tmp_inode->i_fop = &cifs_file_nobrl_ops;
198 else 215 else
199 tmp_inode->i_fop = &cifs_file_ops; 216 tmp_inode->i_fop = &cifs_file_ops;
200 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 217
201 tmp_inode->i_fop->lock = NULL;
202 tmp_inode->i_data.a_ops = &cifs_addr_ops; 218 tmp_inode->i_data.a_ops = &cifs_addr_ops;
203 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 219 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
204 (cifs_sb->tcon->ses->server->maxBuf < 220 (cifs_sb->tcon->ses->server->maxBuf <
@@ -258,6 +274,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
258 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); 274 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
259 275
260 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); 276 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
277 /* since we set the inode type below we need to mask off type
278 to avoid strange results if bits above were corrupt */
279 tmp_inode->i_mode &= ~S_IFMT;
261 if (type == UNIX_FILE) { 280 if (type == UNIX_FILE) {
262 *pobject_type = DT_REG; 281 *pobject_type = DT_REG;
263 tmp_inode->i_mode |= S_IFREG; 282 tmp_inode->i_mode |= S_IFREG;
@@ -283,6 +302,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
283 } else if (type == UNIX_SOCKET) { 302 } else if (type == UNIX_SOCKET) {
284 *pobject_type = DT_SOCK; 303 *pobject_type = DT_SOCK;
285 tmp_inode->i_mode |= S_IFSOCK; 304 tmp_inode->i_mode |= S_IFSOCK;
305 } else {
306 /* safest to just call it a file */
307 *pobject_type = DT_REG;
308 tmp_inode->i_mode |= S_IFREG;
309 cFYI(1,("unknown inode type %d",type));
286 } 310 }
287 311
288 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); 312 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
@@ -302,12 +326,18 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
302 if (S_ISREG(tmp_inode->i_mode)) { 326 if (S_ISREG(tmp_inode->i_mode)) {
303 cFYI(1, ("File inode")); 327 cFYI(1, ("File inode"));
304 tmp_inode->i_op = &cifs_file_inode_ops; 328 tmp_inode->i_op = &cifs_file_inode_ops;
305 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 329
306 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;
307 else 338 else
308 tmp_inode->i_fop = &cifs_file_ops; 339 tmp_inode->i_fop = &cifs_file_ops;
309 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 340
310 tmp_inode->i_fop->lock = NULL;
311 tmp_inode->i_data.a_ops = &cifs_addr_ops; 341 tmp_inode->i_data.a_ops = &cifs_addr_ops;
312 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && 342 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
313 (cifs_sb->tcon->ses->server->maxBuf < 343 (cifs_sb->tcon->ses->server->maxBuf <
@@ -699,7 +729,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
699 (__le16 *)filename, len/2, nlt); 729 (__le16 *)filename, len/2, nlt);
700 else 730 else
701 pqst->len = cifs_strfromUCS_le((char *)pqst->name, 731 pqst->len = cifs_strfromUCS_le((char *)pqst->name,
702 (wchar_t *)filename,len/2,nlt); 732 (__le16 *)filename,len/2,nlt);
703 } else { 733 } else {
704 pqst->name = filename; 734 pqst->name = filename;
705 pqst->len = len; 735 pqst->len = len;
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 981ea0d8b9cd..7b98792150ea 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
@@ -489,21 +489,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
489 receive_len, xid)); 489 receive_len, xid));
490 rc = -EIO; 490 rc = -EIO;
491 } else { /* rcvd frame is ok */ 491 } else { /* rcvd frame is ok */
492
493 if (midQ->resp_buf && 492 if (midQ->resp_buf &&
494 (midQ->midState == MID_RESPONSE_RECEIVED)) { 493 (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 494
501 dump_smb(in_buf, 80); 495 iov[0].iov_base = (char *)midQ->resp_buf;
496 if(midQ->largeBuf)
497 *pRespBufType = CIFS_LARGE_BUFFER;
498 else
499 *pRespBufType = CIFS_SMALL_BUFFER;
500 iov[0].iov_len = receive_len + 4;
501 iov[1].iov_len = 0;
502
503 dump_smb(midQ->resp_buf, 80);
502 /* convert the length into a more usable form */ 504 /* convert the length into a more usable form */
503 if((receive_len > 24) && 505 if((receive_len > 24) &&
504 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 506 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
505 SECMODE_SIGN_ENABLED))) { 507 SECMODE_SIGN_ENABLED))) {
506 rc = cifs_verify_signature(in_buf, 508 rc = cifs_verify_signature(midQ->resp_buf,
507 ses->server->mac_signing_key, 509 ses->server->mac_signing_key,
508 midQ->sequence_number+1); 510 midQ->sequence_number+1);
509 if(rc) { 511 if(rc) {
@@ -512,17 +514,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
512 } 514 }
513 } 515 }
514 516
515 *pbytes_returned = in_buf->smb_buf_length;
516
517 /* BB special case reconnect tid and uid here? */ 517 /* BB special case reconnect tid and uid here? */
518 rc = map_smb_to_linux_error(in_buf); 518 /* BB special case Errbadpassword and pwdexpired here */
519 rc = map_smb_to_linux_error(midQ->resp_buf);
519 520
520 /* convert ByteCount if necessary */ 521 /* convert ByteCount if necessary */
521 if (receive_len >= 522 if (receive_len >=
522 sizeof (struct smb_hdr) - 523 sizeof (struct smb_hdr) -
523 4 /* do not count RFC1001 header */ + 524 4 /* do not count RFC1001 header */ +
524 (2 * in_buf->WordCount) + 2 /* bcc */ ) 525 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
525 BCC(in_buf) = le16_to_cpu(BCC(in_buf)); 526 BCC(midQ->resp_buf) =
527 le16_to_cpu(BCC_LE(midQ->resp_buf));
528 midQ->resp_buf = NULL; /* mark it so will not be freed
529 by DeleteMidQEntry */
526 } else { 530 } else {
527 rc = -EIO; 531 rc = -EIO;
528 cFYI(1,("Bad MID state?")); 532 cFYI(1,("Bad MID state?"));
@@ -548,7 +552,6 @@ out_unlock2:
548 552
549 return rc; 553 return rc;
550} 554}
551#endif /* CIFS_EXPERIMENTAL */
552 555
553int 556int
554SendReceive(const unsigned int xid, struct cifsSesInfo *ses, 557SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -786,10 +789,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
786 sizeof (struct smb_hdr) - 789 sizeof (struct smb_hdr) -
787 4 /* do not count RFC1001 header */ + 790 4 /* do not count RFC1001 header */ +
788 (2 * out_buf->WordCount) + 2 /* bcc */ ) 791 (2 * out_buf->WordCount) + 2 /* bcc */ )
789 BCC(out_buf) = le16_to_cpu(BCC(out_buf)); 792 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
790 } else { 793 } else {
791 rc = -EIO; 794 rc = -EIO;
792 cERROR(1,("Bad MID state? ")); 795 cERROR(1,("Bad MID state?"));
793 } 796 }
794 } 797 }
795cifs_no_response_exit: 798cifs_no_response_exit:
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f375f87c7dbd..777e3363c2a4 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -254,7 +254,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
254 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, 254 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
255 buf_size, cifs_sb->local_nls, 255 buf_size, cifs_sb->local_nls,
256 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 256 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
257 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 257 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
258 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
258#ifdef CONFIG_CIFS_POSIX 259#ifdef CONFIG_CIFS_POSIX
259 if(sb->s_flags & MS_POSIXACL) 260 if(sb->s_flags & MS_POSIXACL)
260 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 261 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
@@ -262,10 +263,27 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
262 cifs_sb->local_nls, 263 cifs_sb->local_nls,
263 cifs_sb->mnt_cifs_flags & 264 cifs_sb->mnt_cifs_flags &
264 CIFS_MOUNT_MAP_SPECIAL_CHR); 265 CIFS_MOUNT_MAP_SPECIAL_CHR);
266/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
267 __u16 fid;
268 int oplock = FALSE;
269 rc = CIFSSMBOpen(xid, pTcon, full_path,
270 FILE_OPEN, GENERIC_READ, 0, &fid,
271 &oplock, NULL, cifs_sb->local_nls,
272 cifs_sb->mnt_cifs_flags &
273 CIFS_MOUNT_MAP_SPECIAL_CHR);
274 if(rc == 0) {
275 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
276 ea_value, buf_size,
277 ACL_TYPE_ACCESS);
278 CIFSSMBClose(xid, pTcon, fid)
279 }
280 } */ /* BB enable after fixing up return data */
281
265#else 282#else
266 cFYI(1,("query POSIX ACL not supported yet")); 283 cFYI(1,("query POSIX ACL not supported yet"));
267#endif /* CONFIG_CIFS_POSIX */ 284#endif /* CONFIG_CIFS_POSIX */
268 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 285 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
286 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
269#ifdef CONFIG_CIFS_POSIX 287#ifdef CONFIG_CIFS_POSIX
270 if(sb->s_flags & MS_POSIXACL) 288 if(sb->s_flags & MS_POSIXACL)
271 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 289 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,