diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 40 | ||||
-rw-r--r-- | fs/cifs/connect.c | 262 | ||||
-rw-r--r-- | fs/cifs/file.c | 2 |
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 | ||
124 | struct TCP_Server_Info { | 124 | struct 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 | */ |
196 | struct cifsSesInfo { | 198 | struct 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) { | 832 | session_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 | ||
1894 | static 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 | |||
1894 | int | 1980 | int |
1895 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 1981 | cifs_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 */ |
2276 | mount_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)) { |