aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2pdu.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2011-12-27 07:23:34 -0500
committerPavel Shilovsky <pshilovsky@samba.org>2012-07-24 13:54:59 -0400
commitaa24d1e9692411e605084938ced6b160f92df454 (patch)
tree399446513c2437af67ca8ed065ba16f272715bb4 /fs/cifs/smb2pdu.c
parentfaaf946a7d5b79194358437150f34ab4c66bfe21 (diff)
CIFS: Process reconnects for SMB2 shares
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r--fs/cifs/smb2pdu.c127
1 files changed, 126 insertions, 1 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 1bf037ec5a9d..48c04b2832e2 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -127,7 +127,132 @@ static int
127smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) 127smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
128{ 128{
129 int rc = 0; 129 int rc = 0;
130 /* BB add missing code here */ 130 struct nls_table *nls_codepage;
131 struct cifs_ses *ses;
132 struct TCP_Server_Info *server;
133
134 /*
135 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
136 * check for tcp and smb session status done differently
137 * for those three - in the calling routine.
138 */
139 if (tcon == NULL)
140 return rc;
141
142 if (smb2_command == SMB2_TREE_CONNECT)
143 return rc;
144
145 if (tcon->tidStatus == CifsExiting) {
146 /*
147 * only tree disconnect, open, and write,
148 * (and ulogoff which does not have tcon)
149 * are allowed as we start force umount.
150 */
151 if ((smb2_command != SMB2_WRITE) &&
152 (smb2_command != SMB2_CREATE) &&
153 (smb2_command != SMB2_TREE_DISCONNECT)) {
154 cFYI(1, "can not send cmd %d while umounting",
155 smb2_command);
156 return -ENODEV;
157 }
158 }
159 if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
160 (!tcon->ses->server))
161 return -EIO;
162
163 ses = tcon->ses;
164 server = ses->server;
165
166 /*
167 * Give demultiplex thread up to 10 seconds to reconnect, should be
168 * greater than cifs socket timeout which is 7 seconds
169 */
170 while (server->tcpStatus == CifsNeedReconnect) {
171 /*
172 * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
173 * here since they are implicitly done when session drops.
174 */
175 switch (smb2_command) {
176 /*
177 * BB Should we keep oplock break and add flush to exceptions?
178 */
179 case SMB2_TREE_DISCONNECT:
180 case SMB2_CANCEL:
181 case SMB2_CLOSE:
182 case SMB2_OPLOCK_BREAK:
183 return -EAGAIN;
184 }
185
186 wait_event_interruptible_timeout(server->response_q,
187 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
188
189 /* are we still trying to reconnect? */
190 if (server->tcpStatus != CifsNeedReconnect)
191 break;
192
193 /*
194 * on "soft" mounts we wait once. Hard mounts keep
195 * retrying until process is killed or server comes
196 * back on-line
197 */
198 if (!tcon->retry) {
199 cFYI(1, "gave up waiting on reconnect in smb_init");
200 return -EHOSTDOWN;
201 }
202 }
203
204 if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
205 return rc;
206
207 nls_codepage = load_nls_default();
208
209 /*
210 * need to prevent multiple threads trying to simultaneously reconnect
211 * the same SMB session
212 */
213 mutex_lock(&tcon->ses->session_mutex);
214 rc = cifs_negotiate_protocol(0, tcon->ses);
215 if (!rc && tcon->ses->need_reconnect)
216 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
217
218 if (rc || !tcon->need_reconnect) {
219 mutex_unlock(&tcon->ses->session_mutex);
220 goto out;
221 }
222
223 cifs_mark_open_files_invalid(tcon);
224 rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
225 mutex_unlock(&tcon->ses->session_mutex);
226 cFYI(1, "reconnect tcon rc = %d", rc);
227 if (rc)
228 goto out;
229 atomic_inc(&tconInfoReconnectCount);
230 /*
231 * BB FIXME add code to check if wsize needs update due to negotiated
232 * smb buffer size shrinking.
233 */
234out:
235 /*
236 * Check if handle based operation so we know whether we can continue
237 * or not without returning to caller to reset file handle.
238 */
239 /*
240 * BB Is flush done by server on drop of tcp session? Should we special
241 * case it and skip above?
242 */
243 switch (smb2_command) {
244 case SMB2_FLUSH:
245 case SMB2_READ:
246 case SMB2_WRITE:
247 case SMB2_LOCK:
248 case SMB2_IOCTL:
249 case SMB2_QUERY_DIRECTORY:
250 case SMB2_CHANGE_NOTIFY:
251 case SMB2_QUERY_INFO:
252 case SMB2_SET_INFO:
253 return -EAGAIN;
254 }
255 unload_nls(nls_codepage);
131 return rc; 256 return rc;
132} 257}
133 258