VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
c6ae4c04a861d (Thomas Gleixner 2019-05-22 09:51:37 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   2) /*
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   3)    lru_cache.c
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   4) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   5)    This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   6) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   7)    Copyright (C) 2003-2008, LINBIT Information Technologies GmbH.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   8)    Copyright (C) 2003-2008, Philipp Reisner <philipp.reisner@linbit.com>.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700   9)    Copyright (C) 2003-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  10) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  11) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  12)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  13) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  14) #include <linux/module.h>
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  15) #include <linux/bitops.h>
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  16) #include <linux/slab.h>
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  17) #include <linux/string.h> /* for memset */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  18) #include <linux/seq_file.h> /* for seq_printf */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  19) #include <linux/lru_cache.h>
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  20) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  21) MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  22) 	      "Lars Ellenberg <lars@linbit.com>");
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  23) MODULE_DESCRIPTION("lru_cache - Track sets of hot objects");
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  24) MODULE_LICENSE("GPL");
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  25) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  26) /* this is developers aid only.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  27)  * it catches concurrent access (lack of locking on the users part) */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  28) #define PARANOIA_ENTRY() do {		\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  29) 	BUG_ON(!lc);			\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  30) 	BUG_ON(!lc->nr_elements);	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  31) 	BUG_ON(test_and_set_bit(__LC_PARANOIA, &lc->flags)); \
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  32) } while (0)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  33) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  34) #define RETURN(x...)     do { \
4738fa16907a9 (Lars Ellenberg  2011-02-21 13:20:55 +0100  35) 	clear_bit_unlock(__LC_PARANOIA, &lc->flags); \
4738fa16907a9 (Lars Ellenberg  2011-02-21 13:20:55 +0100  36) 	return x ; } while (0)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  37) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  38) /* BUG() if e is not one of the elements tracked by lc */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  39) #define PARANOIA_LC_ELEMENT(lc, e) do {	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  40) 	struct lru_cache *lc_ = (lc);	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  41) 	struct lc_element *e_ = (e);	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  42) 	unsigned i = e_->lc_index;	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  43) 	BUG_ON(i >= lc_->nr_elements);	\
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  44) 	BUG_ON(lc_->lc_element[i] != e_); } while (0)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  45) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  46) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  47) /* We need to atomically
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  48)  *  - try to grab the lock (set LC_LOCKED)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  49)  *  - only if there is no pending transaction
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  50)  *    (neither LC_DIRTY nor LC_STARVING is set)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  51)  * Because of PARANOIA_ENTRY() above abusing lc->flags as well,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  52)  * it is not sufficient to just say
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  53)  *	return 0 == cmpxchg(&lc->flags, 0, LC_LOCKED);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  54)  */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  55) int lc_try_lock(struct lru_cache *lc)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  56) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  57) 	unsigned long val;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  58) 	do {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  59) 		val = cmpxchg(&lc->flags, 0, LC_LOCKED);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  60) 	} while (unlikely (val == LC_PARANOIA));
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  61) 	/* Spin until no-one is inside a PARANOIA_ENTRY()/RETURN() section. */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  62) 	return 0 == val;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  63) #if 0
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  64) 	/* Alternative approach, spin in case someone enters or leaves a
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  65) 	 * PARANOIA_ENTRY()/RETURN() section. */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  66) 	unsigned long old, new, val;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  67) 	do {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  68) 		old = lc->flags & LC_PARANOIA;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  69) 		new = old | LC_LOCKED;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  70) 		val = cmpxchg(&lc->flags, old, new);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  71) 	} while (unlikely (val == (old ^ LC_PARANOIA)));
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  72) 	return old == val;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  73) #endif
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  74) }
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  75) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  76) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  77)  * lc_create - prepares to track objects in an active set
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  78)  * @name: descriptive name only used in lc_seq_printf_stats and lc_seq_dump_details
c95c2d328cd05 (Randy Dunlap    2021-04-16 15:46:26 -0700  79)  * @cache: cache root pointer
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  80)  * @max_pending_changes: maximum changes to accumulate until a transaction is required
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  81)  * @e_count: number of elements allowed to be active simultaneously
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  82)  * @e_size: size of the tracked objects
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  83)  * @e_off: offset to the &struct lc_element member in a tracked object
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  84)  *
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  85)  * Returns a pointer to a newly initialized struct lru_cache on success,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  86)  * or NULL on (allocation) failure.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  87)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  88) struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100  89) 		unsigned max_pending_changes,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  90) 		unsigned e_count, size_t e_size, size_t e_off)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  91) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  92) 	struct hlist_head *slot = NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  93) 	struct lc_element **element = NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  94) 	struct lru_cache *lc;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  95) 	struct lc_element *e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  96) 	unsigned cache_obj_size = kmem_cache_size(cache);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  97) 	unsigned i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  98) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700  99) 	WARN_ON(cache_obj_size < e_size);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 100) 	if (cache_obj_size < e_size)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 101) 		return NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 102) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 103) 	/* e_count too big; would probably fail the allocation below anyways.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 104) 	 * for typical use cases, e_count should be few thousand at most. */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 105) 	if (e_count > LC_MAX_ACTIVE)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 106) 		return NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 107) 
a08aa355af18c (Ilia Mirkin     2011-05-24 17:13:30 -0700 108) 	slot = kcalloc(e_count, sizeof(struct hlist_head), GFP_KERNEL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 109) 	if (!slot)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 110) 		goto out_fail;
6396bb221514d (Kees Cook       2018-06-12 14:03:40 -0700 111) 	element = kcalloc(e_count, sizeof(struct lc_element *), GFP_KERNEL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 112) 	if (!element)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 113) 		goto out_fail;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 114) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 115) 	lc = kzalloc(sizeof(*lc), GFP_KERNEL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 116) 	if (!lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 117) 		goto out_fail;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 118) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 119) 	INIT_LIST_HEAD(&lc->in_use);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 120) 	INIT_LIST_HEAD(&lc->lru);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 121) 	INIT_LIST_HEAD(&lc->free);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 122) 	INIT_LIST_HEAD(&lc->to_be_changed);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 123) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 124) 	lc->name = name;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 125) 	lc->element_size = e_size;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 126) 	lc->element_off = e_off;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 127) 	lc->nr_elements = e_count;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 128) 	lc->max_pending_changes = max_pending_changes;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 129) 	lc->lc_cache = cache;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 130) 	lc->lc_element = element;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 131) 	lc->lc_slot = slot;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 132) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 133) 	/* preallocate all objects */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 134) 	for (i = 0; i < e_count; i++) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 135) 		void *p = kmem_cache_alloc(cache, GFP_KERNEL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 136) 		if (!p)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 137) 			break;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 138) 		memset(p, 0, lc->element_size);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 139) 		e = p + e_off;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 140) 		e->lc_index = i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 141) 		e->lc_number = LC_FREE;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 142) 		e->lc_new_number = LC_FREE;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 143) 		list_add(&e->list, &lc->free);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 144) 		element[i] = e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 145) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 146) 	if (i == e_count)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 147) 		return lc;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 148) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 149) 	/* else: could not allocate all elements, give up */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 150) 	for (i--; i; i--) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 151) 		void *p = element[i];
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 152) 		kmem_cache_free(cache, p - e_off);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 153) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 154) 	kfree(lc);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 155) out_fail:
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 156) 	kfree(element);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 157) 	kfree(slot);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 158) 	return NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 159) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 160) 
8ce953aa39e2b (Lars Ellenberg  2014-02-27 09:46:18 +0100 161) static void lc_free_by_index(struct lru_cache *lc, unsigned i)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 162) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 163) 	void *p = lc->lc_element[i];
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 164) 	WARN_ON(!p);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 165) 	if (p) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 166) 		p -= lc->element_off;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 167) 		kmem_cache_free(lc->lc_cache, p);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 168) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 169) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 170) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 171) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 172)  * lc_destroy - frees memory allocated by lc_create()
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 173)  * @lc: the lru cache to destroy
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 174)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 175) void lc_destroy(struct lru_cache *lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 176) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 177) 	unsigned i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 178) 	if (!lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 179) 		return;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 180) 	for (i = 0; i < lc->nr_elements; i++)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 181) 		lc_free_by_index(lc, i);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 182) 	kfree(lc->lc_element);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 183) 	kfree(lc->lc_slot);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 184) 	kfree(lc);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 185) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 186) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 187) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 188)  * lc_reset - does a full reset for @lc and the hash table slots.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 189)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 190)  *
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 191)  * It is roughly the equivalent of re-allocating a fresh lru_cache object,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 192)  * basically a short cut to lc_destroy(lc); lc = lc_create(...);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 193)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 194) void lc_reset(struct lru_cache *lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 195) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 196) 	unsigned i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 197) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 198) 	INIT_LIST_HEAD(&lc->in_use);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 199) 	INIT_LIST_HEAD(&lc->lru);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 200) 	INIT_LIST_HEAD(&lc->free);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 201) 	INIT_LIST_HEAD(&lc->to_be_changed);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 202) 	lc->used = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 203) 	lc->hits = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 204) 	lc->misses = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 205) 	lc->starving = 0;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 206) 	lc->locked = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 207) 	lc->changed = 0;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 208) 	lc->pending_changes = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 209) 	lc->flags = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 210) 	memset(lc->lc_slot, 0, sizeof(struct hlist_head) * lc->nr_elements);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 211) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 212) 	for (i = 0; i < lc->nr_elements; i++) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 213) 		struct lc_element *e = lc->lc_element[i];
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 214) 		void *p = e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 215) 		p -= lc->element_off;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 216) 		memset(p, 0, lc->element_size);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 217) 		/* re-init it */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 218) 		e->lc_index = i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 219) 		e->lc_number = LC_FREE;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 220) 		e->lc_new_number = LC_FREE;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 221) 		list_add(&e->list, &lc->free);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 222) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 223) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 224) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 225) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 226)  * lc_seq_printf_stats - print stats about @lc into @seq
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 227)  * @seq: the seq_file to print into
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 228)  * @lc: the lru cache to print statistics of
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 229)  */
bb649b34dd3d8 (Roland Kammerer 2015-04-16 10:17:51 +0200 230) void lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 231) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 232) 	/* NOTE:
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 233) 	 * total calls to lc_get are
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 234) 	 * (starving + hits + misses)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 235) 	 * misses include "locked" count (update from an other thread in
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 236) 	 * progress) and "changed", when this in fact lead to an successful
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 237) 	 * update of the cache.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 238) 	 */
d50f8f8d91a7d (Joe Perches     2015-04-15 16:18:25 -0700 239) 	seq_printf(seq, "\t%s: used:%u/%u hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n",
d50f8f8d91a7d (Joe Perches     2015-04-15 16:18:25 -0700 240) 		   lc->name, lc->used, lc->nr_elements,
d50f8f8d91a7d (Joe Perches     2015-04-15 16:18:25 -0700 241) 		   lc->hits, lc->misses, lc->starving, lc->locked, lc->changed);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 242) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 243) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 244) static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 245) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 246) 	return  lc->lc_slot + (enr % lc->nr_elements);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 247) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 248) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 249) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 250) static struct lc_element *__lc_find(struct lru_cache *lc, unsigned int enr,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 251) 		bool include_changing)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 252) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 253) 	struct lc_element *e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 254) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 255) 	BUG_ON(!lc);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 256) 	BUG_ON(!lc->nr_elements);
b67bfe0d42cac (Sasha Levin     2013-02-27 17:06:00 -0800 257) 	hlist_for_each_entry(e, lc_hash_slot(lc, enr), colision) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 258) 		/* "about to be changed" elements, pending transaction commit,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 259) 		 * are hashed by their "new number". "Normal" elements have
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 260) 		 * lc_number == lc_new_number. */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 261) 		if (e->lc_new_number != enr)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 262) 			continue;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 263) 		if (e->lc_new_number == e->lc_number || include_changing)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 264) 			return e;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 265) 		break;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 266) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 267) 	return NULL;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 268) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 269) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 270) /**
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 271)  * lc_find - find element by label, if present in the hash table
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 272)  * @lc: The lru_cache object
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 273)  * @enr: element number
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 274)  *
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 275)  * Returns the pointer to an element, if the element with the requested
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 276)  * "label" or element number is present in the hash table,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 277)  * or NULL if not found. Does not change the refcnt.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 278)  * Ignores elements that are "about to be used", i.e. not yet in the active
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 279)  * set, but still pending transaction commit.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 280)  */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 281) struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 282) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 283) 	return __lc_find(lc, enr, 0);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 284) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 285) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 286) /**
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 287)  * lc_is_used - find element by label
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 288)  * @lc: The lru_cache object
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 289)  * @enr: element number
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 290)  *
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 291)  * Returns true, if the element with the requested "label" or element number is
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 292)  * present in the hash table, and is used (refcnt > 0).
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 293)  * Also finds elements that are not _currently_ used but only "about to be
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 294)  * used", i.e. on the "to_be_changed" list, pending transaction commit.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 295)  */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 296) bool lc_is_used(struct lru_cache *lc, unsigned int enr)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 297) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 298) 	struct lc_element *e = __lc_find(lc, enr, 1);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 299) 	return e && e->refcnt;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 300) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 301) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 302) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 303)  * lc_del - removes an element from the cache
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 304)  * @lc: The lru_cache object
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 305)  * @e: The element to remove
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 306)  *
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 307)  * @e must be unused (refcnt == 0). Moves @e from "lru" to "free" list,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 308)  * sets @e->enr to %LC_FREE.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 309)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 310) void lc_del(struct lru_cache *lc, struct lc_element *e)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 311) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 312) 	PARANOIA_ENTRY();
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 313) 	PARANOIA_LC_ELEMENT(lc, e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 314) 	BUG_ON(e->refcnt);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 315) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 316) 	e->lc_number = e->lc_new_number = LC_FREE;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 317) 	hlist_del_init(&e->colision);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 318) 	list_move(&e->list, &lc->free);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 319) 	RETURN();
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 320) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 321) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 322) static struct lc_element *lc_prepare_for_change(struct lru_cache *lc, unsigned new_number)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 323) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 324) 	struct list_head *n;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 325) 	struct lc_element *e;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 326) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 327) 	if (!list_empty(&lc->free))
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 328) 		n = lc->free.next;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 329) 	else if (!list_empty(&lc->lru))
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 330) 		n = lc->lru.prev;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 331) 	else
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 332) 		return NULL;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 333) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 334) 	e = list_entry(n, struct lc_element, list);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 335) 	PARANOIA_LC_ELEMENT(lc, e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 336) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 337) 	e->lc_new_number = new_number;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 338) 	if (!hlist_unhashed(&e->colision))
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 339) 		__hlist_del(&e->colision);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 340) 	hlist_add_head(&e->colision, lc_hash_slot(lc, new_number));
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 341) 	list_move(&e->list, &lc->to_be_changed);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 342) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 343) 	return e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 344) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 345) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 346) static int lc_unused_element_available(struct lru_cache *lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 347) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 348) 	if (!list_empty(&lc->free))
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 349) 		return 1; /* something on the free list */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 350) 	if (!list_empty(&lc->lru))
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 351) 		return 1;  /* something to evict */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 352) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 353) 	return 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 354) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 355) 
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 356) /* used as internal flags to __lc_get */
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 357) enum {
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 358) 	LC_GET_MAY_CHANGE = 1,
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 359) 	LC_GET_MAY_USE_UNCOMMITTED = 2,
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 360) };
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 361) 
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 362) static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 363) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 364) 	struct lc_element *e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 365) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 366) 	PARANOIA_ENTRY();
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 367) 	if (lc->flags & LC_STARVING) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 368) 		++lc->starving;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 369) 		RETURN(NULL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 370) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 371) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 372) 	e = __lc_find(lc, enr, 1);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 373) 	/* if lc_new_number != lc_number,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 374) 	 * this enr is currently being pulled in already,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 375) 	 * and will be available once the pending transaction
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 376) 	 * has been committed. */
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 377) 	if (e) {
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 378) 		if (e->lc_new_number != e->lc_number) {
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 379) 			/* It has been found above, but on the "to_be_changed"
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 380) 			 * list, not yet committed.  Don't pull it in twice,
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 381) 			 * wait for the transaction, then try again...
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 382) 			 */
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 383) 			if (!(flags & LC_GET_MAY_USE_UNCOMMITTED))
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 384) 				RETURN(NULL);
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 385) 			/* ... unless the caller is aware of the implications,
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 386) 			 * probably preparing a cumulative transaction. */
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 387) 			++e->refcnt;
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 388) 			++lc->hits;
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 389) 			RETURN(e);
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 390) 		}
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 391) 		/* else: lc_new_number == lc_number; a real hit. */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 392) 		++lc->hits;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 393) 		if (e->refcnt++ == 0)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 394) 			lc->used++;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 395) 		list_move(&e->list, &lc->in_use); /* Not evictable... */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 396) 		RETURN(e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 397) 	}
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 398) 	/* e == NULL */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 399) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 400) 	++lc->misses;
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 401) 	if (!(flags & LC_GET_MAY_CHANGE))
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 402) 		RETURN(NULL);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 403) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 404) 	/* To avoid races with lc_try_lock(), first, mark us dirty
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 405) 	 * (using test_and_set_bit, as it implies memory barriers), ... */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 406) 	test_and_set_bit(__LC_DIRTY, &lc->flags);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 407) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 408) 	/* ... only then check if it is locked anyways. If lc_unlock clears
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 409) 	 * the dirty bit again, that's not a problem, we will come here again.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 410) 	 */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 411) 	if (test_bit(__LC_LOCKED, &lc->flags)) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 412) 		++lc->locked;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 413) 		RETURN(NULL);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 414) 	}
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 415) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 416) 	/* In case there is nothing available and we can not kick out
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 417) 	 * the LRU element, we have to wait ...
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 418) 	 */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 419) 	if (!lc_unused_element_available(lc)) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 420) 		__set_bit(__LC_STARVING, &lc->flags);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 421) 		RETURN(NULL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 422) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 423) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 424) 	/* It was not present in the active set.  We are going to recycle an
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 425) 	 * unused (or even "free") element, but we won't accumulate more than
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 426) 	 * max_pending_changes changes.  */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 427) 	if (lc->pending_changes >= lc->max_pending_changes)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 428) 		RETURN(NULL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 429) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 430) 	e = lc_prepare_for_change(lc, enr);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 431) 	BUG_ON(!e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 432) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 433) 	clear_bit(__LC_STARVING, &lc->flags);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 434) 	BUG_ON(++e->refcnt != 1);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 435) 	lc->used++;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 436) 	lc->pending_changes++;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 437) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 438) 	RETURN(e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 439) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 440) 
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 441) /**
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 442)  * lc_get - get element by label, maybe change the active set
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 443)  * @lc: the lru cache to operate on
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 444)  * @enr: the label to look up
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 445)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 446)  * Finds an element in the cache, increases its usage count,
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 447)  * "touches" and returns it.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 448)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 449)  * In case the requested number is not present, it needs to be added to the
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 450)  * cache. Therefore it is possible that an other element becomes evicted from
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 451)  * the cache. In either case, the user is notified so he is able to e.g. keep
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 452)  * a persistent log of the cache changes, and therefore the objects in use.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 453)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 454)  * Return values:
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 455)  *  NULL
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 456)  *     The cache was marked %LC_STARVING,
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 457)  *     or the requested label was not in the active set
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 458)  *     and a changing transaction is still pending (@lc was marked %LC_DIRTY).
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 459)  *     Or no unused or free element could be recycled (@lc will be marked as
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 460)  *     %LC_STARVING, blocking further lc_get() operations).
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 461)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 462)  *  pointer to the element with the REQUESTED element number.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 463)  *     In this case, it can be used right away
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 464)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 465)  *  pointer to an UNUSED element with some different element number,
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 466)  *          where that different number may also be %LC_FREE.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 467)  *
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 468)  *          In this case, the cache is marked %LC_DIRTY,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 469)  *          so lc_try_lock() will no longer succeed.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 470)  *          The returned element pointer is moved to the "to_be_changed" list,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 471)  *          and registered with the new element number on the hash collision chains,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 472)  *          so it is possible to pick it up from lc_is_used().
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 473)  *          Up to "max_pending_changes" (see lc_create()) can be accumulated.
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 474)  *          The user now should do whatever housekeeping is necessary,
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 475)  *          typically serialize on lc_try_lock_for_transaction(), then call
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 476)  *          lc_committed(lc) and lc_unlock(), to finish the change.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 477)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 478)  * NOTE: The user needs to check the lc_number on EACH use, so he recognizes
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 479)  *       any cache set change.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 480)  */
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 481) struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 482) {
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 483) 	return __lc_get(lc, enr, LC_GET_MAY_CHANGE);
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 484) }
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 485) 
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 486) /**
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 487)  * lc_get_cumulative - like lc_get; also finds to-be-changed elements
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 488)  * @lc: the lru cache to operate on
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 489)  * @enr: the label to look up
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 490)  *
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 491)  * Unlike lc_get this also returns the element for @enr, if it is belonging to
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 492)  * a pending transaction, so the return values are like for lc_get(),
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 493)  * plus:
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 494)  *
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 495)  * pointer to an element already on the "to_be_changed" list.
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 496)  * 	In this case, the cache was already marked %LC_DIRTY.
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 497)  *
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 498)  * Caller needs to make sure that the pending transaction is completed,
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 499)  * before proceeding to actually use this element.
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 500)  */
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 501) struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr)
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 502) {
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 503) 	return __lc_get(lc, enr, LC_GET_MAY_CHANGE|LC_GET_MAY_USE_UNCOMMITTED);
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 504) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 505) 
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 506) /**
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 507)  * lc_try_get - get element by label, if present; do not change the active set
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 508)  * @lc: the lru cache to operate on
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 509)  * @enr: the label to look up
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 510)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 511)  * Finds an element in the cache, increases its usage count,
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 512)  * "touches" and returns it.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 513)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 514)  * Return values:
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 515)  *  NULL
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 516)  *     The cache was marked %LC_STARVING,
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 517)  *     or the requested label was not in the active set
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 518)  *
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 519)  *  pointer to the element with the REQUESTED element number.
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 520)  *     In this case, it can be used right away
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 521)  */
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 522) struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr)
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 523) {
a9efc748d679e (Lars Ellenberg  2011-02-21 13:20:58 +0100 524) 	return __lc_get(lc, enr, 0);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 525) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 526) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 527) /**
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 528)  * lc_committed - tell @lc that pending changes have been recorded
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 529)  * @lc: the lru cache to operate on
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 530)  *
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 531)  * User is expected to serialize on explicit lc_try_lock_for_transaction()
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 532)  * before the transaction is started, and later needs to lc_unlock() explicitly
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 533)  * as well.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 534)  */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 535) void lc_committed(struct lru_cache *lc)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 536) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 537) 	struct lc_element *e, *tmp;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 538) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 539) 	PARANOIA_ENTRY();
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 540) 	list_for_each_entry_safe(e, tmp, &lc->to_be_changed, list) {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 541) 		/* count number of changes, not number of transactions */
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 542) 		++lc->changed;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 543) 		e->lc_number = e->lc_new_number;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 544) 		list_move(&e->list, &lc->in_use);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 545) 	}
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 546) 	lc->pending_changes = 0;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 547) 	RETURN();
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 548) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 549) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 550) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 551) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 552)  * lc_put - give up refcnt of @e
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 553)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 554)  * @e: the element to put
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 555)  *
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 556)  * If refcnt reaches zero, the element is moved to the lru list,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 557)  * and a %LC_STARVING (if set) is cleared.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 558)  * Returns the new (post-decrement) refcnt.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 559)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 560) unsigned int lc_put(struct lru_cache *lc, struct lc_element *e)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 561) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 562) 	PARANOIA_ENTRY();
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 563) 	PARANOIA_LC_ELEMENT(lc, e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 564) 	BUG_ON(e->refcnt == 0);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 565) 	BUG_ON(e->lc_number != e->lc_new_number);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 566) 	if (--e->refcnt == 0) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 567) 		/* move it to the front of LRU. */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 568) 		list_move(&e->list, &lc->lru);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 569) 		lc->used--;
4738fa16907a9 (Lars Ellenberg  2011-02-21 13:20:55 +0100 570) 		clear_bit_unlock(__LC_STARVING, &lc->flags);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 571) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 572) 	RETURN(e->refcnt);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 573) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 574) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 575) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 576)  * lc_element_by_index
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 577)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 578)  * @i: the index of the element to return
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 579)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 580) struct lc_element *lc_element_by_index(struct lru_cache *lc, unsigned i)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 581) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 582) 	BUG_ON(i >= lc->nr_elements);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 583) 	BUG_ON(lc->lc_element[i] == NULL);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 584) 	BUG_ON(lc->lc_element[i]->lc_index != i);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 585) 	return lc->lc_element[i];
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 586) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 587) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 588) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 589)  * lc_index_of
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 590)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 591)  * @e: the element to query for its index position in lc->element
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 592)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 593) unsigned int lc_index_of(struct lru_cache *lc, struct lc_element *e)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 594) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 595) 	PARANOIA_LC_ELEMENT(lc, e);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 596) 	return e->lc_index;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 597) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 598) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 599) /**
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 600)  * lc_set - associate index with label
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 601)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 602)  * @enr: the label to set
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 603)  * @index: the element index to associate label with.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 604)  *
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 605)  * Used to initialize the active set to some previously recorded state.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 606)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 607) void lc_set(struct lru_cache *lc, unsigned int enr, int index)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 608) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 609) 	struct lc_element *e;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 610) 	struct list_head *lh;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 611) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 612) 	if (index < 0 || index >= lc->nr_elements)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 613) 		return;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 614) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 615) 	e = lc_element_by_index(lc, index);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 616) 	BUG_ON(e->lc_number != e->lc_new_number);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 617) 	BUG_ON(e->refcnt != 0);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 618) 
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 619) 	e->lc_number = e->lc_new_number = enr;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 620) 	hlist_del_init(&e->colision);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 621) 	if (enr == LC_FREE)
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 622) 		lh = &lc->free;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 623) 	else {
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 624) 		hlist_add_head(&e->colision, lc_hash_slot(lc, enr));
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 625) 		lh = &lc->lru;
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 626) 	}
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 627) 	list_move(&e->list, lh);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 628) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 629) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 630) /**
c95c2d328cd05 (Randy Dunlap    2021-04-16 15:46:26 -0700 631)  * lc_seq_dump_details - Dump a complete LRU cache to seq in textual form.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 632)  * @lc: the lru cache to operate on
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 633)  * @seq: the &struct seq_file pointer to seq_printf into
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 634)  * @utext: user supplied additional "heading" or other info
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 635)  * @detail: function pointer the user may provide to dump further details
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 636)  * of the object the lc_element is embedded in. May be NULL.
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 637)  * Note: a leading space ' ' and trailing newline '\n' is implied.
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 638)  */
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 639) void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char *utext,
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 640) 	     void (*detail) (struct seq_file *, struct lc_element *))
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 641) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 642) 	unsigned int nr_elements = lc->nr_elements;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 643) 	struct lc_element *e;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 644) 	int i;
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 645) 
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 646) 	seq_printf(seq, "\tnn: lc_number (new nr) refcnt %s\n ", utext);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 647) 	for (i = 0; i < nr_elements; i++) {
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 648) 		e = lc_element_by_index(lc, i);
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 649) 		if (e->lc_number != e->lc_new_number)
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 650) 			seq_printf(seq, "\t%5d: %6d %8d %6d ",
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 651) 				i, e->lc_number, e->lc_new_number, e->refcnt);
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 652) 		else
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 653) 			seq_printf(seq, "\t%5d: %6d %-8s %6d ",
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 654) 				i, e->lc_number, "-\"-", e->refcnt);
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 655) 		if (detail)
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 656) 			detail(seq, e);
54e6fc38e888a (Lars Ellenberg  2014-05-08 13:39:35 +0200 657) 		seq_putc(seq, '\n');
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 658) 	}
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 659) }
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 660) 
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 661) EXPORT_SYMBOL(lc_create);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 662) EXPORT_SYMBOL(lc_reset);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 663) EXPORT_SYMBOL(lc_destroy);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 664) EXPORT_SYMBOL(lc_set);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 665) EXPORT_SYMBOL(lc_del);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 666) EXPORT_SYMBOL(lc_try_get);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 667) EXPORT_SYMBOL(lc_find);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 668) EXPORT_SYMBOL(lc_get);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 669) EXPORT_SYMBOL(lc_put);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 670) EXPORT_SYMBOL(lc_committed);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 671) EXPORT_SYMBOL(lc_element_by_index);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 672) EXPORT_SYMBOL(lc_index_of);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 673) EXPORT_SYMBOL(lc_seq_printf_stats);
b411b3637fa71 (Philipp Reisner 2009-09-25 16:07:19 -0700 674) EXPORT_SYMBOL(lc_seq_dump_details);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 675) EXPORT_SYMBOL(lc_try_lock);
46a15bc3ec425 (Lars Ellenberg  2011-02-21 13:21:01 +0100 676) EXPORT_SYMBOL(lc_is_used);
cbe5e6109538d (Lars Ellenberg  2013-03-22 22:17:36 -0600 677) EXPORT_SYMBOL(lc_get_cumulative);