Merge tag 'nfsd-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
[platform/kernel/linux-starfive.git] / fs / mbcache.c
index 47ccfcb..e272ad7 100644 (file)
@@ -90,8 +90,14 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&entry->e_list);
-       /* Initial hash reference */
-       atomic_set(&entry->e_refcnt, 1);
+       /*
+        * We create entry with two references. One reference is kept by the
+        * hash table, the other reference is used to protect us from
+        * mb_cache_entry_delete_or_get() until the entry is fully setup. This
+        * avoids nesting of cache->c_list_lock into hash table bit locks which
+        * is problematic for RT.
+        */
+       atomic_set(&entry->e_refcnt, 2);
        entry->e_key = key;
        entry->e_value = value;
        entry->e_reusable = reusable;
@@ -106,15 +112,12 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
                }
        }
        hlist_bl_add_head(&entry->e_hash_list, head);
-       /*
-        * Add entry to LRU list before it can be found by
-        * mb_cache_entry_delete() to avoid races
-        */
+       hlist_bl_unlock(head);
        spin_lock(&cache->c_list_lock);
        list_add_tail(&entry->e_list, &cache->c_list);
        cache->c_entry_count++;
        spin_unlock(&cache->c_list_lock);
-       hlist_bl_unlock(head);
+       mb_cache_entry_put(cache, entry);
 
        return 0;
 }