aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c130
1 files changed, 86 insertions, 44 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2caca06b4bae..20ba7dcc9959 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1613 return rc; 1613 return rc;
1614} 1614}
1615 1615
1616void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
1617 struct super_block * sb, struct smb_vol * vol_info)
1618{
1619 /* if we are reconnecting then should we check to see if
1620 * any requested capabilities changed locally e.g. via
1621 * remount but we can not do much about it here
1622 * if they have (even if we could detect it by the following)
1623 * Perhaps we could add a backpointer to array of sb from tcon
1624 * or if we change to make all sb to same share the same
1625 * sb as NFS - then we only have one backpointer to sb.
1626 * What if we wanted to mount the server share twice once with
1627 * and once without posixacls or posix paths? */
1628 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1629
1630
1631 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1632 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1633
1634 /* check for reconnect case in which we do not
1635 want to change the mount behavior if we can avoid it */
1636 if(vol_info == NULL) {
1637 /* turn off POSIX ACL and PATHNAMES if not set
1638 originally at mount time */
1639 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1640 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1641 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1642 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1643
1644
1645
1646
1647 }
1648
1649 cap &= CIFS_UNIX_CAP_MASK;
1650 if(vol_info && vol_info->no_psx_acl)
1651 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1652 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1653 cFYI(1,("negotiated posix acl support"));
1654 if(sb)
1655 sb->s_flags |= MS_POSIXACL;
1656 }
1657
1658 if(vol_info && vol_info->posix_paths == 0)
1659 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1660 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1661 cFYI(1,("negotiate posix pathnames"));
1662 if(sb)
1663 CIFS_SB(sb)->mnt_cifs_flags |=
1664 CIFS_MOUNT_POSIX_PATHS;
1665 }
1666
1667 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1668#ifdef CONFIG_CIFS_DEBUG2
1669 if(cap & CIFS_UNIX_FCNTL_CAP)
1670 cFYI(1,("FCNTL cap"));
1671 if(cap & CIFS_UNIX_EXTATTR_CAP)
1672 cFYI(1,("EXTATTR cap"));
1673 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1674 cFYI(1,("POSIX path cap"));
1675 if(cap & CIFS_UNIX_XATTR_CAP)
1676 cFYI(1,("XATTR cap"));
1677 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
1678 cFYI(1,("POSIX ACL cap"));
1679#endif /* CIFS_DEBUG2 */
1680 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1681 cFYI(1,("setting capabilities failed"));
1682 }
1683 }
1684}
1685
1616int 1686int
1617cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 1687cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1618 char *mount_data, const char *devname) 1688 char *mount_data, const char *devname)
@@ -1928,20 +1998,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1928 if (tcon == NULL) 1998 if (tcon == NULL)
1929 rc = -ENOMEM; 1999 rc = -ENOMEM;
1930 else { 2000 else {
1931 /* check for null share name ie connect to dfs root */ 2001 /* check for null share name ie connecting to
2002 * dfs root */
1932 2003
1933 /* BB check if this works for exactly length three strings */ 2004 /* BB check if this works for exactly length
2005 * three strings */
1934 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2006 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1935 && (strchr(volume_info.UNC + 3, '/') == 2007 && (strchr(volume_info.UNC + 3, '/') ==
1936 NULL)) { 2008 NULL)) {
1937 rc = connect_to_dfs_path(xid, pSesInfo, 2009 rc = connect_to_dfs_path(xid, pSesInfo,
1938 "", cifs_sb->local_nls, 2010 "", cifs_sb->local_nls,
1939 cifs_sb->mnt_cifs_flags & 2011 cifs_sb->mnt_cifs_flags &
1940 CIFS_MOUNT_MAP_SPECIAL_CHR); 2012 CIFS_MOUNT_MAP_SPECIAL_CHR);
1941 kfree(volume_info.UNC); 2013 kfree(volume_info.UNC);
1942 FreeXid(xid); 2014 FreeXid(xid);
1943 return -ENODEV; 2015 return -ENODEV;
1944 } else { 2016 } else {
2017 /* BB Do we need to wrap sesSem around
2018 * this TCon call and Unix SetFS as
2019 * we do on SessSetup and reconnect? */
1945 rc = CIFSTCon(xid, pSesInfo, 2020 rc = CIFSTCon(xid, pSesInfo,
1946 volume_info.UNC, 2021 volume_info.UNC,
1947 tcon, cifs_sb->local_nls); 2022 tcon, cifs_sb->local_nls);
@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1962 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ 2037 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1963 } 2038 }
1964 2039
2040 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
1965 sb->s_time_gran = 100; 2041 sb->s_time_gran = 100;
1966 2042
1967/* on error free sesinfo and tcon struct if needed */ 2043/* on error free sesinfo and tcon struct if needed */
@@ -2006,45 +2082,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2006 /* do not care if following two calls succeed - informational */ 2082 /* do not care if following two calls succeed - informational */
2007 CIFSSMBQFSDeviceInfo(xid, tcon); 2083 CIFSSMBQFSDeviceInfo(xid, tcon);
2008 CIFSSMBQFSAttributeInfo(xid, tcon); 2084 CIFSSMBQFSAttributeInfo(xid, tcon);
2009 2085
2010 if (tcon->ses->capabilities & CAP_UNIX) { 2086 /* tell server which Unix caps we support */
2011 if(!CIFSSMBQFSUnixInfo(xid, tcon)) { 2087 if (tcon->ses->capabilities & CAP_UNIX)
2012 __u64 cap = 2088 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2013 le64_to_cpu(tcon->fsUnixInfo.Capability); 2089
2014 cap &= CIFS_UNIX_CAP_MASK;
2015 if(volume_info.no_psx_acl)
2016 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2017 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
2018 cFYI(1,("negotiated posix acl support"));
2019 sb->s_flags |= MS_POSIXACL;
2020 }
2021
2022 if(volume_info.posix_paths == 0)
2023 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2024 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2025 cFYI(1,("negotiate posix pathnames"));
2026 cifs_sb->mnt_cifs_flags |=
2027 CIFS_MOUNT_POSIX_PATHS;
2028 }
2029
2030 cFYI(1,("Negotiate caps 0x%x",(int)cap));
2031#ifdef CONFIG_CIFS_DEBUG2
2032 if(cap & CIFS_UNIX_FCNTL_CAP)
2033 cFYI(1,("FCNTL cap"));
2034 if(cap & CIFS_UNIX_EXTATTR_CAP)
2035 cFYI(1,("EXTATTR cap"));
2036 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2037 cFYI(1,("POSIX path cap"));
2038 if(cap & CIFS_UNIX_XATTR_CAP)
2039 cFYI(1,("XATTR cap"));
2040 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
2041 cFYI(1,("POSIX ACL cap"));
2042#endif /* CIFS_DEBUG2 */
2043 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
2044 cFYI(1,("setting capabilities failed"));
2045 }
2046 }
2047 }
2048 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) 2090 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2049 cifs_sb->wsize = min(cifs_sb->wsize, 2091 cifs_sb->wsize = min(cifs_sb->wsize,
2050 (tcon->ses->server->maxBuf - 2092 (tcon->ses->server->maxBuf -