diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/CHANGES | 16 | ||||
-rw-r--r-- | fs/cifs/README | 42 | ||||
-rw-r--r-- | fs/cifs/TODO | 4 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 51 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.c | 13 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifs_uniupr.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 38 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 57 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 158 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 18 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 107 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 23 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 360 | ||||
-rw-r--r-- | fs/cifs/connect.c | 180 | ||||
-rw-r--r-- | fs/cifs/dir.c | 74 | ||||
-rw-r--r-- | fs/cifs/file.c | 81 | ||||
-rw-r--r-- | fs/cifs/inode.c | 268 | ||||
-rw-r--r-- | fs/cifs/misc.c | 36 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 60 | ||||
-rw-r--r-- | fs/cifs/rfc1002pdu.h | 4 | ||||
-rw-r--r-- | fs/cifs/transport.c | 43 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 22 |
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 @@ | |||
1 | Version 1.40 | ||
2 | ------------ | ||
3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance | ||
4 | of readpages by eliminating one extra memcpy. Allow update of file size | ||
5 | from remote server even if file is open for write as long as mount is | ||
6 | directio. Recognize share mode security and send NTLM encrypted password | ||
7 | on tree connect if share mode negotiated. | ||
8 | |||
1 | Version 1.39 | 9 | Version 1.39 |
2 | ------------ | 10 | ------------ |
3 | Defer close of a file handle slightly if pending writes depend on that file handle | 11 | Defer 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 |
5 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 | 13 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 |
14 | Fix SFU style symlinks and mknod needed for servers which do not support the | ||
15 | CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative | ||
16 | dentries so files that the client sees as deleted but that later get created | ||
17 | on the server will be recognized. Add client side permission check on setattr. | ||
18 | Timeout stuck requests better (where server has never responded or sent corrupt | ||
19 | responses) | ||
6 | 20 | ||
7 | Version 1.38 | 21 | Version 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). | ||
439 | sec 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 | |||
422 | The mount.cifs mount helper also accepts a few mount options before -o | 450 | The mount.cifs mount helper also accepts a few mount options before -o |
423 | including: | 451 | including: |
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 @@ | |||
1 | version 1.37 October 9, 2005 | 1 | Version 1.39 November 30, 2005 |
2 | 2 | ||
3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
4 | ================================== | 4 | ================================== |
@@ -58,7 +58,7 @@ o) Improve performance of readpages by sending more than one read | |||
58 | at a time when 8 pages or more are requested. In conjuntion | 58 | at a time when 8 pages or more are requested. In conjuntion |
59 | add support for async_cifs_readpages. | 59 | add support for async_cifs_readpages. |
60 | 60 | ||
61 | p) Add support for storing symlink and fifo info to Windows servers | 61 | p) Add support for storing symlink info to Windows servers |
62 | in the Extended Attribute format their SFU clients would recognize. | 62 | in the Extended Attribute format their SFU clients would recognize. |
63 | 63 | ||
64 | q) Finish fcntl D_NOTIFY support so kde and gnome file list windows | 64 | q) 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; | |||
389 | static write_proc_t ntlmv2_enabled_write; | 401 | static write_proc_t ntlmv2_enabled_write; |
390 | static read_proc_t packet_signing_enabled_read; | 402 | static read_proc_t packet_signing_enabled_read; |
391 | static write_proc_t packet_signing_enabled_write; | 403 | static write_proc_t packet_signing_enabled_write; |
392 | static read_proc_t quotaEnabled_read; | 404 | static read_proc_t experimEnabled_read; |
393 | static write_proc_t quotaEnabled_write; | 405 | static write_proc_t experimEnabled_write; |
394 | static read_proc_t linuxExtensionsEnabled_read; | 406 | static read_proc_t linuxExtensionsEnabled_read; |
395 | static write_proc_t linuxExtensionsEnabled_write; | 407 | static 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 | ||
576 | static int | 588 | static int |
577 | quotaEnabled_read(char *page, char **start, off_t off, | 589 | experimEnabled_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 | } |
598 | static int | 609 | static int |
599 | quotaEnabled_write(struct file *file, const char __user *buffer, | 610 | experimEnabled_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 | ||
616 | static int | 629 | static 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 | ||
31 | struct cifs_sb_info { | 32 | struct 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 | */ |
33 | int | 33 | int |
34 | cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */ | 34 | cifs_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 | */ |
62 | int | 62 | int |
63 | cifs_strtoUCS(wchar_t * to, const char *from, int len, | 63 | cifs_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__ |
62 | int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *); | 62 | int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *); |
63 | int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *); | 63 | int 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 | */ |
245 | const static struct UniCaseRange CifsUniLowerRange[] = { | 245 | static 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 | |||
25 | struct 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 */ | ||
34 | extern const struct cifs_sid sid_everyone; | ||
35 | /* group users */ | ||
36 | extern 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 | ||
85 | static 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 | |||
105 | int 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 | |||
85 | int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, | 138 | int 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 | ||
486 | static ssize_t | 492 | static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, |
487 | cifs_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 | ||
514 | static ssize_t | 504 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, |
515 | cifs_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 | ||
516 | static 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 | ||
537 | static struct file_system_type cifs_fs_type = { | 527 | static 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 | ||
596 | struct file_operations cifs_file_ops = { | 586 | struct 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 | }; | ||
629 | struct 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 | ||
652 | struct 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 | |||
639 | struct file_operations cifs_dir_ops = { | 671 | struct 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 | ||
883 | static int cifs_dnotify_thread(void * dummyarg) | 916 | static 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 */ |
64 | extern struct file_operations cifs_file_ops; | 64 | extern struct file_operations cifs_file_ops; |
65 | extern struct file_operations cifs_file_direct_ops; /* if directio mount */ | 65 | extern struct file_operations cifs_file_direct_ops; /* if directio mount */ |
66 | extern struct file_operations cifs_file_nobrl_ops; | ||
67 | extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ | ||
66 | extern int cifs_open(struct inode *inode, struct file *file); | 68 | extern int cifs_open(struct inode *inode, struct file *file); |
67 | extern int cifs_close(struct inode *inode, struct file *file); | 69 | extern int cifs_close(struct inode *inode, struct file *file); |
68 | extern int cifs_closedir(struct inode *inode, struct file *file); | 70 | extern 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); | |||
97 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 99 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
98 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 100 | extern 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 | ||
290 | struct cifsFileInfo { | 293 | struct 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; | |||
505 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; | 513 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; |
506 | 514 | ||
507 | /* Various Debug counters to remove someday (BB) */ | 515 | /* Various Debug counters to remove someday (BB) */ |
508 | GLOBAL_EXTERN atomic_t bufAllocCount; | 516 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ |
509 | GLOBAL_EXTERN atomic_t smBufAllocCount; | 517 | #ifdef CONFIG_CIFS_STATS2 |
518 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ | ||
519 | GLOBAL_EXTERN atomic_t totSmBufAllocCount; | ||
520 | #endif | ||
521 | GLOBAL_EXTERN atomic_t smBufAllocCount; | ||
510 | GLOBAL_EXTERN atomic_t midCount; | 522 | GLOBAL_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 | ||
606 | typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */ | 610 | typedef 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 | /*******************************************************/ | ||
1015 | typedef 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 | |||
1036 | typedef 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 | |||
1008 | typedef struct smb_com_transaction_ioctl_req { | 1053 | typedef 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 | |||
1098 | typedef 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 | |||
1049 | typedef struct smb_com_transaction_change_notify_req { | 1120 | typedef 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 */ | ||
1073 | typedef struct smb_com_transaction_change_notify_rsp { | 1146 | typedef 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 | ||
2101 | struct win_dev { | ||
2102 | unsigned char type[8]; /* IntxCHR or IntxBLK */ | ||
2103 | __le64 major; | ||
2104 | __le64 minor; | ||
2105 | } __attribute__((packed)); | ||
2106 | |||
2028 | struct gea { | 2107 | struct 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); |
50 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, | 50 | extern 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); |
53 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); | 53 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); |
54 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); | 54 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); |
55 | extern int is_valid_oplock_break(struct smb_hdr *smb); | 55 | extern 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 | ||
95 | extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 95 | extern 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 | ||
99 | extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 100 | extern 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 | ||
102 | extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, | 103 | extern 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 | ||
232 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 233 | extern 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); | ||
235 | extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | 237 | extern 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 | ||
241 | extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 242 | extern 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 */ | ||
246 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 246 | extern 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 *); | |||
269 | extern int cifs_reconnect(struct TCP_Server_Info *server); | 269 | extern int cifs_reconnect(struct TCP_Server_Info *server); |
270 | 270 | ||
271 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); | 271 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); |
272 | extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | ||
273 | __u32 *); | ||
272 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, | 274 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, |
273 | __u32 expected_sequence_number); | 275 | __u32 expected_sequence_number); |
274 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); | 276 | extern 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); |
302 | extern 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 */); | ||
300 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 305 | extern 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 |
42 | static struct { | 43 | static 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 | |||
940 | int | 963 | int |
941 | CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 964 | CIFSSMBRead(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 | |||
1027 | int | 1065 | int |
1028 | CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | 1066 | CIFSSMBWrite(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 | ||
1134 | int | 1171 | int |
1135 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1172 | CIFSSMBWrite2(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 | |||
1212 | int | 1261 | int |
1213 | CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 1262 | CIFSSMBLock(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 */ | ||
1938 | static int | ||
1939 | smb_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 | |||
1968 | static int | ||
1969 | validate_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 | |||
1882 | int | 2015 | int |
1883 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2016 | CIFSSMBQueryReparseLinkInfo(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: | |||
1983 | static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) | 2119 | static 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 */ | ||
2501 | const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | ||
2502 | /* group users */ | ||
2503 | const 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 */ | ||
2506 | static 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 */ | ||
2512 | int | ||
2513 | CIFSSMBGetCIFSACL(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 | } | ||
2575 | qsec_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 */ |
2363 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 2587 | int 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 | ||
295 | int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) | 302 | int 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 | ||
1028 | static int cifs_writepages(struct address_space *mapping, | 1025 | static 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 | ||
1232 | static int cifs_writepage(struct page* page, struct writeback_control *wbc) | 1228 | static 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, ¤t_offset); | 1521 | &bytes_read, ¤t_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 | ||
205 | static 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 | |||
280 | static 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 | |||
193 | int cifs_get_inode_info(struct inode **pinode, | 311 | int 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 | ||
210 | static int | 209 | static int |
211 | smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | 210 | smb_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 | ||
300 | int | 299 | int |
301 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | 300 | SendReceive2(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 | ||
553 | int | 556 | int |
554 | SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | 557 | SendReceive(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 | } |
795 | cifs_no_response_exit: | 798 | cifs_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, |