cifs: handle hostnames that resolve to same ip in failover
[linux-2.6-microblaze.git] / fs / cifs / smb2pdu.c
index b30aa3c..cabc19f 100644 (file)
@@ -160,6 +160,7 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
                            struct cifs_tcon *tcon)
 {
        int rc;
+       struct TCP_Server_Info *server = tcon->ses->server;
        struct dfs_cache_tgt_list tl;
        struct dfs_cache_tgt_iterator *it = NULL;
        char *tree;
@@ -172,15 +173,15 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
        if (!tree)
                return -ENOMEM;
 
-       if (tcon->ipc) {
-               scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
-                         tcon->ses->server->hostname);
-               rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
-               goto out;
-       }
-
        if (!tcon->dfs_path) {
-               rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+               if (tcon->ipc) {
+                       scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
+                                 server->hostname);
+                       rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               } else {
+                       rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon,
+                                      nlsc);
+               }
                goto out;
        }
 
@@ -188,13 +189,13 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
        if (rc)
                goto out;
 
-       extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
-                            &tcp_host_len);
+       extract_unc_hostname(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 *share, *prefix;
                size_t share_len, prefix_len;
+               bool target_match;
 
                rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix,
                                             &prefix_len);
@@ -208,19 +209,38 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
 
                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",
+                       cifs_dbg(FYI, "%s: %.*s doesn't match %.*s",
                                 __func__,
                                 (int)dfs_host_len, dfs_host,
                                 (int)tcp_host_len, tcp_host);
-                       continue;
-               }
 
-               scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, share);
+                       rc = match_target_ip(server, dfs_host, dfs_host_len,
+                                            &target_match);
+                       if (rc) {
+                               cifs_dbg(VFS, "%s: failed to match target ip: %d\n",
+                                        __func__, rc);
+                               break;
+                       }
 
-               rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
-               if (!rc) {
-                       rc = update_super_prepath(tcon, prefix, prefix_len);
-                       break;
+                       if (!target_match) {
+                               cifs_dbg(FYI, "%s: skipping target\n", __func__);
+                               continue;
+                       }
+               }
+
+               if (tcon->ipc) {
+                       scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$",
+                                 (int)share_len, share);
+                       rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               } else {
+                       scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len,
+                                 share);
+                       rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+                       if (!rc) {
+                               rc = update_super_prepath(tcon, prefix,
+                                                         prefix_len);
+                               break;
+                       }
                }
                if (rc == -EREMOTE)
                        break;