^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/list_bl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mbcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Mbcache is a simple key-value store. Keys need not be unique, however
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * key-value pairs are expected to be unique (we use this fact in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * mb_cache_entry_delete()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Ext2 and ext4 use this cache for deduplication of extended attribute blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Ext4 also uses it for deduplication of xattr values stored in inodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * They use hash of data as a key and provide a value that may represent a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * block or inode number. That's why keys need not be unique (hash of different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * data may be the same). However user provided value always uniquely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * identifies a cache entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * We provide functions for creation and removal of entries, search by key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * and a special "delete entry with given key-value pair" operation. Fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * size hash table is used for fast key lookups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct mb_cache {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Hash table of entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct hlist_bl_head *c_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* log2 of hash table size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int c_bucket_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Maximum entries in cache to avoid degrading hash too much */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned long c_max_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Protects c_list, c_entry_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) spinlock_t c_list_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct list_head c_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Number of entries in cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned long c_entry_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct shrinker c_shrink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Work for shrinking when the cache has too many entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct work_struct c_shrink_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct kmem_cache *mb_entry_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static unsigned long mb_cache_shrink(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned long nr_to_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static inline struct hlist_bl_head *mb_cache_entry_head(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return &cache->c_hash[hash_32(key, cache->c_bucket_bits)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Number of entries to reclaim synchronously when there are too many entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * in cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SYNC_SHRINK_BATCH 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * mb_cache_entry_create - create entry in cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @cache - cache where the entry should be created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * @mask - gfp mask with which the entry should be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @key - key of the entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @value - value of the entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @reusable - is the entry reusable by others?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Creates entry in @cache with key @key and value @value. The function returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * -EBUSY if entry with the same key and value already exists in cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Otherwise 0 is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u64 value, bool reusable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct mb_cache_entry *entry, *dup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct hlist_bl_node *dup_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct hlist_bl_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Schedule background reclaim if there are too many entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (cache->c_entry_count >= cache->c_max_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) schedule_work(&cache->c_shrink_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Do some sync reclaim if background reclaim cannot keep up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (cache->c_entry_count >= 2*cache->c_max_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mb_cache_shrink(cache, SYNC_SHRINK_BATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) entry = kmem_cache_alloc(mb_entry_cache, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) INIT_LIST_HEAD(&entry->e_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* One ref for hash, one ref returned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) atomic_set(&entry->e_refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) entry->e_key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) entry->e_value = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) entry->e_reusable = reusable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) entry->e_referenced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) head = mb_cache_entry_head(cache, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) hlist_bl_lock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) hlist_bl_for_each_entry(dup, dup_node, head, e_hash_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (dup->e_key == key && dup->e_value == value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) kmem_cache_free(mb_entry_cache, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) hlist_bl_add_head(&entry->e_hash_list, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) spin_lock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) list_add_tail(&entry->e_list, &cache->c_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Grab ref for LRU list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) atomic_inc(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) cache->c_entry_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) spin_unlock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) EXPORT_SYMBOL(mb_cache_entry_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) void __mb_cache_entry_free(struct mb_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kmem_cache_free(mb_entry_cache, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) EXPORT_SYMBOL(__mb_cache_entry_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static struct mb_cache_entry *__entry_find(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct mb_cache_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct mb_cache_entry *old_entry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct hlist_bl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct hlist_bl_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) head = mb_cache_entry_head(cache, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) hlist_bl_lock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (entry && !hlist_bl_unhashed(&entry->e_hash_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) node = entry->e_hash_list.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) node = hlist_bl_first(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) while (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) entry = hlist_bl_entry(node, struct mb_cache_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) e_hash_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (entry->e_key == key && entry->e_reusable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) atomic_inc(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) node = node->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (old_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mb_cache_entry_put(cache, old_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * mb_cache_entry_find_first - find the first reusable entry with the given key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @cache: cache where we should search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @key: key to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Search in @cache for a reusable entry with key @key. Grabs reference to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * first reusable entry found and returns the entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return __entry_find(cache, NULL, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) EXPORT_SYMBOL(mb_cache_entry_find_first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * mb_cache_entry_find_next - find next reusable entry with the same key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @cache: cache where we should search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @entry: entry to start search from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Finds next reusable entry in the hash chain which has the same key as @entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * If @entry is unhashed (which can happen when deletion of entry races with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * search), finds the first reusable entry in the hash chain. The function drops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * reference to @entry and returns with a reference to the found entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct mb_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return __entry_find(cache, entry, entry->e_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) EXPORT_SYMBOL(mb_cache_entry_find_next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * mb_cache_entry_get - get a cache entry by value (and key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @cache - cache we work with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @key - key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @value - value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *cache, u32 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u64 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct hlist_bl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct hlist_bl_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct mb_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) head = mb_cache_entry_head(cache, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) hlist_bl_lock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (entry->e_key == key && entry->e_value == value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) atomic_inc(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) EXPORT_SYMBOL(mb_cache_entry_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* mb_cache_entry_delete - remove a cache entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @cache - cache we work with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @key - key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @value - value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Remove entry from cache @cache with key @key and value @value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) void mb_cache_entry_delete(struct mb_cache *cache, u32 key, u64 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct hlist_bl_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct hlist_bl_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct mb_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) head = mb_cache_entry_head(cache, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) hlist_bl_lock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (entry->e_key == key && entry->e_value == value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* We keep hash list reference to keep entry alive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) hlist_bl_del_init(&entry->e_hash_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) spin_lock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!list_empty(&entry->e_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) list_del_init(&entry->e_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!WARN_ONCE(cache->c_entry_count == 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "mbcache: attempt to decrement c_entry_count past zero"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) cache->c_entry_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) atomic_dec(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) spin_unlock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) mb_cache_entry_put(cache, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) EXPORT_SYMBOL(mb_cache_entry_delete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* mb_cache_entry_touch - cache entry got used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @cache - cache the entry belongs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @entry - entry that got used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Marks entry as used to give hit higher chances of surviving in cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) void mb_cache_entry_touch(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct mb_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) entry->e_referenced = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) EXPORT_SYMBOL(mb_cache_entry_touch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static unsigned long mb_cache_count(struct shrinker *shrink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct shrink_control *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct mb_cache *cache = container_of(shrink, struct mb_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) c_shrink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return cache->c_entry_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Shrink number of entries in cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static unsigned long mb_cache_shrink(struct mb_cache *cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) unsigned long nr_to_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct mb_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct hlist_bl_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) unsigned long shrunk = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) spin_lock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) while (nr_to_scan-- && !list_empty(&cache->c_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) entry = list_first_entry(&cache->c_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct mb_cache_entry, e_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (entry->e_referenced) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) entry->e_referenced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) list_move_tail(&entry->e_list, &cache->c_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) list_del_init(&entry->e_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) cache->c_entry_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * We keep LRU list reference so that entry doesn't go away
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * from under us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) spin_unlock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) head = mb_cache_entry_head(cache, entry->e_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) hlist_bl_lock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!hlist_bl_unhashed(&entry->e_hash_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) hlist_bl_del_init(&entry->e_hash_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) atomic_dec(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) hlist_bl_unlock(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (mb_cache_entry_put(cache, entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) shrunk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) spin_lock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) spin_unlock(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return shrunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static unsigned long mb_cache_scan(struct shrinker *shrink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct shrink_control *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct mb_cache *cache = container_of(shrink, struct mb_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) c_shrink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return mb_cache_shrink(cache, sc->nr_to_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* We shrink 1/X of the cache when we have too many entries in it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #define SHRINK_DIVISOR 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static void mb_cache_shrink_worker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct mb_cache *cache = container_of(work, struct mb_cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) c_shrink_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mb_cache_shrink(cache, cache->c_max_entries / SHRINK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * mb_cache_create - create cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * @bucket_bits: log2 of the hash table size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * Create cache for keys with 2^bucket_bits hash entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct mb_cache *mb_cache_create(int bucket_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct mb_cache *cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) unsigned long bucket_count = 1UL << bucket_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) cache = kzalloc(sizeof(struct mb_cache), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) cache->c_bucket_bits = bucket_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) cache->c_max_entries = bucket_count << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) INIT_LIST_HEAD(&cache->c_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spin_lock_init(&cache->c_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) cache->c_hash = kmalloc_array(bucket_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sizeof(struct hlist_bl_head),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!cache->c_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) kfree(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (i = 0; i < bucket_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) INIT_HLIST_BL_HEAD(&cache->c_hash[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) cache->c_shrink.count_objects = mb_cache_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) cache->c_shrink.scan_objects = mb_cache_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) cache->c_shrink.seeks = DEFAULT_SEEKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (register_shrinker(&cache->c_shrink)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) kfree(cache->c_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) kfree(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) INIT_WORK(&cache->c_shrink_work, mb_cache_shrink_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EXPORT_SYMBOL(mb_cache_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * mb_cache_destroy - destroy cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * @cache: the cache to destroy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Free all entries in cache and cache itself. Caller must make sure nobody
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * (except shrinker) can reach @cache when calling this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) void mb_cache_destroy(struct mb_cache *cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct mb_cache_entry *entry, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) unregister_shrinker(&cache->c_shrink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * We don't bother with any locking. Cache must not be used at this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) list_for_each_entry_safe(entry, next, &cache->c_list, e_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!hlist_bl_unhashed(&entry->e_hash_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) hlist_bl_del_init(&entry->e_hash_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) atomic_dec(&entry->e_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) list_del(&entry->e_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) WARN_ON(atomic_read(&entry->e_refcnt) != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) mb_cache_entry_put(cache, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) kfree(cache->c_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) kfree(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) EXPORT_SYMBOL(mb_cache_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int __init mbcache_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) mb_entry_cache = kmem_cache_create("mbcache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) sizeof(struct mb_cache_entry), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!mb_entry_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void __exit mbcache_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) kmem_cache_destroy(mb_entry_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) module_init(mbcache_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) module_exit(mbcache_exit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) MODULE_AUTHOR("Jan Kara <jack@suse.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) MODULE_LICENSE("GPL");