Commit 08744015 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French

cifs: Add support for failover in cifs_reconnect_tcon()

After a successful failover, the cifs_reconnect_tcon() function will
make sure to reconnect every tcon to new target server.

Same as previous commit but for SMB1 codepath.
Signed-off-by: default avatarPaulo Alcantara <palcantara@suse.de>
Reviewed-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent a3a53b76
...@@ -44,6 +44,9 @@ ...@@ -44,6 +44,9 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#include "fscache.h" #include "fscache.h"
#include "smbdirect.h" #include "smbdirect.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
static struct { static struct {
...@@ -118,6 +121,77 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) ...@@ -118,6 +121,77 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
*/ */
} }
#ifdef CONFIG_CIFS_DFS_UPCALL
static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
struct cifs_tcon *tcon)
{
int rc;
struct dfs_cache_tgt_list tl;
struct dfs_cache_tgt_iterator *it = NULL;
char tree[MAX_TREE_SIZE + 1];
const char *tcp_host;
size_t tcp_host_len;
const char *dfs_host;
size_t dfs_host_len;
if (tcon->ipc) {
snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
tcon->ses->server->hostname);
return CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
}
if (!tcon->dfs_path)
return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
if (rc)
return rc;
extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
&tcp_host_len);
for (it = dfs_cache_get_tgt_iterator(&tl); it;
it = dfs_cache_get_next_tgt(&tl, it)) {
const char *tgt = dfs_cache_get_tgt_name(it);
extract_unc_hostname(tgt, &dfs_host, &dfs_host_len);
if (dfs_host_len != tcp_host_len
|| strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
cifs_dbg(FYI, "%s: skipping %.*s, doesn't match %.*s",
__func__,
(int)dfs_host_len, dfs_host,
(int)tcp_host_len, tcp_host);
continue;
}
snprintf(tree, sizeof(tree), "\\%s", tgt);
rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
if (!rc)
break;
if (rc == -EREMOTE)
break;
}
if (!rc) {
if (it)
rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1,
it);
else
rc = -ENOENT;
}
dfs_cache_free_tgts(&tl);
return rc;
}
#else
static inline int __cifs_reconnect_tcon(const struct nls_table *nlsc,
struct cifs_tcon *tcon)
{
return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
}
#endif
/* reconnect the socket, tcon, and smb session if needed */ /* reconnect the socket, tcon, and smb session if needed */
static int static int
cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
...@@ -126,6 +200,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -126,6 +200,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
struct cifs_ses *ses; struct cifs_ses *ses;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct nls_table *nls_codepage; struct nls_table *nls_codepage;
int retries;
/* /*
* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
...@@ -152,9 +227,12 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -152,9 +227,12 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
} }
} }
retries = server->nr_targets;
/* /*
* Give demultiplex thread up to 10 seconds to reconnect, should be * Give demultiplex thread up to 10 seconds to each target available for
* greater than cifs socket timeout which is 7 seconds * reconnect -- should be greater than cifs socket timeout which is 7
* seconds.
*/ */
while (server->tcpStatus == CifsNeedReconnect) { while (server->tcpStatus == CifsNeedReconnect) {
rc = wait_event_interruptible_timeout(server->response_q, rc = wait_event_interruptible_timeout(server->response_q,
...@@ -170,6 +248,9 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -170,6 +248,9 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
if (server->tcpStatus != CifsNeedReconnect) if (server->tcpStatus != CifsNeedReconnect)
break; break;
if (--retries)
continue;
/* /*
* on "soft" mounts we wait once. Hard mounts keep * on "soft" mounts we wait once. Hard mounts keep
* retrying until process is killed or server comes * retrying until process is killed or server comes
...@@ -179,6 +260,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -179,6 +260,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n"); cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
return -EHOSTDOWN; return -EHOSTDOWN;
} }
retries = server->nr_targets;
} }
if (!ses->need_reconnect && !tcon->need_reconnect) if (!ses->need_reconnect && !tcon->need_reconnect)
...@@ -214,7 +296,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) ...@@ -214,7 +296,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
} }
cifs_mark_open_files_invalid(tcon); cifs_mark_open_files_invalid(tcon);
rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); rc = __cifs_reconnect_tcon(nls_codepage, tcon);
mutex_unlock(&ses->session_mutex); mutex_unlock(&ses->session_mutex);
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment