summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-06-27 04:28:25 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-06-27 04:28:24 -0700
commit89279350de5d0c67146a94243aaf872acf80cc6b (patch)
tree1136eae11473b464005a89d19c3e16ac52c628cd
parent47d50db7ee0c4325462fd61a22ed00b82891c678 (diff)
parent33b30b124fde308d6192a55df6f176f1c36a79ce (diff)
Merge "fs/mbcache: fix mb_cache_lru_list corruption"
-rw-r--r--fs/mbcache.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/mbcache.c b/fs/mbcache.c
index ab1da987d1ae..de509271d031 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -222,8 +222,19 @@ __mb_cache_entry_release(struct mb_cache_entry *ce)
* then reacquire the lock in the proper order.
*/
spin_lock(&mb_cache_spinlock);
- if (list_empty(&ce->e_lru_list))
- list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
+ /*
+ * Evaluate the conditions under global lock mb_cache_spinlock,
+ * to check if mb_cache_entry_get() is running now
+ * and has already deleted the entry from mb_cache_lru_list
+ * and incremented ce->e_refcnt to prevent further additions
+ * to mb_cache_lru_list.
+ */
+ if (!(ce->e_used || ce->e_queued ||
+ atomic_read(&ce->e_refcnt))) {
+ if (list_empty(&ce->e_lru_list))
+ list_add_tail(&ce->e_lru_list,
+ &mb_cache_lru_list);
+ }
spin_unlock(&mb_cache_spinlock);
}
__spin_unlock_mb_cache_entry(ce);