aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 13:02:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 13:02:46 -0400
commitddbb868493abdb71d6c0e3ff93f735923842de38 (patch)
treed91aed7c58c276dd8f11c9e439027cbe0d948edb
parent3296ca27f50ecbd71db1d808c7a72d311027f919 (diff)
parent61b6bc525a34931bb73e4c95bfe009cd9572a288 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: remove never-used in6_addr option cifs: add addr= mount option alias for ip= [CIFS] Add mention of new mount parm (forceuid) to cifs readme cifs: make overriding of ownership conditional on new mount options cifs: fix IPv6 address length check cifs: clean up set_cifs_acl interfaces cifs: reorganize get_cifs_acl [CIFS] Update readme to indicate change to default mount (serverino) cifs: make serverino the default when mounting cifs: rename cifs_iget to cifs_root_iget cifs: make cnvrtDosUnixTm take a little-endian args and an offset cifs: have cifs_NTtimeToUnix take a little-endian arg cifs: tighten up default file_mode/dir_mode cifs: fix artificial limit on reading symlinks
-rw-r--r--fs/cifs/CHANGES11
-rw-r--r--fs/cifs/README16
-rw-r--r--fs/cifs/cifs_spnego.c6
-rw-r--r--fs/cifs/cifsacl.c178
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsproto.h10
-rw-r--r--fs/cifs/cifssmb.c7
-rw-r--r--fs/cifs/connect.c34
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c19
-rw-r--r--fs/cifs/netmisc.c24
-rw-r--r--fs/cifs/readdir.c44
13 files changed, 180 insertions, 177 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index f20c4069c220..b48689839428 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,12 @@
1Version 1.59
2------------
3Client uses server inode numbers (which are persistent) rather than
4client generated ones by default (mount option "serverino" turned
5on by default if server supports it). Add forceuid and forcegid
6mount options (so that when negotiating unix extensions specifying
7which uid mounted does not immediately force the server's reported
8uids to be overridden).
9
1Version 1.58 10Version 1.58
2------------ 11------------
3Guard against buffer overruns in various UCS-2 to UTF-8 string conversions 12Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
@@ -10,6 +19,8 @@ we converted from). Fix endianness of the vcnum field used during
10session setup to distinguish multiple mounts to same server from different 19session setup to distinguish multiple mounts to same server from different
11userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental 20userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
12flag to be set to 2, and mount must enable krb5 to turn on extended security). 21flag to be set to 2, and mount must enable krb5 to turn on extended security).
22Performance of file create to Samba improved (posix create on lookup
23removes 1 of 2 network requests sent on file create)
13 24
14Version 1.57 25Version 1.57
15------------ 26------------
diff --git a/fs/cifs/README b/fs/cifs/README
index db208ddb9899..ad92921dbde4 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -262,7 +262,8 @@ A partial list of the supported mount options follows:
262 mount. 262 mount.
263 domain Set the SMB/CIFS workgroup name prepended to the 263 domain Set the SMB/CIFS workgroup name prepended to the
264 username during CIFS session establishment 264 username during CIFS session establishment
265 uid Set the default uid for inodes. For mounts to servers 265 forceuid Set the default uid for inodes based on the uid
266 passed in. For mounts to servers
266 which do support the CIFS Unix extensions, such as a 267 which do support the CIFS Unix extensions, such as a
267 properly configured Samba server, the server provides 268 properly configured Samba server, the server provides
268 the uid, gid and mode so this parameter should not be 269 the uid, gid and mode so this parameter should not be
@@ -292,6 +293,12 @@ A partial list of the supported mount options follows:
292 the client. Note that the mount.cifs helper must be 293 the client. Note that the mount.cifs helper must be
293 at version 1.10 or higher to support specifying the uid 294 at version 1.10 or higher to support specifying the uid
294 (or gid) in non-numeric form. 295 (or gid) in non-numeric form.
296 forcegid (similar to above but for the groupid instead of uid)
297 uid Set the default uid for inodes, and indicate to the
298 cifs kernel driver which local user mounted . If the server
299 supports the unix extensions the default uid is
300 not used to fill in the owner fields of inodes (files)
301 unless the "forceuid" parameter is specified.
295 gid Set the default gid for inodes (similar to above). 302 gid Set the default gid for inodes (similar to above).
296 file_mode If CIFS Unix extensions are not supported by the server 303 file_mode If CIFS Unix extensions are not supported by the server
297 this overrides the default mode for file inodes. 304 this overrides the default mode for file inodes.
@@ -388,8 +395,13 @@ A partial list of the supported mount options follows:
388 or the CIFS Unix Extensions equivalent and for those 395 or the CIFS Unix Extensions equivalent and for those
389 this mount option will have no effect. Exporting cifs mounts 396 this mount option will have no effect. Exporting cifs mounts
390 under nfsd requires this mount option on the cifs mount. 397 under nfsd requires this mount option on the cifs mount.
398 This is now the default if server supports the
399 required network operation.
391 noserverino Client generates inode numbers (rather than using the actual one 400 noserverino Client generates inode numbers (rather than using the actual one
392 from the server) by default. 401 from the server). These inode numbers will vary after
402 unmount or reboot which can confuse some applications,
403 but not all server filesystems support unique inode
404 numbers.
393 setuids If the CIFS Unix extensions are negotiated with the server 405 setuids If the CIFS Unix extensions are negotiated with the server
394 the client will attempt to set the effective uid and gid of 406 the client will attempt to set the effective uid and gid of
395 the local process on newly created files, directories, and 407 the local process on newly created files, directories, and
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 67bf93a40d2e..4a4581cb2b5e 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -23,6 +23,7 @@
23#include <linux/string.h> 23#include <linux/string.h>
24#include <keys/user-type.h> 24#include <keys/user-type.h>
25#include <linux/key-type.h> 25#include <linux/key-type.h>
26#include <linux/inet.h>
26#include "cifsglob.h" 27#include "cifsglob.h"
27#include "cifs_spnego.h" 28#include "cifs_spnego.h"
28#include "cifs_debug.h" 29#include "cifs_debug.h"
@@ -73,9 +74,6 @@ struct key_type cifs_spnego_key_type = {
73 * strlen(";sec=ntlmsspi") */ 74 * strlen(";sec=ntlmsspi") */
74#define MAX_MECH_STR_LEN 13 75#define MAX_MECH_STR_LEN 13
75 76
76/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
77#define MAX_IPV6_ADDR_LEN 43
78
79/* strlen of "host=" */ 77/* strlen of "host=" */
80#define HOST_KEY_LEN 5 78#define HOST_KEY_LEN 5
81 79
@@ -102,7 +100,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
102 host=hostname sec=mechanism uid=0xFF user=username */ 100 host=hostname sec=mechanism uid=0xFF user=username */
103 desc_len = MAX_VER_STR_LEN + 101 desc_len = MAX_VER_STR_LEN +
104 HOST_KEY_LEN + strlen(hostname) + 102 HOST_KEY_LEN + strlen(hostname) +
105 IP_KEY_LEN + MAX_IPV6_ADDR_LEN + 103 IP_KEY_LEN + INET6_ADDRSTRLEN +
106 MAX_MECH_STR_LEN + 104 MAX_MECH_STR_LEN +
107 UID_KEY_LEN + (sizeof(uid_t) * 2) + 105 UID_KEY_LEN + (sizeof(uid_t) * 2) +
108 USER_KEY_LEN + strlen(sesInfo->userName) + 1; 106 USER_KEY_LEN + strlen(sesInfo->userName) + 1;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 57ecdc83c26f..1403b5d86a73 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
552 return rc; 552 return rc;
553} 553}
554 554
555 555static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
556/* Retrieve an ACL from the server */ 556 __u16 fid, u32 *pacllen)
557static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
558 const char *path, const __u16 *pfid)
559{ 557{
560 struct cifsFileInfo *open_file = NULL;
561 bool unlock_file = false;
562 int xid;
563 int rc = -EIO;
564 __u16 fid;
565 struct super_block *sb;
566 struct cifs_sb_info *cifs_sb;
567 struct cifs_ntsd *pntsd = NULL; 558 struct cifs_ntsd *pntsd = NULL;
559 int xid, rc;
560
561 xid = GetXid();
562 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
563 FreeXid(xid);
568 564
569 cFYI(1, ("get mode from ACL for %s", path));
570 565
571 if (inode == NULL) 566 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
572 return NULL; 567 return pntsd;
568}
569
570static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
571 const char *path, u32 *pacllen)
572{
573 struct cifs_ntsd *pntsd = NULL;
574 int oplock = 0;
575 int xid, rc;
576 __u16 fid;
573 577
574 xid = GetXid(); 578 xid = GetXid();
575 if (pfid == NULL)
576 open_file = find_readable_file(CIFS_I(inode));
577 else
578 fid = *pfid;
579 579
580 sb = inode->i_sb; 580 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
581 if (sb == NULL) { 581 &fid, &oplock, NULL, cifs_sb->local_nls,
582 FreeXid(xid); 582 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
583 return NULL; 583 if (rc) {
584 } 584 cERROR(1, ("Unable to open file to get ACL"));
585 cifs_sb = CIFS_SB(sb); 585 goto out;
586
587 if (open_file) {
588 unlock_file = true;
589 fid = open_file->netfid;
590 } else if (pfid == NULL) {
591 int oplock = 0;
592 /* open file */
593 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
594 READ_CONTROL, 0, &fid, &oplock, NULL,
595 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
596 CIFS_MOUNT_MAP_SPECIAL_CHR);
597 if (rc != 0) {
598 cERROR(1, ("Unable to open file to get ACL"));
599 FreeXid(xid);
600 return NULL;
601 }
602 } 586 }
603 587
604 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 588 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
605 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); 589 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
606 if (unlock_file == true) /* find_readable_file increments ref count */
607 atomic_dec(&open_file->wrtPending);
608 else if (pfid == NULL) /* if opened above we have to close the handle */
609 CIFSSMBClose(xid, cifs_sb->tcon, fid);
610 /* else handle was passed in by caller */
611 590
591 CIFSSMBClose(xid, cifs_sb->tcon, fid);
592 out:
612 FreeXid(xid); 593 FreeXid(xid);
613 return pntsd; 594 return pntsd;
614} 595}
615 596
616/* Set an ACL on the server */ 597/* Retrieve an ACL from the server */
617static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, 598static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
618 struct inode *inode, const char *path) 599 struct inode *inode, const char *path,
600 u32 *pacllen)
619{ 601{
620 struct cifsFileInfo *open_file; 602 struct cifs_ntsd *pntsd = NULL;
621 bool unlock_file = false; 603 struct cifsFileInfo *open_file = NULL;
622 int xid;
623 int rc = -EIO;
624 __u16 fid;
625 struct super_block *sb;
626 struct cifs_sb_info *cifs_sb;
627 604
628 cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); 605 if (inode)
606 open_file = find_readable_file(CIFS_I(inode));
607 if (!open_file)
608 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
629 609
630 if (!inode) 610 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
631 return rc; 611 atomic_dec(&open_file->wrtPending);
612 return pntsd;
613}
632 614
633 sb = inode->i_sb; 615static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
634 if (sb == NULL) 616 struct cifs_ntsd *pnntsd, u32 acllen)
635 return rc; 617{
618 int xid, rc;
636 619
637 cifs_sb = CIFS_SB(sb);
638 xid = GetXid(); 620 xid = GetXid();
621 rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
622 FreeXid(xid);
639 623
640 open_file = find_readable_file(CIFS_I(inode)); 624 cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
641 if (open_file) { 625 return rc;
642 unlock_file = true; 626}
643 fid = open_file->netfid; 627
644 } else { 628static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
645 int oplock = 0; 629 struct cifs_ntsd *pnntsd, u32 acllen)
646 /* open file */ 630{
647 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, 631 int oplock = 0;
648 WRITE_DAC, 0, &fid, &oplock, NULL, 632 int xid, rc;
649 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 633 __u16 fid;
650 CIFS_MOUNT_MAP_SPECIAL_CHR); 634
651 if (rc != 0) { 635 xid = GetXid();
652 cERROR(1, ("Unable to open file to set ACL")); 636
653 FreeXid(xid); 637 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
654 return rc; 638 &fid, &oplock, NULL, cifs_sb->local_nls,
655 } 639 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
640 if (rc) {
641 cERROR(1, ("Unable to open file to set ACL"));
642 goto out;
656 } 643 }
657 644
658 rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); 645 rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
659 cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); 646 cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
660 if (unlock_file)
661 atomic_dec(&open_file->wrtPending);
662 else
663 CIFSSMBClose(xid, cifs_sb->tcon, fid);
664 647
648 CIFSSMBClose(xid, cifs_sb->tcon, fid);
649 out:
665 FreeXid(xid); 650 FreeXid(xid);
651 return rc;
652}
666 653
654/* Set an ACL on the server */
655static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
656 struct inode *inode, const char *path)
657{
658 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
659 struct cifsFileInfo *open_file;
660 int rc;
661
662 cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
663
664 open_file = find_readable_file(CIFS_I(inode));
665 if (!open_file)
666 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
667
668 rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
669 atomic_dec(&open_file->wrtPending);
667 return rc; 670 return rc;
668} 671}
669 672
670/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 673/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
671void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) 674void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
675 const char *path, const __u16 *pfid)
672{ 676{
673 struct cifs_ntsd *pntsd = NULL; 677 struct cifs_ntsd *pntsd = NULL;
674 u32 acllen = 0; 678 u32 acllen = 0;
675 int rc = 0; 679 int rc = 0;
676 680
677 cFYI(DBG2, ("converting ACL to mode for %s", path)); 681 cFYI(DBG2, ("converting ACL to mode for %s", path));
678 pntsd = get_cifs_acl(&acllen, inode, path, pfid); 682
683 if (pfid)
684 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
685 else
686 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
679 687
680 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 688 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
681 if (pntsd) 689 if (pntsd)
@@ -698,7 +706,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
698 cFYI(DBG2, ("set ACL from mode for %s", path)); 706 cFYI(DBG2, ("set ACL from mode for %s", path));
699 707
700 /* Get the security descriptor */ 708 /* Get the security descriptor */
701 pntsd = get_cifs_acl(&secdesclen, inode, path, NULL); 709 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
702 710
703 /* Add three ACEs for owner, group, everyone getting rid of 711 /* Add three ACEs for owner, group, everyone getting rid of
704 other ACEs as chmod disables ACEs and set the security descriptor */ 712 other ACEs as chmod disables ACEs and set the security descriptor */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5e6d35804d73..0a10a59b6392 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -146,7 +146,7 @@ cifs_read_super(struct super_block *sb, void *data,
146#endif 146#endif
147 sb->s_blocksize = CIFS_MAX_MSGSIZE; 147 sb->s_blocksize = CIFS_MAX_MSGSIZE;
148 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ 148 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
149 inode = cifs_iget(sb, ROOT_I); 149 inode = cifs_root_iget(sb, ROOT_I);
150 150
151 if (IS_ERR(inode)) { 151 if (IS_ERR(inode)) {
152 rc = PTR_ERR(inode); 152 rc = PTR_ERR(inode);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 051b71cfdea9..9570a0e8023f 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,7 +36,7 @@ extern void cifs_read_inode(struct inode *);
36 36
37/* Functions related to inodes */ 37/* Functions related to inodes */
38extern const struct inode_operations cifs_dir_inode_ops; 38extern const struct inode_operations cifs_dir_inode_ops;
39extern struct inode *cifs_iget(struct super_block *, unsigned long); 39extern struct inode *cifs_root_iget(struct super_block *, unsigned long);
40extern int cifs_create(struct inode *, struct dentry *, int, 40extern int cifs_create(struct inode *, struct dentry *, int,
41 struct nameidata *); 41 struct nameidata *);
42extern struct dentry *cifs_lookup(struct inode *, struct dentry *, 42extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
100extern const struct export_operations cifs_export_ops; 100extern const struct export_operations cifs_export_ops;
101#endif /* EXPERIMENTAL */ 101#endif /* EXPERIMENTAL */
102 102
103#define CIFS_VERSION "1.58" 103#define CIFS_VERSION "1.59"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index fae083930eee..f9452329bcce 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -90,10 +90,10 @@ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
90 struct cifsTconInfo *); 90 struct cifsTconInfo *);
91extern void DeleteOplockQEntry(struct oplock_q_entry *); 91extern void DeleteOplockQEntry(struct oplock_q_entry *);
92extern void DeleteTconOplockQEntries(struct cifsTconInfo *); 92extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
93extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601); 93extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
94extern u64 cifs_UnixTimeToNT(struct timespec); 94extern u64 cifs_UnixTimeToNT(struct timespec);
95extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 95extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
96extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 96 int offset);
97 97
98extern int cifs_posix_open(char *full_path, struct inode **pinode, 98extern int cifs_posix_open(char *full_path, struct inode **pinode,
99 struct super_block *sb, int mode, int oflags, 99 struct super_block *sb, int mode, int oflags,
@@ -108,8 +108,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
108extern int cifs_get_inode_info_unix(struct inode **pinode, 108extern int cifs_get_inode_info_unix(struct inode **pinode,
109 const unsigned char *search_path, 109 const unsigned char *search_path,
110 struct super_block *sb, int xid); 110 struct super_block *sb, int xid);
111extern void acl_to_uid_mode(struct inode *inode, const char *path, 111extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
112 const __u16 *pfid); 112 const char *path, const __u16 *pfid);
113extern int mode_to_acl(struct inode *inode, const char *path, __u64); 113extern int mode_to_acl(struct inode *inode, const char *path, __u64);
114 114
115extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, 115extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d06260251c30..b84c61d5bca4 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
524 int val, seconds, remain, result; 524 int val, seconds, remain, result;
525 struct timespec ts, utc; 525 struct timespec ts, utc;
526 utc = CURRENT_TIME; 526 utc = CURRENT_TIME;
527 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), 527 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
528 le16_to_cpu(rsp->SrvTime.Time)); 528 rsp->SrvTime.Time, 0);
529 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d", 529 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
530 (int)ts.tv_sec, (int)utc.tv_sec, 530 (int)ts.tv_sec, (int)utc.tv_sec,
531 (int)(utc.tv_sec - ts.tv_sec))); 531 (int)(utc.tv_sec - ts.tv_sec)));
@@ -2427,8 +2427,7 @@ querySymLinkRetry:
2427 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; 2427 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2428 pSMB->TotalDataCount = 0; 2428 pSMB->TotalDataCount = 0;
2429 pSMB->MaxParameterCount = cpu_to_le16(2); 2429 pSMB->MaxParameterCount = cpu_to_le16(2);
2430 /* BB find exact max data count below from sess structure BB */ 2430 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2431 pSMB->MaxDataCount = cpu_to_le16(4000);
2432 pSMB->MaxSetupCount = 0; 2431 pSMB->MaxSetupCount = 0;
2433 pSMB->Reserved = 0; 2432 pSMB->Reserved = 0;
2434 pSMB->Flags = 0; 2433 pSMB->Flags = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4aa81a507b74..97f4311b9a8e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -35,6 +35,7 @@
35#include <linux/namei.h> 35#include <linux/namei.h>
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37#include <asm/processor.h> 37#include <asm/processor.h>
38#include <linux/inet.h>
38#include <net/ipv6.h> 39#include <net/ipv6.h>
39#include "cifspdu.h" 40#include "cifspdu.h"
40#include "cifsglob.h" 41#include "cifsglob.h"
@@ -61,7 +62,6 @@ struct smb_vol {
61 char *domainname; 62 char *domainname;
62 char *UNC; 63 char *UNC;
63 char *UNCip; 64 char *UNCip;
64 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
65 char *iocharset; /* local code page for mapping to and from Unicode */ 65 char *iocharset; /* local code page for mapping to and from Unicode */
66 char source_rfc1001_name[16]; /* netbios name of client */ 66 char source_rfc1001_name[16]; /* netbios name of client */
67 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ 67 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
@@ -827,14 +827,16 @@ cifs_parse_mount_options(char *options, const char *devname,
827 vol->target_rfc1001_name[0] = 0; 827 vol->target_rfc1001_name[0] = 0;
828 vol->linux_uid = current_uid(); /* use current_euid() instead? */ 828 vol->linux_uid = current_uid(); /* use current_euid() instead? */
829 vol->linux_gid = current_gid(); 829 vol->linux_gid = current_gid();
830 vol->dir_mode = S_IRWXUGO; 830
831 /* 2767 perms indicate mandatory locking support */ 831 /* default to only allowing write access to owner of the mount */
832 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); 832 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
833 833
834 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 834 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
835 vol->rw = true; 835 vol->rw = true;
836 /* default is always to request posix paths. */ 836 /* default is always to request posix paths. */
837 vol->posix_paths = 1; 837 vol->posix_paths = 1;
838 /* default to using server inode numbers where available */
839 vol->server_ino = 1;
838 840
839 if (!options) 841 if (!options)
840 return 1; 842 return 1;
@@ -955,10 +957,12 @@ cifs_parse_mount_options(char *options, const char *devname,
955 } 957 }
956 strcpy(vol->password, value); 958 strcpy(vol->password, value);
957 } 959 }
958 } else if (strnicmp(data, "ip", 2) == 0) { 960 } else if (!strnicmp(data, "ip", 2) ||
961 !strnicmp(data, "addr", 4)) {
959 if (!value || !*value) { 962 if (!value || !*value) {
960 vol->UNCip = NULL; 963 vol->UNCip = NULL;
961 } else if (strnlen(value, 35) < 35) { 964 } else if (strnlen(value, INET6_ADDRSTRLEN) <
965 INET6_ADDRSTRLEN) {
962 vol->UNCip = value; 966 vol->UNCip = value;
963 } else { 967 } else {
964 printk(KERN_WARNING "CIFS: ip address " 968 printk(KERN_WARNING "CIFS: ip address "
@@ -1092,17 +1096,17 @@ cifs_parse_mount_options(char *options, const char *devname,
1092 return 1; 1096 return 1;
1093 } 1097 }
1094 } else if (strnicmp(data, "uid", 3) == 0) { 1098 } else if (strnicmp(data, "uid", 3) == 0) {
1095 if (value && *value) { 1099 if (value && *value)
1096 vol->linux_uid = 1100 vol->linux_uid =
1097 simple_strtoul(value, &value, 0); 1101 simple_strtoul(value, &value, 0);
1102 } else if (strnicmp(data, "forceuid", 8) == 0) {
1098 vol->override_uid = 1; 1103 vol->override_uid = 1;
1099 }
1100 } else if (strnicmp(data, "gid", 3) == 0) { 1104 } else if (strnicmp(data, "gid", 3) == 0) {
1101 if (value && *value) { 1105 if (value && *value)
1102 vol->linux_gid = 1106 vol->linux_gid =
1103 simple_strtoul(value, &value, 0); 1107 simple_strtoul(value, &value, 0);
1108 } else if (strnicmp(data, "forcegid", 8) == 0) {
1104 vol->override_gid = 1; 1109 vol->override_gid = 1;
1105 }
1106 } else if (strnicmp(data, "file_mode", 4) == 0) { 1110 } else if (strnicmp(data, "file_mode", 4) == 0) {
1107 if (value && *value) { 1111 if (value && *value) {
1108 vol->file_mode = 1112 vol->file_mode =
@@ -1315,16 +1319,6 @@ cifs_parse_mount_options(char *options, const char *devname,
1315 vol->direct_io = 1; 1319 vol->direct_io = 1;
1316 } else if (strnicmp(data, "forcedirectio", 13) == 0) { 1320 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1317 vol->direct_io = 1; 1321 vol->direct_io = 1;
1318 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1319 if (!value || !*value) {
1320 vol->in6_addr = NULL;
1321 } else if (strnlen(value, 49) == 48) {
1322 vol->in6_addr = value;
1323 } else {
1324 printk(KERN_WARNING "CIFS: ip v6 address not "
1325 "48 characters long\n");
1326 return 1;
1327 }
1328 } else if (strnicmp(data, "noac", 4) == 0) { 1322 } else if (strnicmp(data, "noac", 4) == 0) {
1329 printk(KERN_WARNING "CIFS: Mount option noac not " 1323 printk(KERN_WARNING "CIFS: Mount option noac not "
1330 "supported. Instead set " 1324 "supported. Instead set "
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 302ea15f02e6..06866841b97f 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -241,7 +241,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
241 /* BB need same check in cifs_create too? */ 241 /* BB need same check in cifs_create too? */
242 /* if not oplocked, invalidate inode pages if mtime or file 242 /* if not oplocked, invalidate inode pages if mtime or file
243 size changed */ 243 size changed */
244 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); 244 temp = cifs_NTtimeToUnix(buf->LastWriteTime);
245 if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && 245 if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
246 (file->f_path.dentry->d_inode->i_size == 246 (file->f_path.dentry->d_inode->i_size ==
247 (loff_t)le64_to_cpu(buf->EndOfFile))) { 247 (loff_t)le64_to_cpu(buf->EndOfFile))) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 9c869a6dcba1..fad882b075ba 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -85,10 +85,10 @@ static void cifs_unix_info_to_inode(struct inode *inode,
85 __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); 85 __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
86 __u64 end_of_file = le64_to_cpu(info->EndOfFile); 86 __u64 end_of_file = le64_to_cpu(info->EndOfFile);
87 87
88 inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime)); 88 inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime);
89 inode->i_mtime = 89 inode->i_mtime =
90 cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime)); 90 cifs_NTtimeToUnix(info->LastModificationTime);
91 inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange)); 91 inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
92 inode->i_mode = le64_to_cpu(info->Permissions); 92 inode->i_mode = le64_to_cpu(info->Permissions);
93 93
94 /* 94 /*
@@ -554,14 +554,11 @@ int cifs_get_inode_info(struct inode **pinode,
554 554
555 /* Linux can not store file creation time so ignore it */ 555 /* Linux can not store file creation time so ignore it */
556 if (pfindData->LastAccessTime) 556 if (pfindData->LastAccessTime)
557 inode->i_atime = cifs_NTtimeToUnix 557 inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
558 (le64_to_cpu(pfindData->LastAccessTime));
559 else /* do not need to use current_fs_time - time not stored */ 558 else /* do not need to use current_fs_time - time not stored */
560 inode->i_atime = CURRENT_TIME; 559 inode->i_atime = CURRENT_TIME;
561 inode->i_mtime = 560 inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
562 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 561 inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
563 inode->i_ctime =
564 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
565 cFYI(DBG2, ("Attributes came in as 0x%x", attr)); 562 cFYI(DBG2, ("Attributes came in as 0x%x", attr));
566 if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { 563 if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
567 inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; 564 inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
@@ -629,7 +626,7 @@ int cifs_get_inode_info(struct inode **pinode,
629 /* fill in 0777 bits from ACL */ 626 /* fill in 0777 bits from ACL */
630 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
631 cFYI(1, ("Getting mode bits from ACL")); 628 cFYI(1, ("Getting mode bits from ACL"));
632 acl_to_uid_mode(inode, full_path, pfid); 629 acl_to_uid_mode(cifs_sb, inode, full_path, pfid);
633 } 630 }
634#endif 631#endif
635 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 632 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
@@ -699,7 +696,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
699} 696}
700 697
701/* gets root inode */ 698/* gets root inode */
702struct inode *cifs_iget(struct super_block *sb, unsigned long ino) 699struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
703{ 700{
704 int xid; 701 int xid;
705 struct cifs_sb_info *cifs_sb; 702 struct cifs_sb_info *cifs_sb;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index e2fe998989a3..32d6baa0a54f 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -853,12 +853,12 @@ smbCalcSize_LE(struct smb_hdr *ptr)
853 853
854#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) 854#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
855 855
856 /* 856/*
857 * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) 857 * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
858 * into Unix UTC (based 1970-01-01, in seconds). 858 * into Unix UTC (based 1970-01-01, in seconds).
859 */ 859 */
860struct timespec 860struct timespec
861cifs_NTtimeToUnix(u64 ntutc) 861cifs_NTtimeToUnix(__le64 ntutc)
862{ 862{
863 struct timespec ts; 863 struct timespec ts;
864 /* BB what about the timezone? BB */ 864 /* BB what about the timezone? BB */
@@ -866,7 +866,7 @@ cifs_NTtimeToUnix(u64 ntutc)
866 /* Subtract the NTFS time offset, then convert to 1s intervals. */ 866 /* Subtract the NTFS time offset, then convert to 1s intervals. */
867 u64 t; 867 u64 t;
868 868
869 t = ntutc - NTFS_TIME_OFFSET; 869 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
870 ts.tv_nsec = do_div(t, 10000000) * 100; 870 ts.tv_nsec = do_div(t, 10000000) * 100;
871 ts.tv_sec = t; 871 ts.tv_sec = t;
872 return ts; 872 return ts;
@@ -883,16 +883,12 @@ cifs_UnixTimeToNT(struct timespec t)
883static int total_days_of_prev_months[] = 883static int total_days_of_prev_months[] =
884{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; 884{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
885 885
886 886struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
887__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
888{
889 return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
890}
891
892struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
893{ 887{
894 struct timespec ts; 888 struct timespec ts;
895 int sec, min, days, month, year; 889 int sec, min, days, month, year;
890 u16 date = le16_to_cpu(le_date);
891 u16 time = le16_to_cpu(le_time);
896 SMB_TIME *st = (SMB_TIME *)&time; 892 SMB_TIME *st = (SMB_TIME *)&time;
897 SMB_DATE *sd = (SMB_DATE *)&date; 893 SMB_DATE *sd = (SMB_DATE *)&date;
898 894
@@ -933,7 +929,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
933 days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); 929 days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
934 sec += 24 * 60 * 60 * days; 930 sec += 24 * 60 * 60 * days;
935 931
936 ts.tv_sec = sec; 932 ts.tv_sec = sec + offset;
937 933
938 /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ 934 /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
939 935
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 964e097c8203..86d0055dc529 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -115,17 +115,6 @@ construct_dentry(struct qstr *qstring, struct file *file,
115 return rc; 115 return rc;
116} 116}
117 117
118static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
119{
120 if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
121 inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
122 inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
123 inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
124 }
125 return;
126}
127
128
129static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, 118static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
130 char *buf, unsigned int *pobject_type, int isNewInode) 119 char *buf, unsigned int *pobject_type, int isNewInode)
131{ 120{
@@ -150,26 +139,25 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
150 allocation_size = le64_to_cpu(pfindData->AllocationSize); 139 allocation_size = le64_to_cpu(pfindData->AllocationSize);
151 end_of_file = le64_to_cpu(pfindData->EndOfFile); 140 end_of_file = le64_to_cpu(pfindData->EndOfFile);
152 tmp_inode->i_atime = 141 tmp_inode->i_atime =
153 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 142 cifs_NTtimeToUnix(pfindData->LastAccessTime);
154 tmp_inode->i_mtime = 143 tmp_inode->i_mtime =
155 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 144 cifs_NTtimeToUnix(pfindData->LastWriteTime);
156 tmp_inode->i_ctime = 145 tmp_inode->i_ctime =
157 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 146 cifs_NTtimeToUnix(pfindData->ChangeTime);
158 } else { /* legacy, OS2 and DOS style */ 147 } else { /* legacy, OS2 and DOS style */
159/* struct timespec ts;*/ 148 int offset = cifs_sb->tcon->ses->server->timeAdj;
160 FIND_FILE_STANDARD_INFO *pfindData = 149 FIND_FILE_STANDARD_INFO *pfindData =
161 (FIND_FILE_STANDARD_INFO *)buf; 150 (FIND_FILE_STANDARD_INFO *)buf;
162 151
163 tmp_inode->i_mtime = cnvrtDosUnixTm( 152 tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
164 le16_to_cpu(pfindData->LastWriteDate), 153 pfindData->LastWriteTime,
165 le16_to_cpu(pfindData->LastWriteTime)); 154 offset);
166 tmp_inode->i_atime = cnvrtDosUnixTm( 155 tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
167 le16_to_cpu(pfindData->LastAccessDate), 156 pfindData->LastAccessTime,
168 le16_to_cpu(pfindData->LastAccessTime)); 157 offset);
169 tmp_inode->i_ctime = cnvrtDosUnixTm( 158 tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
170 le16_to_cpu(pfindData->LastWriteDate), 159 pfindData->LastWriteTime,
171 le16_to_cpu(pfindData->LastWriteTime)); 160 offset);
172 AdjustForTZ(cifs_sb->tcon, tmp_inode);
173 attr = le16_to_cpu(pfindData->Attributes); 161 attr = le16_to_cpu(pfindData->Attributes);
174 allocation_size = le32_to_cpu(pfindData->AllocationSize); 162 allocation_size = le32_to_cpu(pfindData->AllocationSize);
175 end_of_file = le32_to_cpu(pfindData->DataSize); 163 end_of_file = le32_to_cpu(pfindData->DataSize);
@@ -331,11 +319,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
331 local_size = tmp_inode->i_size; 319 local_size = tmp_inode->i_size;
332 320
333 tmp_inode->i_atime = 321 tmp_inode->i_atime =
334 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 322 cifs_NTtimeToUnix(pfindData->LastAccessTime);
335 tmp_inode->i_mtime = 323 tmp_inode->i_mtime =
336 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime)); 324 cifs_NTtimeToUnix(pfindData->LastModificationTime);
337 tmp_inode->i_ctime = 325 tmp_inode->i_ctime =
338 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange)); 326 cifs_NTtimeToUnix(pfindData->LastStatusChange);
339 327
340 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); 328 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
341 /* since we set the inode type below we need to mask off type 329 /* since we set the inode type below we need to mask off type