@@ -128,114 +128,22 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
static int
cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
{
- int rc;
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct nls_table *nls_codepage;
- int retries;
-
- /*
- * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
- * tcp and smb session status done differently for those three - in the
- * calling routine
- */
- if (!tcon)
- return 0;
-
- ses = tcon->ses;
- server = ses->server;
+ struct cifs_tcon_reconnect_params params = {
+ .skip_reconnect = false,
+ };
/*
* only tree disconnect, open, and write, (and ulogoff which does not
* have tcon) are allowed as we start force umount
*/
- if (tcon->tidStatus == CifsExiting) {
- if (smb_command != SMB_COM_WRITE_ANDX &&
- smb_command != SMB_COM_OPEN_ANDX &&
- smb_command != SMB_COM_TREE_DISCONNECT) {
- cifs_dbg(FYI, "can not send cmd %d while umounting\n",
- smb_command);
- return -ENODEV;
- }
- }
-
- retries = server->nr_targets;
-
- /*
- * Give demultiplex thread up to 10 seconds to each target available for
- * reconnect -- should be greater than cifs socket timeout which is 7
- * seconds.
- */
- while (server->tcpStatus == CifsNeedReconnect) {
- rc = wait_event_interruptible_timeout(server->response_q,
- (server->tcpStatus != CifsNeedReconnect),
- 10 * HZ);
- if (rc < 0) {
- cifs_dbg(FYI, "%s: aborting reconnect due to a received"
- " signal by the process\n", __func__);
- return -ERESTARTSYS;
- }
-
- /* are we still trying to reconnect? */
- if (server->tcpStatus != CifsNeedReconnect)
- break;
-
- if (retries && --retries)
- continue;
-
- /*
- * on "soft" mounts we wait once. Hard mounts keep
- * retrying until process is killed or server comes
- * back on-line
- */
- if (!tcon->retry) {
- cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
- return -EHOSTDOWN;
- }
- retries = server->nr_targets;
- }
-
- if (!ses->need_reconnect && !tcon->need_reconnect)
- return 0;
-
- nls_codepage = load_nls_default();
-
- /*
- * need to prevent multiple threads trying to simultaneously
- * reconnect the same SMB session
- */
- mutex_lock(&ses->session_mutex);
-
- /*
- * Recheck after acquire mutex. If another thread is negotiating
- * and the server never sends an answer the socket will be closed
- * and tcpStatus set to reconnect.
- */
- rc = cifs_connect_session_locked(0, ses,
- nls_codepage,
- tcon->retry);
- /* do we need to reconnect tcon? */
- if (rc || !tcon->need_reconnect) {
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
-
- cifs_mark_open_files_invalid(tcon);
- rc = cifs_tree_connect(0, tcon, nls_codepage);
- mutex_unlock(&ses->session_mutex);
- cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
-
- if (rc) {
- printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
- goto out;
+ switch (smb_command) {
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_OPEN_ANDX:
+ case SMB_COM_TREE_DISCONNECT:
+ params.exit_nodev = true;
+ break;
}
- atomic_inc(&tconInfoReconnectCount);
-
- /* tell server Unix caps we support */
- if (cap_unix(ses))
- reset_cifs_unix_caps(0, tcon, NULL, NULL);
-
/*
* Removed call to reopen open files here. It is safer (and faster) to
* reopen files one at a time as needed in read and write.
@@ -243,7 +151,6 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
* FIXME: what about file locks? don't we need to reclaim them ASAP?
*/
-out:
/*
* Check if handle based operation so we know whether we can continue
* or not without returning to caller to reset file handle
@@ -254,11 +161,11 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
case SMB_COM_CLOSE:
case SMB_COM_FIND_CLOSE2:
case SMB_COM_LOCKING_ANDX:
- rc = -EAGAIN;
+ params.late_eagain = true;
+ break;
}
- unload_nls(nls_codepage);
- return rc;
+ return cifs_tcon_reconnect(tcon, ¶ms);
}
/* Allocate and return pointer to an SMB request buffer, and set basic
@@ -5510,6 +5510,13 @@ cifs_tcon_reconnect(struct cifs_tcon *tcon,
goto out;
}
+ /*
+ * tell server Unix caps we support,
+ * note it's a noop for SMB2.
+ */
+ if (cap_unix(ses))
+ reset_cifs_unix_caps(0, tcon, NULL, NULL);
+
if (params->start_timer)
mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
Signed-off-by: Stefan Metzmacher <metze@samba.org> --- fs/cifs/cifssmb.c | 117 +++++----------------------------------------- fs/cifs/connect.c | 7 +++ 2 files changed, 19 insertions(+), 105 deletions(-)