diff options
| author | 2022-09-24 18:14:12 -0700 | |
|---|---|---|
| committer | 2022-09-24 18:14:12 -0700 | |
| commit | b3bbcc5d1da1b654091dad15980b3d58fdae0fc6 (patch) | |
| tree | 77795fbece4fc61a659ed97c70d798ca81f35bb8 /include/linux/mbcache.h | |
| parent | fsdax: Fix infinite loop in dax_iomap_rw() (diff) | |
| parent | devdax: Fix soft-reservation memory description (diff) | |
Merge branch 'for-6.0/dax' into libnvdimm-fixes
Pick up another "Soft Reservation" fix for v6.0-final on top of some
straggling nvdimm fixes that missed v5.19.
Diffstat (limited to 'include/linux/mbcache.h')
| -rw-r--r-- | include/linux/mbcache.h | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h index 20f1e3ff6013..2da63fd7b98f 100644 --- a/include/linux/mbcache.h +++ b/include/linux/mbcache.h @@ -13,8 +13,16 @@ struct mb_cache; struct mb_cache_entry { /* List of entries in cache - protected by cache->c_list_lock */ struct list_head e_list; - /* Hash table list - protected by hash chain bitlock */ + /* + * Hash table list - protected by hash chain bitlock. The entry is + * guaranteed to be hashed while e_refcnt > 0. + */ struct hlist_bl_node e_hash_list; + /* + * Entry refcount. Once it reaches zero, entry is unhashed and freed. + * While refcount > 0, the entry is guaranteed to stay in the hash and + * e.g. mb_cache_entry_try_delete() will fail. + */ atomic_t e_refcnt; /* Key in hash - stable during lifetime of the entry */ u32 e_key; @@ -29,17 +37,24 @@ void mb_cache_destroy(struct mb_cache *cache); int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key, u64 value, bool reusable); -void __mb_cache_entry_free(struct mb_cache_entry *entry); -static inline int mb_cache_entry_put(struct mb_cache *cache, - struct mb_cache_entry *entry) +void __mb_cache_entry_free(struct mb_cache *cache, + struct mb_cache_entry *entry); +void mb_cache_entry_wait_unused(struct mb_cache_entry *entry); +static inline void mb_cache_entry_put(struct mb_cache *cache, + struct mb_cache_entry *entry) { - if (!atomic_dec_and_test(&entry->e_refcnt)) - return 0; - __mb_cache_entry_free(entry); - return 1; + unsigned int cnt = atomic_dec_return(&entry->e_refcnt); + + if (cnt > 0) { + if (cnt <= 2) + wake_up_var(&entry->e_refcnt); + return; + } + __mb_cache_entry_free(cache, entry); } -void mb_cache_entry_delete(struct mb_cache *cache, u32 key, u64 value); +struct mb_cache_entry *mb_cache_entry_delete_or_get(struct mb_cache *cache, + u32 key, u64 value); struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *cache, u32 key, u64 value); struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, |
