aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES6
-rw-r--r--fs/cifs/README30
-rw-r--r--fs/cifs/TODO4
-rw-r--r--fs/cifs/cifs_unicode.c13
-rw-r--r--fs/cifs/cifs_unicode.h6
-rw-r--r--fs/cifs/cifsencrypt.c2
-rw-r--r--fs/cifs/cifsfs.c130
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifspdu.h10
-rw-r--r--fs/cifs/cifssmb.c68
-rw-r--r--fs/cifs/connect.c91
-rw-r--r--fs/cifs/dir.c66
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c252
-rw-r--r--fs/cifs/misc.c19
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/readdir.c43
-rw-r--r--fs/cifs/transport.c5
18 files changed, 540 insertions, 213 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index eab3750cf3..943ef9b822 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,8 +1,12 @@
1Version 1.39 1Version 1.39
2------------ 2------------
3Defer close of a file handle slightly if pending writes depend on that file handle 3Defer 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 4(this reduces the EBADF bad file handle errors that can be logged under heavy
5stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 5stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2
6Fix SFU style symlinks and mknod needed for servers which do not support the
7CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
8dentries so files that the client sees as deleted but that later get created
9on the server will be recognized. Add client side permission check on setattr.
6 10
7Version 1.38 11Version 1.38
8------------ 12------------
diff --git a/fs/cifs/README b/fs/cifs/README
index bb90941826..e5d09a2fc7 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,6 +429,13 @@ 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)
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).
421 439
422The mount.cifs mount helper also accepts a few mount options before -o 440The mount.cifs mount helper also accepts a few mount options before -o
423including: 441including:
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index c909298d11..fc34c74ec4 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
1version 1.37 October 9, 2005 1Version 1.39 November 30, 2005
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -58,7 +58,7 @@ o) Improve performance of readpages by sending more than one read
58at a time when 8 pages or more are requested. In conjuntion 58at a time when 8 pages or more are requested. In conjuntion
59add support for async_cifs_readpages. 59add support for async_cifs_readpages.
60 60
61p) Add support for storing symlink and fifo info to Windows servers 61p) Add support for storing symlink info to Windows servers
62in the Extended Attribute format their SFU clients would recognize. 62in the Extended Attribute format their SFU clients would recognize.
63 63
64q) Finish fcntl D_NOTIFY support so kde and gnome file list windows 64q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 4e12053f08..d2b1282559 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifs_unicode.c 2 * fs/cifs/cifs_unicode.c
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2000,2002 4 * Copyright (c) International Business Machines Corp., 2000,2005
5 * Modified by Steve French (sfrench@us.ibm.com) 5 * Modified by Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
31 * 31 *
32 */ 32 */
33int 33int
34cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */ 34cifs_strfromUCS_le(char *to, const __le16 * from,
35 int len, const struct nls_table *codepage) 35 int len, const struct nls_table *codepage)
36{ 36{
37 int i; 37 int i;
@@ -60,25 +60,26 @@ cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
60 * 60 *
61 */ 61 */
62int 62int
63cifs_strtoUCS(wchar_t * to, const char *from, int len, 63cifs_strtoUCS(__le16 * to, const char *from, int len,
64 const struct nls_table *codepage) 64 const struct nls_table *codepage)
65{ 65{
66 int charlen; 66 int charlen;
67 int i; 67 int i;
68 wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
68 69
69 for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 70 for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
70 71
71 /* works for 2.4.0 kernel or later */ 72 /* works for 2.4.0 kernel or later */
72 charlen = codepage->char2uni(from, len, &to[i]); 73 charlen = codepage->char2uni(from, len, &wchar_to[i]);
73 if (charlen < 1) { 74 if (charlen < 1) {
74 cERROR(1, 75 cERROR(1,
75 ("cifs_strtoUCS: char2uni returned %d", 76 ("cifs_strtoUCS: char2uni returned %d",
76 charlen)); 77 charlen));
77 /* A question mark */ 78 /* A question mark */
78 to[i] = (wchar_t)cpu_to_le16(0x003f); 79 to[i] = cpu_to_le16(0x003f);
79 charlen = 1; 80 charlen = 1;
80 } else 81 } else
81 to[i] = (wchar_t)cpu_to_le16(to[i]); 82 to[i] = cpu_to_le16(wchar_to[i]);
82 83
83 } 84 }
84 85
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index da8dde9652..39e5b97032 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -5,7 +5,7 @@
5 * Convert a unicode character to upper or lower case using 5 * Convert a unicode character to upper or lower case using
6 * compressed tables. 6 * compressed tables.
7 * 7 *
8 * Copyright (c) International Business Machines Corp., 2000,2002 8 * Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -59,8 +59,8 @@ extern struct UniCaseRange UniLowerRange[];
59#endif /* UNIUPR_NOLOWER */ 59#endif /* UNIUPR_NOLOWER */
60 60
61#ifdef __KERNEL__ 61#ifdef __KERNEL__
62int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *); 62int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
63int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *); 63int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
64#endif 64#endif
65 65
66/* 66/*
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 1959c7c4b1..fe2bb7c4c9 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -149,7 +149,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
149 char temp_hash[16]; 149 char temp_hash[16];
150 struct HMACMD5Context ctx; 150 struct HMACMD5Context ctx;
151 char * ucase_buf; 151 char * ucase_buf;
152 wchar_t * unicode_buf; 152 __le16 * unicode_buf;
153 unsigned int i,user_name_len,dom_name_len; 153 unsigned int i,user_name_len,dom_name_len;
154 154
155 if(ses == NULL) 155 if(ses == NULL)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 682b0235ad..2a13a2bac8 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,57 +489,30 @@ cifs_get_sb(struct file_system_type *fs_type,
483 return sb; 489 return sb;
484} 490}
485 491
486static ssize_t 492static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
487cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size, 493 unsigned long nr_segs, loff_t *ppos)
488 loff_t * poffset)
489{ 494{
490 if(file->f_dentry == NULL) 495 struct inode *inode = file->f_dentry->d_inode;
491 return -EIO; 496 ssize_t written;
492 else if(file->f_dentry->d_inode == NULL)
493 return -EIO;
494
495 cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
496 497
497 if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) { 498 written = generic_file_writev(file, iov, nr_segs, ppos);
498 return generic_file_read(file,read_data,read_size,poffset); 499 if (!CIFS_I(inode)->clientCanCacheAll)
499 } else { 500 filemap_fdatawrite(inode->i_mapping);
500 /* BB do we need to lock inode from here until after invalidate? */ 501 return written;
501/* if(file->f_dentry->d_inode->i_mapping) {
502 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
503 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
504 }*/
505/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
506
507 /* BB we should make timer configurable - perhaps
508 by simply calling cifs_revalidate here */
509 /* invalidate_remote_inode(file->f_dentry->d_inode);*/
510 return generic_file_read(file,read_data,read_size,poffset);
511 }
512} 502}
513 503
514static ssize_t 504static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
515cifs_write_wrapper(struct file * file, const char __user *write_data, 505 size_t count, loff_t pos)
516 size_t write_size, loff_t * poffset)
517{ 506{
507 struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
518 ssize_t written; 508 ssize_t written;
519 509
520 if(file->f_dentry == NULL) 510 written = generic_file_aio_write(iocb, buf, count, pos);
521 return -EIO; 511 if (!CIFS_I(inode)->clientCanCacheAll)
522 else if(file->f_dentry->d_inode == NULL) 512 filemap_fdatawrite(inode->i_mapping);
523 return -EIO;
524
525 cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
526
527 written = generic_file_write(file,write_data,write_size,poffset);
528 if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
529 if(file->f_dentry->d_inode->i_mapping) {
530 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
531 }
532 }
533 return written; 513 return written;
534} 514}
535 515
536
537static struct file_system_type cifs_fs_type = { 516static struct file_system_type cifs_fs_type = {
538 .owner = THIS_MODULE, 517 .owner = THIS_MODULE,
539 .name = "cifs", 518 .name = "cifs",
@@ -594,8 +573,12 @@ struct inode_operations cifs_symlink_inode_ops = {
594}; 573};
595 574
596struct file_operations cifs_file_ops = { 575struct file_operations cifs_file_ops = {
597 .read = cifs_read_wrapper, 576 .read = do_sync_read,
598 .write = cifs_write_wrapper, 577 .write = do_sync_write,
578 .readv = generic_file_readv,
579 .writev = cifs_file_writev,
580 .aio_read = generic_file_aio_read,
581 .aio_write = cifs_file_aio_write,
599 .open = cifs_open, 582 .open = cifs_open,
600 .release = cifs_close, 583 .release = cifs_close,
601 .lock = cifs_lock, 584 .lock = cifs_lock,
@@ -608,10 +591,6 @@ struct file_operations cifs_file_ops = {
608#endif /* CONFIG_CIFS_POSIX */ 591#endif /* CONFIG_CIFS_POSIX */
609 592
610#ifdef CONFIG_CIFS_EXPERIMENTAL 593#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, 594 .dir_notify = cifs_dir_notify,
616#endif /* CONFIG_CIFS_EXPERIMENTAL */ 595#endif /* CONFIG_CIFS_EXPERIMENTAL */
617}; 596};
@@ -635,6 +614,46 @@ struct file_operations cifs_file_direct_ops = {
635 .dir_notify = cifs_dir_notify, 614 .dir_notify = cifs_dir_notify,
636#endif /* CONFIG_CIFS_EXPERIMENTAL */ 615#endif /* CONFIG_CIFS_EXPERIMENTAL */
637}; 616};
617struct file_operations cifs_file_nobrl_ops = {
618 .read = do_sync_read,
619 .write = do_sync_write,
620 .readv = generic_file_readv,
621 .writev = cifs_file_writev,
622 .aio_read = generic_file_aio_read,
623 .aio_write = cifs_file_aio_write,
624 .open = cifs_open,
625 .release = cifs_close,
626 .fsync = cifs_fsync,
627 .flush = cifs_flush,
628 .mmap = cifs_file_mmap,
629 .sendfile = generic_file_sendfile,
630#ifdef CONFIG_CIFS_POSIX
631 .ioctl = cifs_ioctl,
632#endif /* CONFIG_CIFS_POSIX */
633
634#ifdef CONFIG_CIFS_EXPERIMENTAL
635 .dir_notify = cifs_dir_notify,
636#endif /* CONFIG_CIFS_EXPERIMENTAL */
637};
638
639struct file_operations cifs_file_direct_nobrl_ops = {
640 /* no mmap, no aio, no readv -
641 BB reevaluate whether they can be done with directio, no cache */
642 .read = cifs_user_read,
643 .write = cifs_user_write,
644 .open = cifs_open,
645 .release = cifs_close,
646 .fsync = cifs_fsync,
647 .flush = cifs_flush,
648 .sendfile = generic_file_sendfile, /* BB removeme BB */
649#ifdef CONFIG_CIFS_POSIX
650 .ioctl = cifs_ioctl,
651#endif /* CONFIG_CIFS_POSIX */
652
653#ifdef CONFIG_CIFS_EXPERIMENTAL
654 .dir_notify = cifs_dir_notify,
655#endif /* CONFIG_CIFS_EXPERIMENTAL */
656};
638 657
639struct file_operations cifs_dir_ops = { 658struct file_operations cifs_dir_ops = {
640 .readdir = cifs_readdir, 659 .readdir = cifs_readdir,
@@ -882,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg)
882 901
883static int cifs_dnotify_thread(void * dummyarg) 902static int cifs_dnotify_thread(void * dummyarg)
884{ 903{
904 struct list_head *tmp;
905 struct cifsSesInfo *ses;
906
885 daemonize("cifsdnotifyd"); 907 daemonize("cifsdnotifyd");
886 allow_signal(SIGTERM); 908 allow_signal(SIGTERM);
887 909
@@ -890,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg)
890 if(try_to_freeze()) 912 if(try_to_freeze())
891 continue; 913 continue;
892 set_current_state(TASK_INTERRUPTIBLE); 914 set_current_state(TASK_INTERRUPTIBLE);
893 schedule_timeout(39*HZ); 915 schedule_timeout(15*HZ);
916 read_lock(&GlobalSMBSeslock);
917 /* check if any stuck requests that need
918 to be woken up and wakeq so the
919 thread can wake up and error out */
920 list_for_each(tmp, &GlobalSMBSessionList) {
921 ses = list_entry(tmp, struct cifsSesInfo,
922 cifsSessionList);
923 if(ses && ses->server &&
924 atomic_read(&ses->server->inFlight))
925 wake_up_all(&ses->server->response_q);
926 }
927 read_unlock(&GlobalSMBSeslock);
894 } while(!signal_pending(current)); 928 } while(!signal_pending(current));
895 complete_and_exit (&cifs_dnotify_exited, 0); 929 complete_and_exit (&cifs_dnotify_exited, 0);
896} 930}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 1223fa81db..9ec40e0e54 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -63,6 +63,8 @@ extern struct inode_operations cifs_symlink_inode_ops;
63/* Functions related to files and directories */ 63/* Functions related to files and directories */
64extern struct file_operations cifs_file_ops; 64extern struct file_operations cifs_file_ops;
65extern struct file_operations cifs_file_direct_ops; /* if directio mount */ 65extern struct file_operations cifs_file_direct_ops; /* if directio mount */
66extern struct file_operations cifs_file_nobrl_ops;
67extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
66extern int cifs_open(struct inode *inode, struct file *file); 68extern int cifs_open(struct inode *inode, struct file *file);
67extern int cifs_close(struct inode *inode, struct file *file); 69extern int cifs_close(struct inode *inode, struct file *file);
68extern int cifs_closedir(struct inode *inode, struct file *file); 70extern int cifs_closedir(struct inode *inode, struct file *file);
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 48a05b9df7..33e1859fd2 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -603,7 +603,9 @@ typedef struct smb_com_logoff_andx_rsp {
603 __u16 ByteCount; 603 __u16 ByteCount;
604} __attribute__((packed)) LOGOFF_ANDX_RSP; 604} __attribute__((packed)) LOGOFF_ANDX_RSP;
605 605
606typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */ 606typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
607 tree_connect PDU to effect disconnect */
608 /* tdis is probably simplest SMB PDU */
607 struct { 609 struct {
608 struct smb_hdr hdr; /* wct = 0 */ 610 struct smb_hdr hdr; /* wct = 0 */
609 __u16 ByteCount; /* bcc = 0 */ 611 __u16 ByteCount; /* bcc = 0 */
@@ -2025,6 +2027,12 @@ typedef struct {
2025} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ 2027} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
2026 2028
2027 2029
2030struct win_dev {
2031 unsigned char type[8]; /* IntxCHR or IntxBLK */
2032 __le64 major;
2033 __le64 minor;
2034} __attribute__((packed));
2035
2028struct gea { 2036struct gea {
2029 unsigned char name_len; 2037 unsigned char name_len;
2030 char name[1]; 2038 char name[1];
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a53c596e10..6867e556d3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
90 check for tcp and smb session status done differently 90 check for tcp and smb session status done differently
91 for those three - in the calling routine */ 91 for those three - in the calling routine */
92 if(tcon) { 92 if(tcon) {
93 if(tcon->tidStatus == CifsExiting) {
94 /* only tree disconnect, open, and write,
95 (and ulogoff which does not have tcon)
96 are allowed as we start force umount */
97 if((smb_command != SMB_COM_WRITE_ANDX) &&
98 (smb_command != SMB_COM_OPEN_ANDX) &&
99 (smb_command != SMB_COM_TREE_DISCONNECT)) {
100 cFYI(1,("can not send cmd %d while umounting",
101 smb_command));
102 return -ENODEV;
103 }
104 }
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 105 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){ 106 (tcon->ses->server)){
95 struct nls_table *nls_codepage; 107 struct nls_table *nls_codepage;
@@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
187 check for tcp and smb session status done differently 199 check for tcp and smb session status done differently
188 for those three - in the calling routine */ 200 for those three - in the calling routine */
189 if(tcon) { 201 if(tcon) {
202 if(tcon->tidStatus == CifsExiting) {
203 /* only tree disconnect, open, and write,
204 (and ulogoff which does not have tcon)
205 are allowed as we start force umount */
206 if((smb_command != SMB_COM_WRITE_ANDX) &&
207 (smb_command != SMB_COM_OPEN_ANDX) &&
208 (smb_command != SMB_COM_TREE_DISCONNECT)) {
209 cFYI(1,("can not send cmd %d while umounting",
210 smb_command));
211 return -ENODEV;
212 }
213 }
214
190 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 215 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
191 (tcon->ses->server)){ 216 (tcon->ses->server)){
192 struct nls_table *nls_codepage; 217 struct nls_table *nls_codepage;
@@ -1142,7 +1167,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1142 int bytes_returned, wct; 1167 int bytes_returned, wct;
1143 int smb_hdr_len; 1168 int smb_hdr_len;
1144 1169
1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */ 1170 /* BB removeme BB */
1171 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1172
1146 if(tcon->ses->capabilities & CAP_LARGE_FILES) 1173 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1147 wct = 14; 1174 wct = 14;
1148 else 1175 else
@@ -1553,7 +1580,7 @@ createSymLinkRetry:
1553 1580
1554 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1581 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1555 name_len = 1582 name_len =
1556 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX 1583 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1557 /* find define for this maxpathcomponent */ 1584 /* find define for this maxpathcomponent */
1558 , nls_codepage); 1585 , nls_codepage);
1559 name_len++; /* trailing null */ 1586 name_len++; /* trailing null */
@@ -1577,7 +1604,7 @@ createSymLinkRetry:
1577 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 1604 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1579 name_len_target = 1606 name_len_target =
1580 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX 1607 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1581 /* find define for this maxpathcomponent */ 1608 /* find define for this maxpathcomponent */
1582 , nls_codepage); 1609 , nls_codepage);
1583 name_len_target++; /* trailing null */ 1610 name_len_target++; /* trailing null */
@@ -1803,7 +1830,7 @@ querySymLinkRetry:
1803 1830
1804 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1831 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1805 name_len = 1832 name_len =
1806 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 1833 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1807 /* find define for this maxpathcomponent */ 1834 /* find define for this maxpathcomponent */
1808 , nls_codepage); 1835 , nls_codepage);
1809 name_len++; /* trailing null */ 1836 name_len++; /* trailing null */
@@ -1860,7 +1887,7 @@ querySymLinkRetry:
1860 min_t(const int, buflen,count) / 2); 1887 min_t(const int, buflen,count) / 2);
1861 /* BB FIXME investigate remapping reserved chars here */ 1888 /* BB FIXME investigate remapping reserved chars here */
1862 cifs_strfromUCS_le(symlinkinfo, 1889 cifs_strfromUCS_le(symlinkinfo,
1863 (wchar_t *) ((char *)&pSMBr->hdr.Protocol + 1890 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1864 data_offset), 1891 data_offset),
1865 name_len, nls_codepage); 1892 name_len, nls_codepage);
1866 } else { 1893 } else {
@@ -1951,7 +1978,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1951 reparse_buf->TargetNameOffset), 1978 reparse_buf->TargetNameOffset),
1952 min(buflen/2, reparse_buf->TargetNameLen / 2)); 1979 min(buflen/2, reparse_buf->TargetNameLen / 2));
1953 cifs_strfromUCS_le(symlinkinfo, 1980 cifs_strfromUCS_le(symlinkinfo,
1954 (wchar_t *) (reparse_buf->LinkNamesBuf + 1981 (__le16 *) (reparse_buf->LinkNamesBuf +
1955 reparse_buf->TargetNameOffset), 1982 reparse_buf->TargetNameOffset),
1956 name_len, nls_codepage); 1983 name_len, nls_codepage);
1957 } else { /* ASCII names */ 1984 } else { /* ASCII names */
@@ -1983,9 +2010,9 @@ qreparse_out:
1983static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) 2010static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1984{ 2011{
1985 /* u8 cifs fields do not need le conversion */ 2012 /* u8 cifs fields do not need le conversion */
1986 ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 2013 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
1987 ace->e_tag = (__u16)cifs_ace->cifs_e_tag; 2014 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
1988 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid); 2015 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)); */ 2016 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1990 2017
1991 return; 2018 return;
@@ -2037,7 +2064,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2037 } else if(size > buflen) { 2064 } else if(size > buflen) {
2038 return -ERANGE; 2065 return -ERANGE;
2039 } else /* buffer big enough */ { 2066 } else /* buffer big enough */ {
2040 local_acl->a_version = POSIX_ACL_XATTR_VERSION; 2067 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2041 for(i = 0;i < count ;i++) { 2068 for(i = 0;i < count ;i++) {
2042 cifs_convert_ace(&local_acl->a_entries[i],pACE); 2069 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2043 pACE ++; 2070 pACE ++;
@@ -2051,14 +2078,14 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2051{ 2078{
2052 __u16 rc = 0; /* 0 = ACL converted ok */ 2079 __u16 rc = 0; /* 0 = ACL converted ok */
2053 2080
2054 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm); 2081 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); 2082 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2056 /* BB is there a better way to handle the large uid? */ 2083 /* BB is there a better way to handle the large uid? */
2057 if(local_ace->e_id == -1) { 2084 if(local_ace->e_id == cpu_to_le32(-1)) {
2058 /* Probably no need to le convert -1 on any arch but can not hurt */ 2085 /* Probably no need to le convert -1 on any arch but can not hurt */
2059 cifs_ace->cifs_uid = cpu_to_le64(-1); 2086 cifs_ace->cifs_uid = cpu_to_le64(-1);
2060 } else 2087 } else
2061 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id); 2088 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));*/ 2089 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2063 return rc; 2090 return rc;
2064} 2091}
@@ -2078,16 +2105,17 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl
2078 2105
2079 count = posix_acl_xattr_count((size_t)buflen); 2106 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", 2107 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2081 count,buflen,local_acl->a_version)); 2108 count, buflen, le32_to_cpu(local_acl->a_version)));
2082 if(local_acl->a_version != 2) { 2109 if(le32_to_cpu(local_acl->a_version) != 2) {
2083 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version)); 2110 cFYI(1,("unknown POSIX ACL version %d",
2111 le32_to_cpu(local_acl->a_version)));
2084 return 0; 2112 return 0;
2085 } 2113 }
2086 cifs_acl->version = cpu_to_le16(1); 2114 cifs_acl->version = cpu_to_le16(1);
2087 if(acl_type == ACL_TYPE_ACCESS) 2115 if(acl_type == ACL_TYPE_ACCESS)
2088 cifs_acl->access_entry_count = count; 2116 cifs_acl->access_entry_count = cpu_to_le16(count);
2089 else if(acl_type == ACL_TYPE_DEFAULT) 2117 else if(acl_type == ACL_TYPE_DEFAULT)
2090 cifs_acl->default_entry_count = count; 2118 cifs_acl->default_entry_count = cpu_to_le16(count);
2091 else { 2119 else {
2092 cFYI(1,("unknown ACL type %d",acl_type)); 2120 cFYI(1,("unknown ACL type %d",acl_type));
2093 return 0; 2121 return 0;
@@ -3203,7 +3231,7 @@ getDFSRetry:
3203 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset); 3231 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3204 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 3232 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3205 cifs_strfromUCS_le(*targetUNCs, 3233 cifs_strfromUCS_le(*targetUNCs,
3206 (wchar_t *) temp, name_len, nls_codepage); 3234 (__le16 *) temp, name_len, nls_codepage);
3207 } else { 3235 } else {
3208 strncpy(*targetUNCs,temp,name_len); 3236 strncpy(*targetUNCs,temp,name_len);
3209 } 3237 }
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2cb620716b..c467de8576 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1986,32 +1986,32 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1986 bytes_returned = 0; /* skill null user */ 1986 bytes_returned = 0; /* skill null user */
1987 else 1987 else
1988 bytes_returned = 1988 bytes_returned =
1989 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, 1989 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
1990 nls_codepage); 1990 nls_codepage);
1991 /* convert number of 16 bit words to bytes */ 1991 /* convert number of 16 bit words to bytes */
1992 bcc_ptr += 2 * bytes_returned; 1992 bcc_ptr += 2 * bytes_returned;
1993 bcc_ptr += 2; /* trailing null */ 1993 bcc_ptr += 2; /* trailing null */
1994 if (domain == NULL) 1994 if (domain == NULL)
1995 bytes_returned = 1995 bytes_returned =
1996 cifs_strtoUCS((wchar_t *) bcc_ptr, 1996 cifs_strtoUCS((__le16 *) bcc_ptr,
1997 "CIFS_LINUX_DOM", 32, nls_codepage); 1997 "CIFS_LINUX_DOM", 32, nls_codepage);
1998 else 1998 else
1999 bytes_returned = 1999 bytes_returned =
2000 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2000 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2001 nls_codepage); 2001 nls_codepage);
2002 bcc_ptr += 2 * bytes_returned; 2002 bcc_ptr += 2 * bytes_returned;
2003 bcc_ptr += 2; 2003 bcc_ptr += 2;
2004 bytes_returned = 2004 bytes_returned =
2005 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2005 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2006 32, nls_codepage); 2006 32, nls_codepage);
2007 bcc_ptr += 2 * bytes_returned; 2007 bcc_ptr += 2 * bytes_returned;
2008 bytes_returned = 2008 bytes_returned =
2009 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 2009 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2010 32, nls_codepage); 2010 32, nls_codepage);
2011 bcc_ptr += 2 * bytes_returned; 2011 bcc_ptr += 2 * bytes_returned;
2012 bcc_ptr += 2; 2012 bcc_ptr += 2;
2013 bytes_returned = 2013 bytes_returned =
2014 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2014 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2015 64, nls_codepage); 2015 64, nls_codepage);
2016 bcc_ptr += 2 * bytes_returned; 2016 bcc_ptr += 2 * bytes_returned;
2017 bcc_ptr += 2; 2017 bcc_ptr += 2;
@@ -2081,7 +2081,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2081 if(ses->serverOS == NULL) 2081 if(ses->serverOS == NULL)
2082 goto sesssetup_nomem; 2082 goto sesssetup_nomem;
2083 cifs_strfromUCS_le(ses->serverOS, 2083 cifs_strfromUCS_le(ses->serverOS,
2084 (wchar_t *)bcc_ptr, len,nls_codepage); 2084 (__le16 *)bcc_ptr, len,nls_codepage);
2085 bcc_ptr += 2 * (len + 1); 2085 bcc_ptr += 2 * (len + 1);
2086 remaining_words -= len + 1; 2086 remaining_words -= len + 1;
2087 ses->serverOS[2 * len] = 0; 2087 ses->serverOS[2 * len] = 0;
@@ -2093,7 +2093,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2093 if(ses->serverNOS == NULL) 2093 if(ses->serverNOS == NULL)
2094 goto sesssetup_nomem; 2094 goto sesssetup_nomem;
2095 cifs_strfromUCS_le(ses->serverNOS, 2095 cifs_strfromUCS_le(ses->serverNOS,
2096 (wchar_t *)bcc_ptr,len,nls_codepage); 2096 (__le16 *)bcc_ptr,len,nls_codepage);
2097 bcc_ptr += 2 * (len + 1); 2097 bcc_ptr += 2 * (len + 1);
2098 ses->serverNOS[2 * len] = 0; 2098 ses->serverNOS[2 * len] = 0;
2099 ses->serverNOS[1 + (2 * len)] = 0; 2099 ses->serverNOS[1 + (2 * len)] = 0;
@@ -2111,7 +2111,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2111 if(ses->serverDomain == NULL) 2111 if(ses->serverDomain == NULL)
2112 goto sesssetup_nomem; 2112 goto sesssetup_nomem;
2113 cifs_strfromUCS_le(ses->serverDomain, 2113 cifs_strfromUCS_le(ses->serverDomain,
2114 (wchar_t *)bcc_ptr,len,nls_codepage); 2114 (__le16 *)bcc_ptr,len,nls_codepage);
2115 bcc_ptr += 2 * (len + 1); 2115 bcc_ptr += 2 * (len + 1);
2116 ses->serverDomain[2*len] = 0; 2116 ses->serverDomain[2*len] = 0;
2117 ses->serverDomain[1+(2*len)] = 0; 2117 ses->serverDomain[1+(2*len)] = 0;
@@ -2255,30 +2255,30 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2255 bcc_ptr++; 2255 bcc_ptr++;
2256 } 2256 }
2257 bytes_returned = 2257 bytes_returned =
2258 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage); 2258 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2259 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */ 2259 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2260 bcc_ptr += 2; /* trailing null */ 2260 bcc_ptr += 2; /* trailing null */
2261 if (domain == NULL) 2261 if (domain == NULL)
2262 bytes_returned = 2262 bytes_returned =
2263 cifs_strtoUCS((wchar_t *) bcc_ptr, 2263 cifs_strtoUCS((__le16 *) bcc_ptr,
2264 "CIFS_LINUX_DOM", 32, nls_codepage); 2264 "CIFS_LINUX_DOM", 32, nls_codepage);
2265 else 2265 else
2266 bytes_returned = 2266 bytes_returned =
2267 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2267 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2268 nls_codepage); 2268 nls_codepage);
2269 bcc_ptr += 2 * bytes_returned; 2269 bcc_ptr += 2 * bytes_returned;
2270 bcc_ptr += 2; 2270 bcc_ptr += 2;
2271 bytes_returned = 2271 bytes_returned =
2272 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2272 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2273 32, nls_codepage); 2273 32, nls_codepage);
2274 bcc_ptr += 2 * bytes_returned; 2274 bcc_ptr += 2 * bytes_returned;
2275 bytes_returned = 2275 bytes_returned =
2276 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2276 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2277 nls_codepage); 2277 nls_codepage);
2278 bcc_ptr += 2 * bytes_returned; 2278 bcc_ptr += 2 * bytes_returned;
2279 bcc_ptr += 2; 2279 bcc_ptr += 2;
2280 bytes_returned = 2280 bytes_returned =
2281 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2281 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2282 64, nls_codepage); 2282 64, nls_codepage);
2283 bcc_ptr += 2 * bytes_returned; 2283 bcc_ptr += 2 * bytes_returned;
2284 bcc_ptr += 2; 2284 bcc_ptr += 2;
@@ -2357,7 +2357,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2357 ses->serverOS = 2357 ses->serverOS =
2358 kzalloc(2 * (len + 1), GFP_KERNEL); 2358 kzalloc(2 * (len + 1), GFP_KERNEL);
2359 cifs_strfromUCS_le(ses->serverOS, 2359 cifs_strfromUCS_le(ses->serverOS,
2360 (wchar_t *) 2360 (__le16 *)
2361 bcc_ptr, len, 2361 bcc_ptr, len,
2362 nls_codepage); 2362 nls_codepage);
2363 bcc_ptr += 2 * (len + 1); 2363 bcc_ptr += 2 * (len + 1);
@@ -2372,7 +2372,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2372 kzalloc(2 * (len + 1), 2372 kzalloc(2 * (len + 1),
2373 GFP_KERNEL); 2373 GFP_KERNEL);
2374 cifs_strfromUCS_le(ses->serverNOS, 2374 cifs_strfromUCS_le(ses->serverNOS,
2375 (wchar_t *)bcc_ptr, 2375 (__le16 *)bcc_ptr,
2376 len, 2376 len,
2377 nls_codepage); 2377 nls_codepage);
2378 bcc_ptr += 2 * (len + 1); 2378 bcc_ptr += 2 * (len + 1);
@@ -2384,9 +2384,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2384 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2384 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2385 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); 2385 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2386 cifs_strfromUCS_le(ses->serverDomain, 2386 cifs_strfromUCS_le(ses->serverDomain,
2387 (wchar_t *)bcc_ptr, 2387 (__le16 *)bcc_ptr,
2388 len, 2388 len, nls_codepage);
2389 nls_codepage);
2390 bcc_ptr += 2*(len+1); 2389 bcc_ptr += 2*(len+1);
2391 ses->serverDomain[2*len] = 0; 2390 ses->serverDomain[2*len] = 0;
2392 ses->serverDomain[1+(2*len)] = 0; 2391 ses->serverDomain[1+(2*len)] = 0;
@@ -2560,16 +2559,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2560 } 2559 }
2561 2560
2562 bytes_returned = 2561 bytes_returned =
2563 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2562 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2564 32, nls_codepage); 2563 32, nls_codepage);
2565 bcc_ptr += 2 * bytes_returned; 2564 bcc_ptr += 2 * bytes_returned;
2566 bytes_returned = 2565 bytes_returned =
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2566 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2568 nls_codepage); 2567 nls_codepage);
2569 bcc_ptr += 2 * bytes_returned; 2568 bcc_ptr += 2 * bytes_returned;
2570 bcc_ptr += 2; /* null terminate Linux version */ 2569 bcc_ptr += 2; /* null terminate Linux version */
2571 bytes_returned = 2570 bytes_returned =
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2571 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2573 64, nls_codepage); 2572 64, nls_codepage);
2574 bcc_ptr += 2 * bytes_returned; 2573 bcc_ptr += 2 * bytes_returned;
2575 *(bcc_ptr + 1) = 0; 2574 *(bcc_ptr + 1) = 0;
@@ -2673,7 +2672,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2673 ses->serverOS = 2672 ses->serverOS =
2674 kzalloc(2 * (len + 1), GFP_KERNEL); 2673 kzalloc(2 * (len + 1), GFP_KERNEL);
2675 cifs_strfromUCS_le(ses->serverOS, 2674 cifs_strfromUCS_le(ses->serverOS,
2676 (wchar_t *) 2675 (__le16 *)
2677 bcc_ptr, len, 2676 bcc_ptr, len,
2678 nls_codepage); 2677 nls_codepage);
2679 bcc_ptr += 2 * (len + 1); 2678 bcc_ptr += 2 * (len + 1);
@@ -2690,7 +2689,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2690 GFP_KERNEL); 2689 GFP_KERNEL);
2691 cifs_strfromUCS_le(ses-> 2690 cifs_strfromUCS_le(ses->
2692 serverNOS, 2691 serverNOS,
2693 (wchar_t *) 2692 (__le16 *)
2694 bcc_ptr, 2693 bcc_ptr,
2695 len, 2694 len,
2696 nls_codepage); 2695 nls_codepage);
@@ -2708,23 +2707,15 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2708 1), 2707 1),
2709 GFP_KERNEL); 2708 GFP_KERNEL);
2710 cifs_strfromUCS_le 2709 cifs_strfromUCS_le
2711 (ses-> 2710 (ses->serverDomain,
2712 serverDomain, 2711 (__le16 *)bcc_ptr,
2713 (wchar_t *) 2712 len, nls_codepage);
2714 bcc_ptr, len,
2715 nls_codepage);
2716 bcc_ptr += 2713 bcc_ptr +=
2717 2 * (len + 1); 2714 2 * (len + 1);
2718 ses-> 2715 ses->serverDomain[2*len]
2719 serverDomain[2
2720 * len]
2721 = 0; 2716 = 0;
2722 ses-> 2717 ses->serverDomain
2723 serverDomain[1 2718 [1 + (2 * len)]
2724 +
2725 (2
2726 *
2727 len)]
2728 = 0; 2719 = 0;
2729 } /* else no more room so create dummy domain string */ 2720 } /* else no more room so create dummy domain string */
2730 else 2721 else
@@ -2903,7 +2894,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2903 SecurityBlob->DomainName.MaximumLength = 0; 2894 SecurityBlob->DomainName.MaximumLength = 0;
2904 } else { 2895 } else {
2905 __u16 len = 2896 __u16 len =
2906 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, 2897 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2907 nls_codepage); 2898 nls_codepage);
2908 len *= 2; 2899 len *= 2;
2909 SecurityBlob->DomainName.MaximumLength = 2900 SecurityBlob->DomainName.MaximumLength =
@@ -2921,7 +2912,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2921 SecurityBlob->UserName.MaximumLength = 0; 2912 SecurityBlob->UserName.MaximumLength = 0;
2922 } else { 2913 } else {
2923 __u16 len = 2914 __u16 len =
2924 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64, 2915 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
2925 nls_codepage); 2916 nls_codepage);
2926 len *= 2; 2917 len *= 2;
2927 SecurityBlob->UserName.MaximumLength = 2918 SecurityBlob->UserName.MaximumLength =
@@ -2934,7 +2925,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2934 cpu_to_le16(len); 2925 cpu_to_le16(len);
2935 } 2926 }
2936 2927
2937 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage); 2928 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
2938 SecurityBlob->WorkstationName.Length *= 2; 2929 SecurityBlob->WorkstationName.Length *= 2;
2939 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length); 2930 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2940 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength); 2931 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
@@ -2947,16 +2938,16 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2947 bcc_ptr++; 2938 bcc_ptr++;
2948 } 2939 }
2949 bytes_returned = 2940 bytes_returned =
2950 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 2941 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2951 32, nls_codepage); 2942 32, nls_codepage);
2952 bcc_ptr += 2 * bytes_returned; 2943 bcc_ptr += 2 * bytes_returned;
2953 bytes_returned = 2944 bytes_returned =
2954 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32, 2945 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2955 nls_codepage); 2946 nls_codepage);
2956 bcc_ptr += 2 * bytes_returned; 2947 bcc_ptr += 2 * bytes_returned;
2957 bcc_ptr += 2; /* null term version string */ 2948 bcc_ptr += 2; /* null term version string */
2958 bytes_returned = 2949 bytes_returned =
2959 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS, 2950 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2960 64, nls_codepage); 2951 64, nls_codepage);
2961 bcc_ptr += 2 * bytes_returned; 2952 bcc_ptr += 2 * bytes_returned;
2962 *(bcc_ptr + 1) = 0; 2953 *(bcc_ptr + 1) = 0;
@@ -3069,7 +3060,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3069 ses->serverOS = 3060 ses->serverOS =
3070 kzalloc(2 * (len + 1), GFP_KERNEL); 3061 kzalloc(2 * (len + 1), GFP_KERNEL);
3071 cifs_strfromUCS_le(ses->serverOS, 3062 cifs_strfromUCS_le(ses->serverOS,
3072 (wchar_t *) 3063 (__le16 *)
3073 bcc_ptr, len, 3064 bcc_ptr, len,
3074 nls_codepage); 3065 nls_codepage);
3075 bcc_ptr += 2 * (len + 1); 3066 bcc_ptr += 2 * (len + 1);
@@ -3086,7 +3077,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3086 GFP_KERNEL); 3077 GFP_KERNEL);
3087 cifs_strfromUCS_le(ses-> 3078 cifs_strfromUCS_le(ses->
3088 serverNOS, 3079 serverNOS,
3089 (wchar_t *) 3080 (__le16 *)
3090 bcc_ptr, 3081 bcc_ptr,
3091 len, 3082 len,
3092 nls_codepage); 3083 nls_codepage);
@@ -3105,7 +3096,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3105 cifs_strfromUCS_le 3096 cifs_strfromUCS_le
3106 (ses-> 3097 (ses->
3107 serverDomain, 3098 serverDomain,
3108 (wchar_t *) 3099 (__le16 *)
3109 bcc_ptr, len, 3100 bcc_ptr, len,
3110 nls_codepage); 3101 nls_codepage);
3111 bcc_ptr += 3102 bcc_ptr +=
@@ -3227,7 +3218,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3227 if (ses->capabilities & CAP_UNICODE) { 3218 if (ses->capabilities & CAP_UNICODE) {
3228 smb_buffer->Flags2 |= SMBFLG2_UNICODE; 3219 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3229 length = 3220 length =
3230 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage); 3221 cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
3231 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ 3222 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3232 bcc_ptr += 2; /* skip trailing null */ 3223 bcc_ptr += 2; /* skip trailing null */
3233 } else { /* ASCII */ 3224 } else { /* ASCII */
@@ -3263,7 +3254,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3263 tcon->nativeFileSystem = 3254 tcon->nativeFileSystem =
3264 kzalloc(length + 2, GFP_KERNEL); 3255 kzalloc(length + 2, GFP_KERNEL);
3265 cifs_strfromUCS_le(tcon->nativeFileSystem, 3256 cifs_strfromUCS_le(tcon->nativeFileSystem,
3266 (wchar_t *) bcc_ptr, 3257 (__le16 *) bcc_ptr,
3267 length, nls_codepage); 3258 length, nls_codepage);
3268 bcc_ptr += 2 * length; 3259 bcc_ptr += 2 * length;
3269 bcc_ptr[0] = 0; /* null terminate the string */ 3260 bcc_ptr[0] = 0; /* null terminate the string */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 8dfe717a33..32cc96cafa 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -228,8 +228,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
228 else { 228 else {
229 rc = cifs_get_inode_info(&newinode, full_path, 229 rc = cifs_get_inode_info(&newinode, full_path,
230 buf, inode->i_sb,xid); 230 buf, inode->i_sb,xid);
231 if(newinode) 231 if(newinode) {
232 newinode->i_mode = mode; 232 newinode->i_mode = mode;
233 if((oplock & CIFS_CREATE_ACTION) &&
234 (cifs_sb->mnt_cifs_flags &
235 CIFS_MOUNT_SET_UID)) {
236 newinode->i_uid = current->fsuid;
237 newinode->i_gid = current->fsgid;
238 }
239 }
233 } 240 }
234 241
235 if (rc != 0) { 242 if (rc != 0) {
@@ -292,7 +299,8 @@ cifs_create_out:
292 return rc; 299 return rc;
293} 300}
294 301
295int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) 302int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
303 dev_t device_number)
296{ 304{
297 int rc = -EPERM; 305 int rc = -EPERM;
298 int xid; 306 int xid;
@@ -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 da4f5e10b3..14a1c72ced 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -489,8 +489,10 @@ int cifs_close(struct inode *inode, struct file *file)
489 the struct would be in each open file, 489 the struct would be in each open file,
490 but this should give enough time to 490 but this should give enough time to
491 clear the socket */ 491 clear the socket */
492 write_unlock(&file->f_owner.lock);
492 cERROR(1,("close with pending writes")); 493 cERROR(1,("close with pending writes"));
493 msleep(timeout); 494 msleep(timeout);
495 write_lock(&file->f_owner.lock);
494 timeout *= 4; 496 timeout *= 4;
495 } 497 }
496 write_unlock(&file->f_owner.lock); 498 write_unlock(&file->f_owner.lock);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 923d071163..411c1f7f84 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,111 @@ int cifs_get_inode_info_unix(struct inode **pinode,
190 return rc; 202 return rc;
191} 203}
192 204
205static int decode_sfu_inode(struct inode * inode, __u64 size,
206 const unsigned char *path,
207 struct cifs_sb_info *cifs_sb, int xid)
208{
209 int rc;
210 int oplock = FALSE;
211 __u16 netfid;
212 struct cifsTconInfo *pTcon = cifs_sb->tcon;
213 char buf[24];
214 unsigned int bytes_read;
215 char * pbuf;
216
217 pbuf = buf;
218
219 if(size == 0) {
220 inode->i_mode |= S_IFIFO;
221 return 0;
222 } else if (size < 8) {
223 return -EINVAL; /* EOPNOTSUPP? */
224 }
225
226 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
227 CREATE_NOT_DIR, &netfid, &oplock, NULL,
228 cifs_sb->local_nls,
229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) {
232 /* Read header */
233 rc = CIFSSMBRead(xid, pTcon,
234 netfid,
235 24 /* length */, 0 /* offset */,
236 &bytes_read, &pbuf);
237 if((rc == 0) && (bytes_read >= 8)) {
238 if(memcmp("IntxBLK", pbuf, 8) == 0) {
239 cFYI(1,("Block device"));
240 inode->i_mode |= S_IFBLK;
241 if(bytes_read == 24) {
242 /* we have enough to decode dev num */
243 __u64 mjr; /* major */
244 __u64 mnr; /* minor */
245 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
246 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
247 inode->i_rdev = MKDEV(mjr, mnr);
248 }
249 } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
250 cFYI(1,("Char device"));
251 inode->i_mode |= S_IFCHR;
252 if(bytes_read == 24) {
253 /* we have enough to decode dev num */
254 __u64 mjr; /* major */
255 __u64 mnr; /* minor */
256 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
257 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
258 inode->i_rdev = MKDEV(mjr, mnr);
259 }
260 } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
261 cFYI(1,("Symlink"));
262 inode->i_mode |= S_IFLNK;
263 } else {
264 inode->i_mode |= S_IFREG; /* file? */
265 rc = -EOPNOTSUPP;
266 }
267 } else {
268 inode->i_mode |= S_IFREG; /* then it is a file */
269 rc = -EOPNOTSUPP; /* or some unknown SFU type */
270 }
271 CIFSSMBClose(xid, pTcon, netfid);
272 }
273 return rc;
274
275}
276
277#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
278
279static int get_sfu_uid_mode(struct inode * inode,
280 const unsigned char *path,
281 struct cifs_sb_info *cifs_sb, int xid)
282{
283#ifdef CONFIG_CIFS_XATTR
284 ssize_t rc;
285 char ea_value[4];
286 __u32 mode;
287
288 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
289 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
290 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
291 if(rc < 0)
292 return (int)rc;
293 else if (rc > 3) {
294 mode = le32_to_cpu(*((__le32 *)ea_value));
295 inode->i_mode &= ~SFBITS_MASK;
296 cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
297 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
298 cFYI(1,("special mode bits 0%o", mode));
299 return 0;
300 } else {
301 return 0;
302 }
303#else
304 return -EOPNOTSUPP;
305#endif
306
307
308}
309
193int cifs_get_inode_info(struct inode **pinode, 310int cifs_get_inode_info(struct inode **pinode,
194 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 311 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
195 struct super_block *sb, int xid) 312 struct super_block *sb, int xid)
@@ -202,7 +319,7 @@ int cifs_get_inode_info(struct inode **pinode,
202 char *buf = NULL; 319 char *buf = NULL;
203 320
204 pTcon = cifs_sb->tcon; 321 pTcon = cifs_sb->tcon;
205 cFYI(1,("Getting info on %s ", search_path)); 322 cFYI(1,("Getting info on %s", search_path));
206 323
207 if ((pfindData == NULL) && (*pinode != NULL)) { 324 if ((pfindData == NULL) && (*pinode != NULL)) {
208 if (CIFS_I(*pinode)->clientCanCacheRead) { 325 if (CIFS_I(*pinode)->clientCanCacheRead) {
@@ -303,9 +420,9 @@ int cifs_get_inode_info(struct inode **pinode,
303 inode = *pinode; 420 inode = *pinode;
304 cifsInfo = CIFS_I(inode); 421 cifsInfo = CIFS_I(inode);
305 cifsInfo->cifsAttrs = attr; 422 cifsInfo->cifsAttrs = attr;
306 cFYI(1, (" Old time %ld ", cifsInfo->time)); 423 cFYI(1, ("Old time %ld ", cifsInfo->time));
307 cifsInfo->time = jiffies; 424 cifsInfo->time = jiffies;
308 cFYI(1, (" New time %ld ", cifsInfo->time)); 425 cFYI(1, ("New time %ld ", cifsInfo->time));
309 426
310 /* blksize needs to be multiple of two. So safer to default to 427 /* blksize needs to be multiple of two. So safer to default to
311 blksize and blkbits set in superblock so 2**blkbits and blksize 428 blksize and blkbits set in superblock so 2**blkbits and blksize
@@ -319,13 +436,15 @@ int cifs_get_inode_info(struct inode **pinode,
319 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 436 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
320 inode->i_ctime = 437 inode->i_ctime =
321 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 438 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
322 cFYI(0, (" Attributes came in as 0x%x ", attr)); 439 cFYI(0, ("Attributes came in as 0x%x ", attr));
323 440
324 /* set default mode. will override for dirs below */ 441 /* set default mode. will override for dirs below */
325 if (atomic_read(&cifsInfo->inUse) == 0) 442 if (atomic_read(&cifsInfo->inUse) == 0)
326 /* new inode, can safely set these fields */ 443 /* new inode, can safely set these fields */
327 inode->i_mode = cifs_sb->mnt_file_mode; 444 inode->i_mode = cifs_sb->mnt_file_mode;
328 445 else /* since we set the inode type below we need to mask off
446 to avoid strange results if type changes and both get orred in */
447 inode->i_mode &= ~S_IFMT;
329/* if (attr & ATTR_REPARSE) */ 448/* if (attr & ATTR_REPARSE) */
330 /* We no longer handle these as symlinks because we could not 449 /* We no longer handle these as symlinks because we could not
331 follow them due to the absolute path with drive letter */ 450 follow them due to the absolute path with drive letter */
@@ -340,10 +459,16 @@ int cifs_get_inode_info(struct inode **pinode,
340 (pfindData->EndOfFile == 0)) { 459 (pfindData->EndOfFile == 0)) {
341 inode->i_mode = cifs_sb->mnt_file_mode; 460 inode->i_mode = cifs_sb->mnt_file_mode;
342 inode->i_mode |= S_IFIFO; 461 inode->i_mode |= S_IFIFO;
343/* BB Finish for SFU style symlinks and devies */ 462/* BB Finish for SFU style symlinks and devices */
344/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 463 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
345 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ 464 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
346 465 if (decode_sfu_inode(inode,
466 le64_to_cpu(pfindData->EndOfFile),
467 search_path,
468 cifs_sb, xid)) {
469 cFYI(1,("Unrecognized sfu inode type"));
470 }
471 cFYI(1,("sfu mode 0%o",inode->i_mode));
347 } else { 472 } else {
348 inode->i_mode |= S_IFREG; 473 inode->i_mode |= S_IFREG;
349 /* treat the dos attribute of read-only as read-only 474 /* treat the dos attribute of read-only as read-only
@@ -368,7 +493,10 @@ int cifs_get_inode_info(struct inode **pinode,
368 493
369 /* BB fill in uid and gid here? with help from winbind? 494 /* BB fill in uid and gid here? with help from winbind?
370 or retrieve from NTFS stream extended attribute */ 495 or retrieve from NTFS stream extended attribute */
371 if (atomic_read(&cifsInfo->inUse) == 0) { 496 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
497 /* fill in uid, gid, mode from server ACL */
498 get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
499 } else if (atomic_read(&cifsInfo->inUse) == 0) {
372 inode->i_uid = cifs_sb->mnt_uid; 500 inode->i_uid = cifs_sb->mnt_uid;
373 inode->i_gid = cifs_sb->mnt_gid; 501 inode->i_gid = cifs_sb->mnt_gid;
374 /* set so we do not keep refreshing these fields with 502 /* set so we do not keep refreshing these fields with
@@ -377,24 +505,29 @@ int cifs_get_inode_info(struct inode **pinode,
377 } 505 }
378 506
379 if (S_ISREG(inode->i_mode)) { 507 if (S_ISREG(inode->i_mode)) {
380 cFYI(1, (" File inode ")); 508 cFYI(1, ("File inode"));
381 inode->i_op = &cifs_file_inode_ops; 509 inode->i_op = &cifs_file_inode_ops;
382 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 510 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
383 inode->i_fop = &cifs_file_direct_ops; 511 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
384 else 512 inode->i_fop =
513 &cifs_file_direct_nobrl_ops;
514 else
515 inode->i_fop = &cifs_file_direct_ops;
516 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
517 inode->i_fop = &cifs_file_nobrl_ops;
518 else /* not direct, send byte range locks */
385 inode->i_fop = &cifs_file_ops; 519 inode->i_fop = &cifs_file_ops;
386 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 520
387 inode->i_fop->lock = NULL;
388 inode->i_data.a_ops = &cifs_addr_ops; 521 inode->i_data.a_ops = &cifs_addr_ops;
389 if(pTcon->ses->server->maxBuf < 522 if(pTcon->ses->server->maxBuf <
390 4096 + MAX_CIFS_HDR_SIZE) 523 4096 + MAX_CIFS_HDR_SIZE)
391 inode->i_data.a_ops->readpages = NULL; 524 inode->i_data.a_ops->readpages = NULL;
392 } else if (S_ISDIR(inode->i_mode)) { 525 } else if (S_ISDIR(inode->i_mode)) {
393 cFYI(1, (" Directory inode ")); 526 cFYI(1, ("Directory inode"));
394 inode->i_op = &cifs_dir_inode_ops; 527 inode->i_op = &cifs_dir_inode_ops;
395 inode->i_fop = &cifs_dir_ops; 528 inode->i_fop = &cifs_dir_ops;
396 } else if (S_ISLNK(inode->i_mode)) { 529 } else if (S_ISLNK(inode->i_mode)) {
397 cFYI(1, (" Symbolic Link inode ")); 530 cFYI(1, ("Symbolic Link inode"));
398 inode->i_op = &cifs_symlink_inode_ops; 531 inode->i_op = &cifs_symlink_inode_ops;
399 } else { 532 } else {
400 init_special_inode(inode, inode->i_mode, 533 init_special_inode(inode, inode->i_mode,
@@ -431,7 +564,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
431 struct cifsInodeInfo *cifsInode; 564 struct cifsInodeInfo *cifsInode;
432 FILE_BASIC_INFO *pinfo_buf; 565 FILE_BASIC_INFO *pinfo_buf;
433 566
434 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); 567 cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
435 568
436 xid = GetXid(); 569 xid = GetXid();
437 570
@@ -577,7 +710,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 char *full_path = NULL; 710 char *full_path = NULL;
578 struct inode *newinode = NULL; 711 struct inode *newinode = NULL;
579 712
580 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); 713 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
581 714
582 xid = GetXid(); 715 xid = GetXid();
583 716
@@ -635,6 +768,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
635 /* BB to be implemented via Windows secrty descriptors 768 /* BB to be implemented via Windows secrty descriptors
636 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 769 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
637 -1, -1, local_nls); */ 770 -1, -1, local_nls); */
771 if(direntry->d_inode) {
772 direntry->d_inode->i_mode = mode;
773 direntry->d_inode->i_mode |= S_IFDIR;
774 if(cifs_sb->mnt_cifs_flags &
775 CIFS_MOUNT_SET_UID) {
776 direntry->d_inode->i_uid =
777 current->fsuid;
778 direntry->d_inode->i_gid =
779 current->fsgid;
780 }
781 }
638 } 782 }
639 } 783 }
640 kfree(full_path); 784 kfree(full_path);
@@ -651,7 +795,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
651 char *full_path = NULL; 795 char *full_path = NULL;
652 struct cifsInodeInfo *cifsInode; 796 struct cifsInodeInfo *cifsInode;
653 797
654 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); 798 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
655 799
656 xid = GetXid(); 800 xid = GetXid();
657 801
@@ -906,14 +1050,20 @@ int cifs_revalidate(struct dentry *direntry)
906 filemap_fdatawrite(direntry->d_inode->i_mapping); 1050 filemap_fdatawrite(direntry->d_inode->i_mapping);
907 } 1051 }
908 if (invalidate_inode) { 1052 if (invalidate_inode) {
909 if (direntry->d_inode->i_mapping) 1053 /* shrink_dcache not necessary now that cifs dentry ops
910 filemap_fdatawait(direntry->d_inode->i_mapping); 1054 are exported for negative dentries */
911 /* may eventually have to do this for open files too */ 1055/* if(S_ISDIR(direntry->d_inode->i_mode))
912 if (list_empty(&(cifsInode->openFileList))) { 1056 shrink_dcache_parent(direntry); */
913 /* Has changed on server - flush read ahead pages */ 1057 if (S_ISREG(direntry->d_inode->i_mode)) {
914 cFYI(1, ("Invalidating read ahead data on " 1058 if (direntry->d_inode->i_mapping)
915 "closed file")); 1059 filemap_fdatawait(direntry->d_inode->i_mapping);
916 invalidate_remote_inode(direntry->d_inode); 1060 /* may eventually have to do this for open files too */
1061 if (list_empty(&(cifsInode->openFileList))) {
1062 /* changed on server - flush read ahead pages */
1063 cFYI(1, ("Invalidating read ahead data on "
1064 "closed file"));
1065 invalidate_remote_inode(direntry->d_inode);
1066 }
917 } 1067 }
918 } 1068 }
919/* up(&direntry->d_inode->i_sem); */ 1069/* up(&direntry->d_inode->i_sem); */
@@ -970,11 +1120,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
970 1120
971 xid = GetXid(); 1121 xid = GetXid();
972 1122
973 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1123 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
974 direntry->d_name.name, attrs->ia_valid)); 1124 direntry->d_name.name, attrs->ia_valid));
1125
975 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1126 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
976 pTcon = cifs_sb->tcon; 1127 pTcon = cifs_sb->tcon;
977 1128
1129 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1130 /* check if we have permission to change attrs */
1131 rc = inode_change_ok(direntry->d_inode, attrs);
1132 if(rc < 0) {
1133 FreeXid(xid);
1134 return rc;
1135 } else
1136 rc = 0;
1137 }
1138
978 down(&direntry->d_sb->s_vfs_rename_sem); 1139 down(&direntry->d_sb->s_vfs_rename_sem);
979 full_path = build_path_from_dentry(direntry); 1140 full_path = build_path_from_dentry(direntry);
980 up(&direntry->d_sb->s_vfs_rename_sem); 1141 up(&direntry->d_sb->s_vfs_rename_sem);
@@ -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 34a06692e4..94baf6c8ec 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -397,12 +397,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
397 if(smb->Command == SMB_COM_LOCKING_ANDX) 397 if(smb->Command == SMB_COM_LOCKING_ANDX)
398 return 0; 398 return 0;
399 else 399 else
400 cERROR(1, ("Rcvd Request not response ")); 400 cERROR(1, ("Rcvd Request not response"));
401 } 401 }
402 } else { /* bad signature or mid */ 402 } else { /* bad signature or mid */
403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) 403 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
404 cERROR(1, 404 cERROR(1,
405 ("Bad protocol string signature header %x ", 405 ("Bad protocol string signature header %x",
406 *(unsigned int *) smb->Protocol)); 406 *(unsigned int *) smb->Protocol));
407 if (mid != smb->Mid) 407 if (mid != smb->Mid)
408 cERROR(1, ("Mids do not match")); 408 cERROR(1, ("Mids do not match"));
@@ -417,7 +417,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
417 __u32 len = smb->smb_buf_length; 417 __u32 len = smb->smb_buf_length;
418 __u32 clc_len; /* calculated length */ 418 __u32 clc_len; /* calculated length */
419 cFYI(0, 419 cFYI(0,
420 ("Entering checkSMB with Length: %x, smb_buf_length: %x ", 420 ("Entering checkSMB with Length: %x, smb_buf_length: %x",
421 length, len)); 421 length, len));
422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || 422 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { 423 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
@@ -451,9 +451,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); 451 cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
452 /* Windows XP can return a few bytes too much, presumably 452 /* Windows XP can return a few bytes too much, presumably
453 an illegal pad, at the end of byte range lock responses 453 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 454 so we allow for that three byte pad, as long as actual
455 received length is as long or longer than calculated length */ 455 received length is as long or longer than calculated length */
456 if((4+len > clc_len) && (len <= clc_len + 3)) 456 /* We have now had to extend this more, since there is a
457 case in which it needs to be bigger still to handle a
458 malformed response to transact2 findfirst from WinXP when
459 access denied is returned and thus bcc and wct are zero
460 but server says length is 0x21 bytes too long as if the server
461 forget to reset the smb rfc1001 length when it reset the
462 wct and bcc to minimum size and drop the t2 parms and data */
463 if((4+len > clc_len) && (len <= clc_len + 512))
457 return 0; 464 return 0;
458 else 465 else
459 return 1; 466 return 1;
@@ -678,7 +685,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
678 __u16 temp; 685 __u16 temp;
679 686
680 if(!mapChars) 687 if(!mapChars)
681 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); 688 return cifs_strtoUCS(target, source, PATH_MAX, cp);
682 689
683 for(i = 0, j = 0; i < maxlen; j++) { 690 for(i = 0, j = 0; i < maxlen; j++) {
684 src_char = source[i]; 691 src_char = source[i];
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index f781468984..5de74d216f 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 a86bd1c076..9bdaaecae3 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,8 +204,14 @@ 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 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
@@ -258,6 +275,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
258 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); 275 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
259 276
260 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); 277 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
278 /* since we set the inode type below we need to mask off type
279 to avoid strange results if bits above were corrupt */
280 tmp_inode->i_mode &= ~S_IFMT;
261 if (type == UNIX_FILE) { 281 if (type == UNIX_FILE) {
262 *pobject_type = DT_REG; 282 *pobject_type = DT_REG;
263 tmp_inode->i_mode |= S_IFREG; 283 tmp_inode->i_mode |= S_IFREG;
@@ -283,6 +303,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
283 } else if (type == UNIX_SOCKET) { 303 } else if (type == UNIX_SOCKET) {
284 *pobject_type = DT_SOCK; 304 *pobject_type = DT_SOCK;
285 tmp_inode->i_mode |= S_IFSOCK; 305 tmp_inode->i_mode |= S_IFSOCK;
306 } else {
307 /* safest to just call it a file */
308 *pobject_type = DT_REG;
309 tmp_inode->i_mode |= S_IFREG;
310 cFYI(1,("unknown inode type %d",type));
286 } 311 }
287 312
288 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); 313 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
@@ -699,7 +724,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
699 (__le16 *)filename, len/2, nlt); 724 (__le16 *)filename, len/2, nlt);
700 else 725 else
701 pqst->len = cifs_strfromUCS_le((char *)pqst->name, 726 pqst->len = cifs_strfromUCS_le((char *)pqst->name,
702 (wchar_t *)filename,len/2,nlt); 727 (__le16 *)filename,len/2,nlt);
703 } else { 728 } else {
704 pqst->name = filename; 729 pqst->name = filename;
705 pqst->len = len; 730 pqst->len = len;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 981ea0d8b9..f887119609 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -515,6 +515,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
515 *pbytes_returned = in_buf->smb_buf_length; 515 *pbytes_returned = in_buf->smb_buf_length;
516 516
517 /* BB special case reconnect tid and uid here? */ 517 /* BB special case reconnect tid and uid here? */
518 /* BB special case Errbadpassword and pwdexpired here */
518 rc = map_smb_to_linux_error(in_buf); 519 rc = map_smb_to_linux_error(in_buf);
519 520
520 /* convert ByteCount if necessary */ 521 /* convert ByteCount if necessary */
@@ -522,7 +523,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
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 * in_buf->WordCount) + 2 /* bcc */ )
525 BCC(in_buf) = le16_to_cpu(BCC(in_buf)); 526 BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf));
526 } else { 527 } else {
527 rc = -EIO; 528 rc = -EIO;
528 cFYI(1,("Bad MID state?")); 529 cFYI(1,("Bad MID state?"));
@@ -786,7 +787,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
786 sizeof (struct smb_hdr) - 787 sizeof (struct smb_hdr) -
787 4 /* do not count RFC1001 header */ + 788 4 /* do not count RFC1001 header */ +
788 (2 * out_buf->WordCount) + 2 /* bcc */ ) 789 (2 * out_buf->WordCount) + 2 /* bcc */ )
789 BCC(out_buf) = le16_to_cpu(BCC(out_buf)); 790 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
790 } else { 791 } else {
791 rc = -EIO; 792 rc = -EIO;
792 cERROR(1,("Bad MID state? ")); 793 cERROR(1,("Bad MID state? "));