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