From: Darrick J. Wong <djwong@xxxxxxxxxx> Create a helper to bump the refcount of a cache node. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- lib/support/cache.h | 1 + lib/support/cache.c | 57 +++++++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/lib/support/cache.h b/lib/support/cache.h index b18b6d3325e9ad..e8f1c82ef7869c 100644 --- a/lib/support/cache.h +++ b/lib/support/cache.h @@ -141,5 +141,6 @@ int cache_node_get_priority(struct cache_node *); int cache_node_purge(struct cache *, cache_key_t, struct cache_node *); void cache_report(FILE *fp, const char *, struct cache *); int cache_overflowed(struct cache *); +struct cache_node *cache_node_grab(struct cache *cache, struct cache_node *node); #endif /* __CACHE_H__ */ diff --git a/lib/support/cache.c b/lib/support/cache.c index 606acd5453cf10..49568ffa6de2e4 100644 --- a/lib/support/cache.c +++ b/lib/support/cache.c @@ -362,6 +362,35 @@ __cache_node_purge( return 0; } +/* Grab a new refcount to the cache node object. Caller must hold cn_mutex. */ +struct cache_node *cache_node_grab(struct cache *cache, struct cache_node *node) +{ + struct cache_mru *mru; + + if (node->cn_count == 0 && cache->get) { + int err = cache->get(cache, node); + if (err) + return NULL; + } + if (node->cn_count == 0) { + ASSERT(node->cn_priority >= 0); + ASSERT(!list_empty(&node->cn_mru)); + mru = &cache->c_mrus[node->cn_priority]; + pthread_mutex_lock(&mru->cm_mutex); + mru->cm_count--; + list_del_init(&node->cn_mru); + pthread_mutex_unlock(&mru->cm_mutex); + if (node->cn_old_priority != -1) { + ASSERT(node->cn_priority == + CACHE_DIRTY_PRIORITY); + node->cn_priority = node->cn_old_priority; + node->cn_old_priority = -1; + } + } + node->cn_count++; + return node; +} + /* * Lookup in the cache hash table. With any luck we'll get a cache * hit, in which case this will all be over quickly and painlessly. @@ -377,7 +406,6 @@ cache_node_get( struct cache_node **nodep) { struct cache_hash *hash; - struct cache_mru *mru; struct cache_node *node = NULL, *n; unsigned int hashidx; int priority = 0; @@ -411,31 +439,10 @@ cache_node_get( * from its MRU list, and update stats. */ pthread_mutex_lock(&node->cn_mutex); - - if (node->cn_count == 0 && cache->get) { - int err = cache->get(cache, node); - if (err) { - pthread_mutex_unlock(&node->cn_mutex); - goto next_object; - } + if (!cache_node_grab(cache, node)) { + pthread_mutex_unlock(&node->cn_mutex); + goto next_object; } - if (node->cn_count == 0) { - ASSERT(node->cn_priority >= 0); - ASSERT(!list_empty(&node->cn_mru)); - mru = &cache->c_mrus[node->cn_priority]; - pthread_mutex_lock(&mru->cm_mutex); - mru->cm_count--; - list_del_init(&node->cn_mru); - pthread_mutex_unlock(&mru->cm_mutex); - if (node->cn_old_priority != -1) { - ASSERT(node->cn_priority == - CACHE_DIRTY_PRIORITY); - node->cn_priority = node->cn_old_priority; - node->cn_old_priority = -1; - } - } - node->cn_count++; - pthread_mutex_unlock(&node->cn_mutex); pthread_mutex_unlock(&hash->ch_mutex);