summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/dfs_cache.c40
1 files 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);