cifs: fix return of uninitialized rc in dfs_cache_update_tgthint()
[platform/kernel/linux-starfive.git] / fs / cifs / dfs_cache.c
index e70915a..3bc1d34 100644 (file)
@@ -792,26 +792,27 @@ static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const
  */
 static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
 {
-       int rc;
-       struct cache_entry *ce;
        struct dfs_info3_param *refs = NULL;
+       struct cache_entry *ce;
        int numrefs = 0;
-       bool newent = false;
+       int rc;
 
        cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
 
-       down_write(&htable_rw_lock);
+       down_read(&htable_rw_lock);
 
        ce = lookup_cache_entry(path);
-       if (!IS_ERR(ce)) {
-               if (!cache_entry_expired(ce)) {
-                       dump_ce(ce);
-                       up_write(&htable_rw_lock);
-                       return 0;
-               }
-       } else {
-               newent = true;
+       if (!IS_ERR(ce) && !cache_entry_expired(ce)) {
+               up_read(&htable_rw_lock);
+               return 0;
        }
+       /*
+        * Unlock shared access as we don't want to hold any locks while getting
+        * a new referral.  The @ses used for performing the I/O could be
+        * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
+        * in order to failover -- if necessary.
+        */
+       up_read(&htable_rw_lock);
 
        /*
         * Either the entry was not found, or it is expired.
@@ -819,19 +820,22 @@ static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, cons
         */
        rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
        if (rc)
-               goto out_unlock;
+               goto out;
 
        dump_refs(refs, numrefs);
 
-       if (!newent) {
-               rc = update_cache_entry_locked(ce, refs, numrefs);
-               goto out_unlock;
+       down_write(&htable_rw_lock);
+       /* Re-check as another task might have it added or refreshed already */
+       ce = lookup_cache_entry(path);
+       if (!IS_ERR(ce)) {
+               if (cache_entry_expired(ce))
+                       rc = update_cache_entry_locked(ce, refs, numrefs);
+       } else {
+               rc = add_cache_entry_locked(refs, numrefs);
        }
 
-       rc = add_cache_entry_locked(refs, numrefs);
-
-out_unlock:
        up_write(&htable_rw_lock);
+out:
        free_dfs_info_array(refs, numrefs);
        return rc;
 }
@@ -1046,10 +1050,10 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
                             const struct nls_table *cp, int remap, const char *path,
                             const struct dfs_cache_tgt_iterator *it)
 {
-       int rc;
-       const char *npath;
-       struct cache_entry *ce;
        struct cache_dfs_tgt *t;
+       struct cache_entry *ce;
+       const char *npath;
+       int rc = 0;
 
        npath = dfs_cache_canonical_path(path, cp, remap);
        if (IS_ERR(npath))