Signed-off-by: Stefan Metzmacher <metze@xxxxxxxxx> --- fs/cifs/cifssmb.c | 117 +++++----------------------------------------- fs/cifs/connect.c | 7 +++ 2 files changed, 19 insertions(+), 105 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 412d141e1adc..2cf74028ce70 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -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 diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 67d2ad330f33..e920335384d7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -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); -- 2.17.1