Commit 83328585 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

cifs: refresh root referrals



Also refresh cached root referrals so the other cached referrals may
have a better chance to have a working root server to issue the
referrals on.

Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 6916881f
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -1346,14 +1346,15 @@ static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cach
/* Refresh dfs referral of tcon and mark it for reconnect if needed */
static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_refresh)
{
	struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
	struct cifs_ses *ses = CIFS_DFS_ROOT_SES(tcon->ses);
	struct cache_entry *ce;
	struct cifs_tcon *ipc = ses->tcon_ipc;
	struct dfs_info3_param *refs = NULL;
	int numrefs = 0;
	bool needs_refresh = false;
	struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
	int rc = 0;
	struct cache_entry *ce;
	unsigned int xid;
	int numrefs = 0;
	int rc = 0;

	xid = get_xid();

@@ -1372,6 +1373,14 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
		goto out;
	}

	spin_lock(&ipc->tc_lock);
	if (ses->ses_status != SES_GOOD || ipc->status != TID_GOOD) {
		spin_unlock(&ipc->tc_lock);
		cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", __func__);
		goto out;
	}
	spin_unlock(&ipc->tc_lock);

	rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
	if (!rc) {
		/* Create or update a cache entry with the new referral */
@@ -1457,9 +1466,9 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
static void refresh_cache_worker(struct work_struct *work)
{
	struct TCP_Server_Info *server;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon, *ntcon;
	struct list_head tcons;
	struct cifs_ses *ses;

	INIT_LIST_HEAD(&tcons);

@@ -1469,23 +1478,15 @@ static void refresh_cache_worker(struct work_struct *work)
			continue;

		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
			struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(ses);

			spin_lock(&root_ses->ses_lock);
			if (root_ses->ses_status != SES_GOOD) {
				spin_unlock(&root_ses->ses_lock);
				continue;
			if (ses->tcon_ipc) {
				ses->ses_count++;
				list_add_tail(&ses->tcon_ipc->ulist, &tcons);
			}
			spin_unlock(&root_ses->ses_lock);

			list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
				spin_lock(&tcon->tc_lock);
				if (!tcon->ipc && tcon->status != TID_NEW &&
				    tcon->status != TID_NEED_TCON) {
				if (!tcon->ipc) {
					tcon->tc_count++;
					list_add_tail(&tcon->ulist, &tcons);
				}
				spin_unlock(&tcon->tc_lock);
			}
		}
	}
@@ -1501,6 +1502,9 @@ static void refresh_cache_worker(struct work_struct *work)
			__refresh_tcon(server->leaf_fullpath + 1, tcon, false);
		mutex_unlock(&server->refpath_lock);

		if (tcon->ipc)
			cifs_put_smb_ses(tcon->ses);
		else
			cifs_put_tcon(tcon);
	}