]>
Commit | Line | Data |
---|---|---|
e80aa729 NS |
1 | /* |
2 | * Copyright (c) 2006 Silicon Graphics, Inc. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it would be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | #ifndef __CACHE_H__ | |
19 | #define __CACHE_H__ | |
20 | ||
ba9ecd40 DC |
21 | /* |
22 | * initialisation flags | |
23 | */ | |
24 | /* | |
25 | * xfs_db always writes changes immediately, and so we need to purge buffers | |
26 | * when we get a buffer lookup mismatch due to reading the same block with a | |
27 | * different buffer configuration. | |
28 | */ | |
29 | #define CACHE_MISCOMPARE_PURGE (1 << 0) | |
30 | ||
31 | /* | |
32 | * cache object campare return values | |
33 | */ | |
34 | enum { | |
35 | CACHE_HIT, | |
36 | CACHE_MISS, | |
37 | CACHE_PURGE, | |
38 | }; | |
39 | ||
2556c98b BN |
40 | #define HASH_CACHE_RATIO 8 |
41 | ||
a040d7c9 BN |
42 | /* |
43 | * Cache priorities range from BASE to MAX. | |
44 | * | |
45 | * For prefetch support, the top half of the range starts at | |
aef29e17 DC |
46 | * CACHE_PREFETCH_PRIORITY and everytime the buffer is fetched and is at or |
47 | * above this priority level, it is reduced to below this level (refer to | |
48 | * libxfs_getbuf). | |
49 | * | |
50 | * If we have dirty nodes, we can't recycle them until they've been cleaned. To | |
51 | * keep these out of the reclaimable lists (as there can be lots of them) give | |
52 | * them their own priority that the shaker doesn't attempt to walk. | |
a040d7c9 BN |
53 | */ |
54 | ||
55 | #define CACHE_BASE_PRIORITY 0 | |
56 | #define CACHE_PREFETCH_PRIORITY 8 | |
69ec88b5 | 57 | #define CACHE_MAX_PRIORITY 15 |
aef29e17 DC |
58 | #define CACHE_DIRTY_PRIORITY (CACHE_MAX_PRIORITY + 1) |
59 | #define CACHE_NR_PRIORITIES CACHE_DIRTY_PRIORITY | |
69ec88b5 | 60 | |
e80aa729 NS |
61 | /* |
62 | * Simple, generic implementation of a cache (arbitrary data). | |
63 | * Provides a hash table with a capped number of cache entries. | |
64 | */ | |
65 | ||
66 | struct cache; | |
e80aa729 NS |
67 | struct cache_node; |
68 | ||
69 | typedef void *cache_key_t; | |
2556c98b | 70 | |
e80aa729 | 71 | typedef void (*cache_walk_t)(struct cache_node *); |
2556c98b | 72 | typedef struct cache_node * (*cache_node_alloc_t)(cache_key_t); |
0a7942b3 | 73 | typedef int (*cache_node_flush_t)(struct cache_node *); |
e80aa729 | 74 | typedef void (*cache_node_relse_t)(struct cache_node *); |
602dcc0e DC |
75 | typedef unsigned int (*cache_node_hash_t)(cache_key_t, unsigned int, |
76 | unsigned int); | |
e80aa729 | 77 | typedef int (*cache_node_compare_t)(struct cache_node *, cache_key_t); |
1c4110bd | 78 | typedef unsigned int (*cache_bulk_relse_t)(struct cache *, struct list_head *); |
e80aa729 NS |
79 | |
80 | struct cache_operations { | |
81 | cache_node_hash_t hash; | |
82 | cache_node_alloc_t alloc; | |
33165ec3 | 83 | cache_node_flush_t flush; |
e80aa729 NS |
84 | cache_node_relse_t relse; |
85 | cache_node_compare_t compare; | |
1c4110bd | 86 | cache_bulk_relse_t bulkrelse; /* optional */ |
e80aa729 NS |
87 | }; |
88 | ||
69ec88b5 BN |
89 | struct cache_hash { |
90 | struct list_head ch_list; /* hash chain head */ | |
91 | unsigned int ch_count; /* hash chain length */ | |
92 | pthread_mutex_t ch_mutex; /* hash chain mutex */ | |
93 | }; | |
94 | ||
95 | struct cache_mru { | |
96 | struct list_head cm_list; /* MRU head */ | |
97 | unsigned int cm_count; /* MRU length */ | |
98 | pthread_mutex_t cm_mutex; /* MRU lock */ | |
99 | }; | |
100 | ||
101 | struct cache_node { | |
102 | struct list_head cn_hash; /* hash chain */ | |
103 | struct list_head cn_mru; /* MRU chain */ | |
104 | unsigned int cn_count; /* reference count */ | |
105 | unsigned int cn_hashidx; /* hash chain index */ | |
106 | int cn_priority; /* priority, -1 = free list */ | |
1b9fecf7 | 107 | int cn_old_priority;/* saved pre-dirty prio */ |
69ec88b5 BN |
108 | pthread_mutex_t cn_mutex; /* node mutex */ |
109 | }; | |
110 | ||
e80aa729 | 111 | struct cache { |
ba9ecd40 | 112 | int c_flags; /* behavioural flags */ |
e80aa729 NS |
113 | unsigned int c_maxcount; /* max cache nodes */ |
114 | unsigned int c_count; /* count of nodes */ | |
115 | pthread_mutex_t c_mutex; /* node count mutex */ | |
116 | cache_node_hash_t hash; /* node hash function */ | |
117 | cache_node_alloc_t alloc; /* allocation function */ | |
33165ec3 | 118 | cache_node_flush_t flush; /* flush dirty data function */ |
e80aa729 NS |
119 | cache_node_relse_t relse; /* memory free function */ |
120 | cache_node_compare_t compare; /* comparison routine */ | |
1c4110bd | 121 | cache_bulk_relse_t bulkrelse; /* bulk release routine */ |
e80aa729 | 122 | unsigned int c_hashsize; /* hash bucket count */ |
602dcc0e | 123 | unsigned int c_hashshift; /* hash key shift */ |
e80aa729 | 124 | struct cache_hash *c_hash; /* hash table buckets */ |
aef29e17 | 125 | struct cache_mru c_mrus[CACHE_DIRTY_PRIORITY + 1]; |
9f38f08d MV |
126 | unsigned long long c_misses; /* cache misses */ |
127 | unsigned long long c_hits; /* cache hits */ | |
128 | unsigned int c_max; /* max nodes ever used */ | |
e80aa729 NS |
129 | }; |
130 | ||
ba9ecd40 | 131 | struct cache *cache_init(int, unsigned int, struct cache_operations *); |
e80aa729 NS |
132 | void cache_destroy(struct cache *); |
133 | void cache_walk(struct cache *, cache_walk_t); | |
134 | void cache_purge(struct cache *); | |
33165ec3 | 135 | void cache_flush(struct cache *); |
e80aa729 NS |
136 | |
137 | int cache_node_get(struct cache *, cache_key_t, struct cache_node **); | |
a040d7c9 | 138 | void cache_node_put(struct cache *, struct cache_node *); |
69ec88b5 BN |
139 | void cache_node_set_priority(struct cache *, struct cache_node *, int); |
140 | int cache_node_get_priority(struct cache_node *); | |
e80aa729 | 141 | int cache_node_purge(struct cache *, cache_key_t, struct cache_node *); |
b6281496 | 142 | void cache_report(FILE *fp, const char *, struct cache *); |
2556c98b | 143 | int cache_overflowed(struct cache *); |
e80aa729 NS |
144 | |
145 | #endif /* __CACHE_H__ */ |