aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-11-13 14:45:32 -0500
committerSteve French <sfrench@us.ibm.com>2008-11-13 14:45:32 -0500
commit3b7952109361c684caf0c50474da8662ecc81019 (patch)
tree402062ed63236ef245d8d65010d8f06520df8453 /fs
parentc527c8a7ffa18400c2c1488f7ab5aff5e83f3c8e (diff)
[CIFS] Fix cifs reconnection flags
In preparation for Jeff's big umount/mount fixes to remove the possibility of various races in cifs mount and linked list handling of sessions, sockets and tree connections, this patch cleans up some repetitive code in cifs_mount, and addresses a problem with ses->status and tcon->tidStatus in which we were overloading the "need_reconnect" state with other status in that field. So the "need_reconnect" flag has been broken out from those two state fields (need reconnect was not mutually exclusive from some of the other possible tid and ses states). In addition, a few exit cases in cifs_mount were cleaned up, and a problem with a tcon flag (for lease support) was not being set consistently for the 2nd mount of the same share CC: Jeff Layton <jlayton@redhat.com> CC: Shirish Pargaonkar <shirishp@us.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsglob.h5
-rw-r--r--fs/cifs/cifssmb.c40
-rw-r--r--fs/cifs/connect.c262
-rw-r--r--fs/cifs/file.c2
5 files changed, 160 insertions, 151 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ac5915d61dca..903bbd6449d1 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1013,7 +1013,7 @@ static int cifs_oplock_thread(void *dummyarg)
1013 not bother sending an oplock release if session 1013 not bother sending an oplock release if session
1014 to server still is disconnected since oplock 1014 to server still is disconnected since oplock
1015 already released by the server in that case */ 1015 already released by the server in that case */
1016 if (pTcon->tidStatus != CifsNeedReconnect) { 1016 if (!pTcon->need_reconnect) {
1017 rc = CIFSSMBLock(0, pTcon, netfid, 1017 rc = CIFSSMBLock(0, pTcon, netfid,
1018 0 /* len */ , 0 /* offset */, 0, 1018 0 /* len */ , 0 /* offset */, 0,
1019 0, LOCKING_ANDX_OPLOCK_RELEASE, 1019 0, LOCKING_ANDX_OPLOCK_RELEASE,
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1cb1189f24e0..dc0aa140f1bf 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -122,6 +122,8 @@ struct cifs_cred {
122 */ 122 */
123 123
124struct TCP_Server_Info { 124struct TCP_Server_Info {
125 struct list_head tcp_ses_list;
126 struct list_head smb_ses_list;
125 /* 15 character server name + 0x20 16th byte indicating type = srv */ 127 /* 15 character server name + 0x20 16th byte indicating type = srv */
126 char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 128 char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
127 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; 129 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
@@ -195,6 +197,7 @@ struct cifsUidInfo {
195 */ 197 */
196struct cifsSesInfo { 198struct cifsSesInfo {
197 struct list_head cifsSessionList; 199 struct list_head cifsSessionList;
200 struct list_head tcon_list;
198 struct semaphore sesSem; 201 struct semaphore sesSem;
199#if 0 202#if 0
200 struct cifsUidInfo *uidInfo; /* pointer to user info */ 203 struct cifsUidInfo *uidInfo; /* pointer to user info */
@@ -216,6 +219,7 @@ struct cifsSesInfo {
216 char userName[MAX_USERNAME_SIZE + 1]; 219 char userName[MAX_USERNAME_SIZE + 1];
217 char *domainName; 220 char *domainName;
218 char *password; 221 char *password;
222 bool need_reconnect:1; /* connection reset, uid now invalid */
219}; 223};
220/* no more than one of the following three session flags may be set */ 224/* no more than one of the following three session flags may be set */
221#define CIFS_SES_NT4 1 225#define CIFS_SES_NT4 1
@@ -288,6 +292,7 @@ struct cifsTconInfo {
288 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol 292 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
289 for this mount even if server would support */ 293 for this mount even if server would support */
290 bool local_lease:1; /* check leases (only) on local system not remote */ 294 bool local_lease:1; /* check leases (only) on local system not remote */
295 bool need_reconnect:1; /* connection reset, tid now invalid */
291 /* BB add field for back pointer to sb struct(s)? */ 296 /* BB add field for back pointer to sb struct(s)? */
292}; 297};
293 298
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d5eac48fc415..7f0651b69573 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -190,10 +190,10 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
190 /* need to prevent multiple threads trying to 190 /* need to prevent multiple threads trying to
191 simultaneously reconnect the same SMB session */ 191 simultaneously reconnect the same SMB session */
192 down(&tcon->ses->sesSem); 192 down(&tcon->ses->sesSem);
193 if (tcon->ses->status == CifsNeedReconnect) 193 if (tcon->ses->need_reconnect)
194 rc = cifs_setup_session(0, tcon->ses, 194 rc = cifs_setup_session(0, tcon->ses,
195 nls_codepage); 195 nls_codepage);
196 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) { 196 if (!rc && (tcon->need_reconnect)) {
197 mark_open_files_invalid(tcon); 197 mark_open_files_invalid(tcon);
198 rc = CIFSTCon(0, tcon->ses, tcon->treeName, 198 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
199 tcon, nls_codepage); 199 tcon, nls_codepage);
@@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
295 check for tcp and smb session status done differently 295 check for tcp and smb session status done differently
296 for those three - in the calling routine */ 296 for those three - in the calling routine */
297 if (tcon) { 297 if (tcon) {
298 if (tcon->tidStatus == CifsExiting) { 298 if (tcon->need_reconnect) {
299 /* only tree disconnect, open, and write, 299 /* only tree disconnect, open, and write,
300 (and ulogoff which does not have tcon) 300 (and ulogoff which does not have tcon)
301 are allowed as we start force umount */ 301 are allowed as we start force umount */
@@ -337,10 +337,10 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
337 /* need to prevent multiple threads trying to 337 /* need to prevent multiple threads trying to
338 simultaneously reconnect the same SMB session */ 338 simultaneously reconnect the same SMB session */
339 down(&tcon->ses->sesSem); 339 down(&tcon->ses->sesSem);
340 if (tcon->ses->status == CifsNeedReconnect) 340 if (tcon->ses->need_reconnect)
341 rc = cifs_setup_session(0, tcon->ses, 341 rc = cifs_setup_session(0, tcon->ses,
342 nls_codepage); 342 nls_codepage);
343 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) { 343 if (!rc && (tcon->need_reconnect)) {
344 mark_open_files_invalid(tcon); 344 mark_open_files_invalid(tcon);
345 rc = CIFSTCon(0, tcon->ses, tcon->treeName, 345 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
346 tcon, nls_codepage); 346 tcon, nls_codepage);
@@ -759,7 +759,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
759 759
760 /* No need to return error on this operation if tid invalidated and 760 /* No need to return error on this operation if tid invalidated and
761 closed on server already e.g. due to tcp session crashing */ 761 closed on server already e.g. due to tcp session crashing */
762 if (tcon->tidStatus == CifsNeedReconnect) { 762 if (tcon->need_reconnect) {
763 up(&tcon->tconSem); 763 up(&tcon->tconSem);
764 return 0; 764 return 0;
765 } 765 }
@@ -806,32 +806,36 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
806 up(&ses->sesSem); 806 up(&ses->sesSem);
807 return -EBUSY; 807 return -EBUSY;
808 } 808 }
809
810 if (ses->server == NULL)
811 return -EIO;
812
813 if (ses->need_reconnect)
814 goto session_already_dead; /* no need to send SMBlogoff if uid
815 already closed due to reconnect */
809 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); 816 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
810 if (rc) { 817 if (rc) {
811 up(&ses->sesSem); 818 up(&ses->sesSem);
812 return rc; 819 return rc;
813 } 820 }
814 821
815 if (ses->server) { 822 pSMB->hdr.Mid = GetNextMid(ses->server);
816 pSMB->hdr.Mid = GetNextMid(ses->server);
817 823
818 if (ses->server->secMode & 824 if (ses->server->secMode &
819 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 825 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
820 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 826 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
821 }
822 827
823 pSMB->hdr.Uid = ses->Suid; 828 pSMB->hdr.Uid = ses->Suid;
824 829
825 pSMB->AndXCommand = 0xFF; 830 pSMB->AndXCommand = 0xFF;
826 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); 831 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
827 if (ses->server) { 832session_already_dead:
828 atomic_dec(&ses->server->socketUseCount); 833 atomic_dec(&ses->server->socketUseCount);
829 if (atomic_read(&ses->server->socketUseCount) == 0) { 834 if (atomic_read(&ses->server->socketUseCount) == 0) {
830 spin_lock(&GlobalMid_Lock); 835 spin_lock(&GlobalMid_Lock);
831 ses->server->tcpStatus = CifsExiting; 836 ses->server->tcpStatus = CifsExiting;
832 spin_unlock(&GlobalMid_Lock); 837 spin_unlock(&GlobalMid_Lock);
833 rc = -ESHUTDOWN; 838 rc = -ESHUTDOWN;
834 }
835 } 839 }
836 up(&ses->sesSem); 840 up(&ses->sesSem);
837 841
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c682be8f2984..c1cd1217c990 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -149,7 +149,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
149 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 149 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
150 if (ses->server) { 150 if (ses->server) {
151 if (ses->server == server) { 151 if (ses->server == server) {
152 ses->status = CifsNeedReconnect; 152 ses->need_reconnect = true;
153 ses->ipc_tid = 0; 153 ses->ipc_tid = 0;
154 } 154 }
155 } 155 }
@@ -158,7 +158,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
158 list_for_each(tmp, &GlobalTreeConnectionList) { 158 list_for_each(tmp, &GlobalTreeConnectionList) {
159 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 159 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
160 if ((tcon->ses) && (tcon->ses->server == server)) 160 if ((tcon->ses) && (tcon->ses->server == server))
161 tcon->tidStatus = CifsNeedReconnect; 161 tcon->need_reconnect = true;
162 } 162 }
163 read_unlock(&GlobalSMBSeslock); 163 read_unlock(&GlobalSMBSeslock);
164 /* do not want to be sending data on a socket we are freeing */ 164 /* do not want to be sending data on a socket we are freeing */
@@ -1891,6 +1891,92 @@ kill_cifsd(struct TCP_Server_Info *server)
1891 force_sig(SIGKILL, task); 1891 force_sig(SIGKILL, task);
1892} 1892}
1893 1893
1894static void setup_cifs_sb(struct smb_vol *pvolume_info,
1895 struct cifs_sb_info *cifs_sb)
1896{
1897 if (pvolume_info->rsize > CIFSMaxBufSize) {
1898 cERROR(1, ("rsize %d too large, using MaxBufSize",
1899 pvolume_info->rsize));
1900 cifs_sb->rsize = CIFSMaxBufSize;
1901 } else if ((pvolume_info->rsize) &&
1902 (pvolume_info->rsize <= CIFSMaxBufSize))
1903 cifs_sb->rsize = pvolume_info->rsize;
1904 else /* default */
1905 cifs_sb->rsize = CIFSMaxBufSize;
1906
1907 if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1908 cERROR(1, ("wsize %d too large, using 4096 instead",
1909 pvolume_info->wsize));
1910 cifs_sb->wsize = 4096;
1911 } else if (pvolume_info->wsize)
1912 cifs_sb->wsize = pvolume_info->wsize;
1913 else
1914 cifs_sb->wsize = min_t(const int,
1915 PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1916 127*1024);
1917 /* old default of CIFSMaxBufSize was too small now
1918 that SMB Write2 can send multiple pages in kvec.
1919 RFC1001 does not describe what happens when frame
1920 bigger than 128K is sent so use that as max in
1921 conjunction with 52K kvec constraint on arch with 4K
1922 page size */
1923
1924 if (cifs_sb->rsize < 2048) {
1925 cifs_sb->rsize = 2048;
1926 /* Windows ME may prefer this */
1927 cFYI(1, ("readsize set to minimum: 2048"));
1928 }
1929 /* calculate prepath */
1930 cifs_sb->prepath = pvolume_info->prepath;
1931 if (cifs_sb->prepath) {
1932 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1933 /* we can not convert the / to \ in the path
1934 separators in the prefixpath yet because we do not
1935 know (until reset_cifs_unix_caps is called later)
1936 whether POSIX PATH CAP is available. We normalize
1937 the / to \ after reset_cifs_unix_caps is called */
1938 pvolume_info->prepath = NULL;
1939 } else
1940 cifs_sb->prepathlen = 0;
1941 cifs_sb->mnt_uid = pvolume_info->linux_uid;
1942 cifs_sb->mnt_gid = pvolume_info->linux_gid;
1943 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
1944 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
1945 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
1946 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
1947
1948 if (pvolume_info->noperm)
1949 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1950 if (pvolume_info->setuids)
1951 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1952 if (pvolume_info->server_ino)
1953 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1954 if (pvolume_info->remap)
1955 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1956 if (pvolume_info->no_xattr)
1957 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1958 if (pvolume_info->sfu_emul)
1959 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1960 if (pvolume_info->nobrl)
1961 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1962 if (pvolume_info->cifs_acl)
1963 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1964 if (pvolume_info->override_uid)
1965 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1966 if (pvolume_info->override_gid)
1967 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
1968 if (pvolume_info->dynperm)
1969 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
1970 if (pvolume_info->direct_io) {
1971 cFYI(1, ("mounting share using direct i/o"));
1972 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1973 }
1974
1975 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
1976 cERROR(1, ("mount option dynperm ignored if cifsacl "
1977 "mount option supported"));
1978}
1979
1894int 1980int
1895cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 1981cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1896 char *mount_data, const char *devname) 1982 char *mount_data, const char *devname)
@@ -1996,9 +2082,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1996 goto out; 2082 goto out;
1997 } 2083 }
1998 2084
1999 if (srvTcp) { 2085 if (!srvTcp) { /* create socket */
2000 cFYI(1, ("Existing tcp session with server found"));
2001 } else { /* create socket */
2002 if (volume_info.port) 2086 if (volume_info.port)
2003 sin_server.sin_port = htons(volume_info.port); 2087 sin_server.sin_port = htons(volume_info.port);
2004 else 2088 else
@@ -2074,7 +2158,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2074 cFYI(1, ("Existing smb sess found (status=%d)", 2158 cFYI(1, ("Existing smb sess found (status=%d)",
2075 pSesInfo->status)); 2159 pSesInfo->status));
2076 down(&pSesInfo->sesSem); 2160 down(&pSesInfo->sesSem);
2077 if (pSesInfo->status == CifsNeedReconnect) { 2161 if (pSesInfo->need_reconnect) {
2078 cFYI(1, ("Session needs reconnect")); 2162 cFYI(1, ("Session needs reconnect"));
2079 rc = cifs_setup_session(xid, pSesInfo, 2163 rc = cifs_setup_session(xid, pSesInfo,
2080 cifs_sb->local_nls); 2164 cifs_sb->local_nls);
@@ -2124,146 +2208,59 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2124 2208
2125 /* search for existing tcon to this server share */ 2209 /* search for existing tcon to this server share */
2126 if (!rc) { 2210 if (!rc) {
2127 if (volume_info.rsize > CIFSMaxBufSize) { 2211 setup_cifs_sb(&volume_info, cifs_sb);
2128 cERROR(1, ("rsize %d too large, using MaxBufSize",
2129 volume_info.rsize));
2130 cifs_sb->rsize = CIFSMaxBufSize;
2131 } else if ((volume_info.rsize) &&
2132 (volume_info.rsize <= CIFSMaxBufSize))
2133 cifs_sb->rsize = volume_info.rsize;
2134 else /* default */
2135 cifs_sb->rsize = CIFSMaxBufSize;
2136
2137 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2138 cERROR(1, ("wsize %d too large, using 4096 instead",
2139 volume_info.wsize));
2140 cifs_sb->wsize = 4096;
2141 } else if (volume_info.wsize)
2142 cifs_sb->wsize = volume_info.wsize;
2143 else
2144 cifs_sb->wsize =
2145 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2146 127*1024);
2147 /* old default of CIFSMaxBufSize was too small now
2148 that SMB Write2 can send multiple pages in kvec.
2149 RFC1001 does not describe what happens when frame
2150 bigger than 128K is sent so use that as max in
2151 conjunction with 52K kvec constraint on arch with 4K
2152 page size */
2153
2154 if (cifs_sb->rsize < 2048) {
2155 cifs_sb->rsize = 2048;
2156 /* Windows ME may prefer this */
2157 cFYI(1, ("readsize set to minimum: 2048"));
2158 }
2159 /* calculate prepath */
2160 cifs_sb->prepath = volume_info.prepath;
2161 if (cifs_sb->prepath) {
2162 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2163 /* we can not convert the / to \ in the path
2164 separators in the prefixpath yet because we do not
2165 know (until reset_cifs_unix_caps is called later)
2166 whether POSIX PATH CAP is available. We normalize
2167 the / to \ after reset_cifs_unix_caps is called */
2168 volume_info.prepath = NULL;
2169 } else
2170 cifs_sb->prepathlen = 0;
2171 cifs_sb->mnt_uid = volume_info.linux_uid;
2172 cifs_sb->mnt_gid = volume_info.linux_gid;
2173 cifs_sb->mnt_file_mode = volume_info.file_mode;
2174 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
2175 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2176 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2177
2178 if (volume_info.noperm)
2179 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2180 if (volume_info.setuids)
2181 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2182 if (volume_info.server_ino)
2183 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2184 if (volume_info.remap)
2185 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2186 if (volume_info.no_xattr)
2187 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2188 if (volume_info.sfu_emul)
2189 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2190 if (volume_info.nobrl)
2191 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2192 if (volume_info.cifs_acl)
2193 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2194 if (volume_info.override_uid)
2195 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2196 if (volume_info.override_gid)
2197 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2198 if (volume_info.dynperm)
2199 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2200 if (volume_info.direct_io) {
2201 cFYI(1, ("mounting share using direct i/o"));
2202 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2203 }
2204
2205 if ((volume_info.cifs_acl) && (volume_info.dynperm))
2206 cERROR(1, ("mount option dynperm ignored if cifsacl "
2207 "mount option supported"));
2208 2212
2209 tcon = 2213 tcon =
2210 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, 2214 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2211 volume_info.username); 2215 volume_info.username);
2212 if (tcon) { 2216 if (tcon) {
2213 cFYI(1, ("Found match on UNC path")); 2217 cFYI(1, ("Found match on UNC path"));
2214 /* we can have only one retry value for a connection
2215 to a share so for resources mounted more than once
2216 to the same server share the last value passed in
2217 for the retry flag is used */
2218 tcon->retry = volume_info.retry;
2219 tcon->nocase = volume_info.nocase;
2220 tcon->local_lease = volume_info.local_lease;
2221 if (tcon->seal != volume_info.seal) 2218 if (tcon->seal != volume_info.seal)
2222 cERROR(1, ("transport encryption setting " 2219 cERROR(1, ("transport encryption setting "
2223 "conflicts with existing tid")); 2220 "conflicts with existing tid"));
2224 } else { 2221 } else {
2225 tcon = tconInfoAlloc(); 2222 tcon = tconInfoAlloc();
2226 if (tcon == NULL) 2223 if (tcon == NULL) {
2227 rc = -ENOMEM; 2224 rc = -ENOMEM;
2228 else { 2225 goto mount_fail_check;
2229 /* check for null share name ie connecting to 2226 }
2230 * dfs root */ 2227
2231 2228 /* check for null share name ie connect to dfs root */
2232 /* BB check if this works for exactly length 2229
2233 * three strings */ 2230 /* BB check if works for exactly length 3 strings */
2234 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2231 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2235 && (strchr(volume_info.UNC + 3, '/') == 2232 && (strchr(volume_info.UNC + 3, '/') == NULL)) {
2236 NULL)) { 2233 /* rc = connect_to_dfs_path(...) */
2237/* rc = connect_to_dfs_path(xid, pSesInfo, 2234 cFYI(1, ("DFS root not supported"));
2238 "", cifs_sb->local_nls, 2235 rc = -ENODEV;
2239 cifs_sb->mnt_cifs_flags & 2236 goto mount_fail_check;
2240 CIFS_MOUNT_MAP_SPECIAL_CHR);*/ 2237 } else {
2241 cFYI(1, ("DFS root not supported")); 2238 /* BB Do we need to wrap sesSem around
2242 rc = -ENODEV; 2239 * this TCon call and Unix SetFS as
2243 goto out; 2240 * we do on SessSetup and reconnect? */
2244 } else { 2241 rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
2245 /* BB Do we need to wrap sesSem around 2242 tcon, cifs_sb->local_nls);
2246 * this TCon call and Unix SetFS as 2243 cFYI(1, ("CIFS Tcon rc = %d", rc));
2247 * we do on SessSetup and reconnect? */ 2244 if (volume_info.nodfs) {
2248 rc = CIFSTCon(xid, pSesInfo, 2245 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2249 volume_info.UNC, 2246 cFYI(1, ("DFS disabled (%d)",
2250 tcon, cifs_sb->local_nls); 2247 tcon->Flags));
2251 cFYI(1, ("CIFS Tcon rc = %d", rc));
2252 if (volume_info.nodfs) {
2253 tcon->Flags &=
2254 ~SMB_SHARE_IS_IN_DFS;
2255 cFYI(1, ("DFS disabled (%d)",
2256 tcon->Flags));
2257 }
2258 }
2259 if (!rc) {
2260 atomic_inc(&pSesInfo->inUse);
2261 tcon->retry = volume_info.retry;
2262 tcon->nocase = volume_info.nocase;
2263 tcon->seal = volume_info.seal;
2264 } 2248 }
2265 } 2249 }
2250 if (!rc) {
2251 atomic_inc(&pSesInfo->inUse);
2252 tcon->seal = volume_info.seal;
2253 } else
2254 goto mount_fail_check;
2266 } 2255 }
2256
2257 /* we can have only one retry value for a connection
2258 to a share so for resources mounted more than once
2259 to the same server share the last value passed in
2260 for the retry flag is used */
2261 tcon->retry = volume_info.retry;
2262 tcon->nocase = volume_info.nocase;
2263 tcon->local_lease = volume_info.local_lease;
2267 } 2264 }
2268 if (pSesInfo) { 2265 if (pSesInfo) {
2269 if (pSesInfo->capabilities & CAP_LARGE_FILES) { 2266 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
@@ -2276,6 +2273,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2276 sb->s_time_gran = 100; 2273 sb->s_time_gran = 100;
2277 2274
2278/* on error free sesinfo and tcon struct if needed */ 2275/* on error free sesinfo and tcon struct if needed */
2276mount_fail_check:
2279 if (rc) { 2277 if (rc) {
2280 /* if session setup failed, use count is zero but 2278 /* if session setup failed, use count is zero but
2281 we still need to free cifsd thread */ 2279 we still need to free cifsd thread */
@@ -3518,6 +3516,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3518 /* above now done in SendReceive */ 3516 /* above now done in SendReceive */
3519 if ((rc == 0) && (tcon != NULL)) { 3517 if ((rc == 0) && (tcon != NULL)) {
3520 tcon->tidStatus = CifsGood; 3518 tcon->tidStatus = CifsGood;
3519 tcon->need_reconnect = false;
3521 tcon->tid = smb_buffer_response->Tid; 3520 tcon->tid = smb_buffer_response->Tid;
3522 bcc_ptr = pByteArea(smb_buffer_response); 3521 bcc_ptr = pByteArea(smb_buffer_response);
3523 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 3522 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -3746,6 +3745,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3746 cFYI(1, ("CIFS Session Established successfully")); 3745 cFYI(1, ("CIFS Session Established successfully"));
3747 spin_lock(&GlobalMid_Lock); 3746 spin_lock(&GlobalMid_Lock);
3748 pSesInfo->status = CifsGood; 3747 pSesInfo->status = CifsGood;
3748 pSesInfo->need_reconnect = false;
3749 spin_unlock(&GlobalMid_Lock); 3749 spin_unlock(&GlobalMid_Lock);
3750 } 3750 }
3751 3751
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index ead1a3bb0256..1540adaa593d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -493,7 +493,7 @@ int cifs_close(struct inode *inode, struct file *file)
493 if (pTcon) { 493 if (pTcon) {
494 /* no sense reconnecting to close a file that is 494 /* no sense reconnecting to close a file that is
495 already closed */ 495 already closed */
496 if (pTcon->tidStatus != CifsNeedReconnect) { 496 if (!pTcon->need_reconnect) {
497 timeout = 2; 497 timeout = 2;
498 while ((atomic_read(&pSMBFile->wrtPending) != 0) 498 while ((atomic_read(&pSMBFile->wrtPending) != 0)
499 && (timeout <= 2048)) { 499 && (timeout <= 2048)) {