SUNRPC/cache: Allow garbage collection of invalid cache entries
authorTrond Myklebust <trondmy@gmail.com>
Sun, 1 Mar 2020 23:21:43 +0000 (18:21 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 16 Mar 2020 16:04:34 +0000 (12:04 -0400)
If the cache entry never gets initialised, we want the garbage
collector to be able to evict it. Otherwise if the upcall daemon
fails to initialise the entry, we end up never expiring it.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
[ cel: resolved a merge conflict ]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/cache.h
net/sunrpc/cache.c

index 656882a50991e06657d013254a6b384807b7f899..532cdbda43da0cef7880e9f9fbf3039854409b62 100644 (file)
@@ -209,9 +209,6 @@ static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
 
 static inline bool cache_is_expired(struct cache_detail *detail, struct cache_head *h)
 {
-       if (!test_bit(CACHE_VALID, &h->flags))
-               return false;
-
        return  (h->expiry_time < seconds_since_boot()) ||
                (detail->flush_time >= h->last_refresh);
 }
index 7f2e5d818e05ee87b05d37a5da23a83cfdd54699..cd76ef2d26b82a8af8867b141a8d48f4f20a6370 100644 (file)
@@ -64,13 +64,14 @@ static struct cache_head *sunrpc_cache_find_rcu(struct cache_detail *detail,
 
        rcu_read_lock();
        hlist_for_each_entry_rcu(tmp, head, cache_list) {
-               if (detail->match(tmp, key)) {
-                       if (cache_is_expired(detail, tmp))
-                               continue;
-                       tmp = cache_get_rcu(tmp);
-                       rcu_read_unlock();
-                       return tmp;
-               }
+               if (!detail->match(tmp, key))
+                       continue;
+               if (test_bit(CACHE_VALID, &tmp->flags) &&
+                   cache_is_expired(detail, tmp))
+                       continue;
+               tmp = cache_get_rcu(tmp);
+               rcu_read_unlock();
+               return tmp;
        }
        rcu_read_unlock();
        return NULL;
@@ -114,17 +115,18 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
        /* check if entry appeared while we slept */
        hlist_for_each_entry_rcu(tmp, head, cache_list,
                                 lockdep_is_held(&detail->hash_lock)) {
-               if (detail->match(tmp, key)) {
-                       if (cache_is_expired(detail, tmp)) {
-                               sunrpc_begin_cache_remove_entry(tmp, detail);
-                               freeme = tmp;
-                               break;
-                       }
-                       cache_get(tmp);
-                       spin_unlock(&detail->hash_lock);
-                       cache_put(new, detail);
-                       return tmp;
+               if (!detail->match(tmp, key))
+                       continue;
+               if (test_bit(CACHE_VALID, &tmp->flags) &&
+                   cache_is_expired(detail, tmp)) {
+                       sunrpc_begin_cache_remove_entry(tmp, detail);
+                       freeme = tmp;
+                       break;
                }
+               cache_get(tmp);
+               spin_unlock(&detail->hash_lock);
+               cache_put(new, detail);
+               return tmp;
        }
 
        hlist_add_head_rcu(&new->cache_list, head);