Blob Blame History Raw
From: Paulo Alcantara <pc@cjr.nz>
Date: Tue, 13 Dec 2022 11:30:30 -0300
Subject: [PATCH] cifs: refresh root referrals
Git-commit: 8332858569a096cff02e157555d839e0be921ec7
References: bsc#1193629
Patch-mainline: v6.2-rc1

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: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
Acked-by: Paulo Alcantara <palcantara@suse.de>
---
 fs/cifs/dfs_cache.c | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c
index 95cc3951420e..cb83b86eafe6 100644
--- a/fs/cifs/dfs_cache.c
+++ b/fs/cifs/dfs_cache.c
@@ -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,7 +1502,10 @@ static void refresh_cache_worker(struct work_struct *work)
 			__refresh_tcon(server->leaf_fullpath + 1, tcon, false);
 		mutex_unlock(&server->refpath_lock);
 
-		cifs_put_tcon(tcon);
+		if (tcon->ipc)
+			cifs_put_smb_ses(tcon->ses);
+		else
+			cifs_put_tcon(tcon);
 	}
 
 	spin_lock(&cache_ttl_lock);
-- 
2.39.0