diff options
author | Paulo Alcantara <paulo@paulo.ac> | 2018-11-20 15:16:36 -0200 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2018-12-28 10:13:11 -0600 |
commit | 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d (patch) | |
tree | 0c6b6495cbf7e30c3f7716234acd7f80cc821548 /fs/cifs | |
parent | 08744015492fec5a30ab8e2779601ae2b1a5e431 (diff) |
cifs: Always resolve hostname before reconnecting
In case a hostname resolves to a different IP address (e.g. long
running mounts), make sure to resolve it every time prior to calling
generic_ip_connect() in reconnect.
Suggested-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Paulo Alcantara <palcantara@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/connect.c | 84 |
1 files changed, 52 insertions, 32 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 80ef165d5f33..69b9d5606eba 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -325,6 +325,53 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, const char *devname, bool is_smb3); static char *extract_hostname(const char *unc); +/* + * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may + * get their ip addresses changed at some point. + * + * This should be called with server->srv_mutex held. + */ +#ifdef CONFIG_CIFS_DFS_UPCALL +static int reconn_set_ipaddr(struct TCP_Server_Info *server) +{ + int rc; + int len; + char *unc, *ipaddr = NULL; + + if (!server->hostname) + return -EINVAL; + + len = strlen(server->hostname) + 3; + + unc = kmalloc(len, GFP_KERNEL); + if (!unc) { + cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); + return -ENOMEM; + } + snprintf(unc, len, "\\\\%s", server->hostname); + + rc = dns_resolve_server_name_to_ip(unc, &ipaddr); + kfree(unc); + + if (rc < 0) { + cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", + __func__, server->hostname, rc); + return rc; + } + + rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, + strlen(ipaddr)); + kfree(ipaddr); + + return !rc ? -1 : 0; +} +#else +static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) +{ + return 0; +} +#endif + #ifdef CONFIG_CIFS_DFS_UPCALL struct super_cb_data { struct TCP_Server_Info *server; @@ -366,10 +413,6 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server, struct dfs_cache_tgt_iterator **tgt_it) { const char *name; - int rc; - char *ipaddr = NULL; - char *unc; - int len; if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list || !server->nr_targets) @@ -393,34 +436,6 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server, if (!server->hostname) { cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n", __func__, -ENOMEM); - return; - } - - len = strlen(server->hostname) + 3; - - unc = kmalloc(len, GFP_KERNEL); - if (!unc) { - cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); - return; - } - snprintf(unc, len, "\\\\%s", server->hostname); - - rc = dns_resolve_server_name_to_ip(unc, &ipaddr); - kfree(unc); - - if (rc < 0) { - cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n", - __func__, server->hostname, rc); - return; - } - - rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, - strlen(ipaddr)); - kfree(ipaddr); - - if (!rc) { - cifs_dbg(FYI, "%s: failed to get ipaddr out of hostname\n", - __func__); } } @@ -567,6 +582,11 @@ cifs_reconnect(struct TCP_Server_Info *server) reconn_inval_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); #endif + rc = reconn_set_ipaddr(server); + if (rc) { + cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", + __func__, rc); + } mutex_unlock(&server->srv_mutex); msleep(3000); } else { |