Commit 565674d6 authored by Stefan Metzmacher's avatar Stefan Metzmacher Committed by Steve French
Browse files

cifs: merge __{cifs,smb2}_reconnect[_tcon]() into cifs_tree_connect()



They were identical execpt to CIFSTCon() vs. SMB2_tcon().
These are also available via ops->tree_connect().

Signed-off-by: default avatarStefan Metzmacher <metze@samba.org>
Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 1a0e7f7c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -272,6 +272,9 @@ extern void cifs_move_llist(struct list_head *source, struct list_head *dest);
extern void cifs_free_llist(struct list_head *llist);
extern void cifs_del_lock_waiters(struct cifsLockInfo *lock);

extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon,
			     const struct nls_table *nlsc);

extern int cifs_negotiate_protocol(const unsigned int xid,
				   struct cifs_ses *ses);
extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
+1 −111
Original line number Diff line number Diff line
@@ -124,116 +124,6 @@ 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 TCP_Server_Info *server = tcon->ses->server;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (!tcon->dfs_path) {
		if (tcon->ipc) {
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
				  server->hostname);
			rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
		} else {
			rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
		}
		goto out;
	}

	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
	if (rc)
		goto out;

	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);
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &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: %.*s doesn't match %.*s\n",
				 __func__,
				 (int)dfs_host_len, dfs_host,
				 (int)tcp_host_len, tcp_host);

			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;
			}

			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 = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
		} else {
			scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len,
				  share);
			rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
			if (!rc) {
				rc = update_super_prepath(tcon, prefix,
							  prefix_len);
				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);
out:
	kfree(tree);
	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 */
static int
cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
@@ -338,7 +228,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
	}

	cifs_mark_open_files_invalid(tcon);
	rc = __cifs_reconnect_tcon(nls_codepage, tcon);
	rc = cifs_tree_connect(0, tcon, nls_codepage);
	mutex_unlock(&ses->session_mutex);
	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);

+100 −0
Original line number Diff line number Diff line
@@ -5532,3 +5532,103 @@ cifs_prune_tlinks(struct work_struct *work)
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
				TLINK_IDLE_EXPIRE);
}

#ifdef CONFIG_CIFS_DFS_UPCALL
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	int rc;
	struct TCP_Server_Info *server = tcon->ses->server;
	const struct smb_version_operations *ops = server->ops;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (!tcon->dfs_path) {
		if (tcon->ipc) {
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
			rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
		}
		goto out;
	}

	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
	if (rc)
		goto out;

	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);
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &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: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
				 dfs_host, (int)tcp_host_len, tcp_host);

			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;
			}

			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 = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
			scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, share);
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
			if (!rc) {
				rc = update_super_prepath(tcon, prefix, prefix_len);
				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);
out:
	kfree(tree);
	return rc;
}
#else
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	const struct smb_version_operations *ops = tcon->ses->server->ops;

	return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
}
#endif
+1 −112
Original line number Diff line number Diff line
@@ -152,117 +152,6 @@ out:
	return;
}

#ifdef CONFIG_CIFS_DFS_UPCALL
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;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (!tcon->dfs_path) {
		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;
	}

	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
	if (rc)
		goto out;

	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);
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &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: %.*s doesn't match %.*s\n",
				 __func__,
				 (int)dfs_host_len, dfs_host,
				 (int)tcp_host_len, tcp_host);

			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;
			}

			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;
	}

	if (!rc) {
		if (it)
			rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1,
							    it);
		else
			rc = -ENOENT;
	}
	dfs_cache_free_tgts(&tl);
out:
	kfree(tree);
	return rc;
}
#else
static inline int __smb2_reconnect(const struct nls_table *nlsc,
				   struct cifs_tcon *tcon)
{
	return SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
}
#endif

static int
smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
	       struct TCP_Server_Info *server)
@@ -409,7 +298,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
	if (tcon->use_persistent)
		tcon->need_reopen_files = true;

	rc = __smb2_reconnect(nls_codepage, tcon);
	rc = cifs_tree_connect(0, tcon, nls_codepage);
	mutex_unlock(&tcon->ses->session_mutex);

	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);