summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-04-04 08:41:28 -0400
committerDavid Howells <dhowells@redhat.com>2018-04-06 09:05:14 -0400
commitec0328e46d6e5d0f17372eb90ab8e333c2ac7ca9 (patch)
tree0ff7cf689f4259baa44a5de789f72cdc015a1e30
parentee1235a9a06813429c201bf186397a6feeea07bf (diff)
fscache: Maintain a catalogue of allocated cookies
Maintain a catalogue of allocated cookies so that cookie collisions can be handled properly. For the moment, this just involves printing a warning and returning a NULL cookie to the caller of fscache_acquire_cookie(), but in future it might make sense to wait for the old cookie to finish being cleaned up. This requires the cookie key to be stored attached to the cookie so that we still have the key available if the netfs relinquishes the cookie. This is done by an earlier patch. The catalogue also renders redundant fscache_netfs_list (used for checking for duplicates), so that can be removed. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Anna Schumaker <anna.schumaker@netapp.com> Tested-by: Steve Dickson <steved@redhat.com>
-rw-r--r--fs/fscache/cookie.c294
-rw-r--r--fs/fscache/internal.h7
-rw-r--r--fs/fscache/netfs.c81
-rw-r--r--include/linux/fscache.h8
-rw-r--r--include/trace/events/fscache.h8
5 files changed, 279 insertions, 119 deletions
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 8ca9a932d225..7dc55b93a830 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -21,6 +21,9 @@ struct kmem_cache *fscache_cookie_jar;
21 21
22static atomic_t fscache_object_debug_id = ATOMIC_INIT(0); 22static atomic_t fscache_object_debug_id = ATOMIC_INIT(0);
23 23
24#define fscache_cookie_hash_shift 15
25static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift];
26
24static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, 27static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
25 loff_t object_size); 28 loff_t object_size);
26static int fscache_alloc_object(struct fscache_cache *cache, 29static int fscache_alloc_object(struct fscache_cache *cache,
@@ -28,6 +31,44 @@ static int fscache_alloc_object(struct fscache_cache *cache,
28static int fscache_attach_object(struct fscache_cookie *cookie, 31static int fscache_attach_object(struct fscache_cookie *cookie,
29 struct fscache_object *object); 32 struct fscache_object *object);
30 33
34static void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)
35{
36 struct hlist_node *object;
37 const u8 *k;
38 unsigned loop;
39
40 pr_err("%c-cookie c=%p [p=%p fl=%lx nc=%u na=%u]\n",
41 prefix, cookie, cookie->parent, cookie->flags,
42 atomic_read(&cookie->n_children),
43 atomic_read(&cookie->n_active));
44 pr_err("%c-cookie d=%p n=%p\n",
45 prefix, cookie->def, cookie->netfs_data);
46
47 object = READ_ONCE(cookie->backing_objects.first);
48 if (object)
49 pr_err("%c-cookie o=%p\n",
50 prefix, hlist_entry(object, struct fscache_object, cookie_link));
51
52 pr_err("%c-key=[%u] '", prefix, cookie->key_len);
53 k = (cookie->key_len <= sizeof(cookie->inline_key)) ?
54 cookie->inline_key : cookie->key;
55 for (loop = 0; loop < cookie->key_len; loop++)
56 pr_cont("%02x", k[loop]);
57 pr_cont("'\n");
58}
59
60void fscache_free_cookie(struct fscache_cookie *cookie)
61{
62 if (cookie) {
63 BUG_ON(!hlist_empty(&cookie->backing_objects));
64 if (cookie->aux_len > sizeof(cookie->inline_aux))
65 kfree(cookie->aux);
66 if (cookie->key_len > sizeof(cookie->inline_key))
67 kfree(cookie->key);
68 kmem_cache_free(fscache_cookie_jar, cookie);
69 }
70}
71
31/* 72/*
32 * initialise an cookie jar slab element prior to any use 73 * initialise an cookie jar slab element prior to any use
33 */ 74 */
@@ -42,6 +83,170 @@ void fscache_cookie_init_once(void *_cookie)
42} 83}
43 84
44/* 85/*
86 * Set the index key in a cookie. The cookie struct has space for a 12-byte
87 * key plus length and hash, but if that's not big enough, it's instead a
88 * pointer to a buffer containing 3 bytes of hash, 1 byte of length and then
89 * the key data.
90 */
91static int fscache_set_key(struct fscache_cookie *cookie,
92 const void *index_key, size_t index_key_len)
93{
94 unsigned long long h;
95 u32 *buf;
96 int i;
97
98 cookie->key_len = index_key_len;
99
100 if (index_key_len > sizeof(cookie->inline_key)) {
101 buf = kzalloc(index_key_len, GFP_KERNEL);
102 if (!buf)
103 return -ENOMEM;
104 cookie->key = buf;
105 } else {
106 buf = (u32 *)cookie->inline_key;
107 buf[0] = 0;
108 buf[1] = 0;
109 buf[2] = 0;
110 }
111
112 memcpy(buf, index_key, index_key_len);
113
114 /* Calculate a hash and combine this with the length in the first word
115 * or first half word
116 */
117 h = (unsigned long)cookie->parent;
118 h += index_key_len + cookie->type;
119 for (i = 0; i < (index_key_len + sizeof(u32) - 1) / sizeof(u32); i++)
120 h += buf[i];
121
122 cookie->key_hash = h ^ (h >> 32);
123 return 0;
124}
125
126static long fscache_compare_cookie(const struct fscache_cookie *a,
127 const struct fscache_cookie *b)
128{
129 const void *ka, *kb;
130
131 if (a->key_hash != b->key_hash)
132 return (long)a->key_hash - (long)b->key_hash;
133 if (a->parent != b->parent)
134 return (long)a->parent - (long)b->parent;
135 if (a->key_len != b->key_len)
136 return (long)a->key_len - (long)b->key_len;
137 if (a->type != b->type)
138 return (long)a->type - (long)b->type;
139
140 if (a->key_len <= sizeof(a->inline_key)) {
141 ka = &a->inline_key;
142 kb = &b->inline_key;
143 } else {
144 ka = a->key;
145 kb = b->key;
146 }
147 return memcmp(ka, kb, a->key_len);
148}
149
150/*
151 * Allocate a cookie.
152 */
153struct fscache_cookie *fscache_alloc_cookie(
154 struct fscache_cookie *parent,
155 const struct fscache_cookie_def *def,
156 const void *index_key, size_t index_key_len,
157 const void *aux_data, size_t aux_data_len,
158 void *netfs_data,
159 loff_t object_size)
160{
161 struct fscache_cookie *cookie;
162
163 /* allocate and initialise a cookie */
164 cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL);
165 if (!cookie)
166 return NULL;
167
168 cookie->key_len = index_key_len;
169 cookie->aux_len = aux_data_len;
170
171 if (fscache_set_key(cookie, index_key, index_key_len) < 0)
172 goto nomem;
173
174 if (cookie->aux_len <= sizeof(cookie->inline_aux)) {
175 memcpy(cookie->inline_aux, aux_data, cookie->aux_len);
176 } else {
177 cookie->aux = kmemdup(aux_data, cookie->aux_len, GFP_KERNEL);
178 if (!cookie->aux)
179 goto nomem;
180 }
181
182 atomic_set(&cookie->usage, 1);
183 atomic_set(&cookie->n_children, 0);
184
185 /* We keep the active count elevated until relinquishment to prevent an
186 * attempt to wake up every time the object operations queue quiesces.
187 */
188 atomic_set(&cookie->n_active, 1);
189
190 cookie->def = def;
191 cookie->parent = parent;
192 cookie->netfs_data = netfs_data;
193 cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET);
194 cookie->type = def->type;
195
196 /* radix tree insertion won't use the preallocation pool unless it's
197 * told it may not wait */
198 INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
199 return cookie;
200
201nomem:
202 fscache_free_cookie(cookie);
203 return NULL;
204}
205
206/*
207 * Attempt to insert the new cookie into the hash. If there's a collision, we
208 * return the old cookie if it's not in use and an error otherwise.
209 */
210struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate)
211{
212 struct fscache_cookie *cursor;
213 struct hlist_bl_head *h;
214 struct hlist_bl_node *p;
215 unsigned int bucket;
216
217 bucket = candidate->key_hash & (ARRAY_SIZE(fscache_cookie_hash) - 1);
218 h = &fscache_cookie_hash[bucket];
219
220 hlist_bl_lock(h);
221 hlist_bl_for_each_entry(cursor, p, h, hash_link) {
222 if (fscache_compare_cookie(candidate, cursor) == 0)
223 goto collision;
224 }
225
226 __set_bit(FSCACHE_COOKIE_ACQUIRED, &candidate->flags);
227 fscache_cookie_get(candidate->parent, fscache_cookie_get_acquire_parent);
228 atomic_inc(&candidate->parent->n_children);
229 hlist_bl_add_head(&candidate->hash_link, h);
230 hlist_bl_unlock(h);
231 return candidate;
232
233collision:
234 if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) {
235 trace_fscache_cookie(cursor, fscache_cookie_collision,
236 atomic_read(&cursor->usage));
237 pr_err("Duplicate cookie detected\n");
238 fscache_print_cookie(cursor, 'O');
239 fscache_print_cookie(candidate, 'N');
240 hlist_bl_unlock(h);
241 return NULL;
242 }
243
244 fscache_cookie_get(cursor, fscache_cookie_get_reacquire);
245 hlist_bl_unlock(h);
246 return cursor;
247}
248
249/*
45 * request a cookie to represent an object (index, datafile, xattr, etc) 250 * request a cookie to represent an object (index, datafile, xattr, etc)
46 * - parent specifies the parent object 251 * - parent specifies the parent object
47 * - the top level index cookie for each netfs is stored in the fscache_netfs 252 * - the top level index cookie for each netfs is stored in the fscache_netfs
@@ -65,7 +270,7 @@ struct fscache_cookie *__fscache_acquire_cookie(
65 loff_t object_size, 270 loff_t object_size,
66 bool enable) 271 bool enable)
67{ 272{
68 struct fscache_cookie *cookie; 273 struct fscache_cookie *candidate, *cookie;
69 274
70 BUG_ON(!def); 275 BUG_ON(!def);
71 276
@@ -95,53 +300,24 @@ struct fscache_cookie *__fscache_acquire_cookie(
95 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX && 300 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
96 parent->type != FSCACHE_COOKIE_TYPE_INDEX); 301 parent->type != FSCACHE_COOKIE_TYPE_INDEX);
97 302
98 /* allocate and initialise a cookie */ 303 candidate = fscache_alloc_cookie(parent, def,
99 cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL); 304 index_key, index_key_len,
100 if (!cookie) { 305 aux_data, aux_data_len,
306 netfs_data, object_size);
307 if (!candidate) {
101 fscache_stat(&fscache_n_acquires_oom); 308 fscache_stat(&fscache_n_acquires_oom);
102 _leave(" [ENOMEM]"); 309 _leave(" [ENOMEM]");
103 return NULL; 310 return NULL;
104 } 311 }
105 312
106 cookie->key_len = index_key_len; 313 cookie = fscache_hash_cookie(candidate);
107 cookie->aux_len = aux_data_len; 314 if (!cookie) {
108 315 trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
109 if (cookie->key_len <= sizeof(cookie->inline_key)) { 316 goto out;
110 memcpy(cookie->inline_key, index_key, cookie->key_len);
111 } else {
112 cookie->key = kmemdup(index_key, cookie->key_len, GFP_KERNEL);
113 if (!cookie->key)
114 goto nomem;
115 }
116
117 if (cookie->aux_len <= sizeof(cookie->inline_aux)) {
118 memcpy(cookie->inline_aux, aux_data, cookie->aux_len);
119 } else {
120 cookie->aux = kmemdup(aux_data, cookie->aux_len, GFP_KERNEL);
121 if (!cookie->aux)
122 goto nomem;
123 } 317 }
124 318
125 atomic_set(&cookie->usage, 1); 319 if (cookie == candidate)
126 atomic_set(&cookie->n_children, 0); 320 candidate = NULL;
127
128 /* We keep the active count elevated until relinquishment to prevent an
129 * attempt to wake up every time the object operations queue quiesces.
130 */
131 atomic_set(&cookie->n_active, 1);
132
133 fscache_cookie_get(parent, fscache_cookie_get_acquire_parent);
134 atomic_inc(&parent->n_children);
135
136 cookie->def = def;
137 cookie->parent = parent;
138 cookie->netfs_data = netfs_data;
139 cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET);
140 cookie->type = def->type;
141
142 /* radix tree insertion won't use the preallocation pool unless it's
143 * told it may not wait */
144 INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
145 321
146 switch (cookie->type) { 322 switch (cookie->type) {
147 case FSCACHE_COOKIE_TYPE_INDEX: 323 case FSCACHE_COOKIE_TYPE_INDEX:
@@ -178,16 +354,10 @@ struct fscache_cookie *__fscache_acquire_cookie(
178 } 354 }
179 355
180 fscache_stat(&fscache_n_acquires_ok); 356 fscache_stat(&fscache_n_acquires_ok);
181 _leave(" = %p", cookie);
182 return cookie;
183 357
184nomem: 358out:
185 if (cookie->aux_len > sizeof(cookie->inline_aux)) 359 fscache_free_cookie(candidate);
186 kfree(cookie->aux); 360 return cookie;
187 if (cookie->key_len > sizeof(cookie->inline_key))
188 kfree(cookie->key);
189 kmem_cache_free(fscache_cookie_jar, cookie);
190 return NULL;
191} 361}
192EXPORT_SYMBOL(__fscache_acquire_cookie); 362EXPORT_SYMBOL(__fscache_acquire_cookie);
193 363
@@ -679,6 +849,22 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
679EXPORT_SYMBOL(__fscache_relinquish_cookie); 849EXPORT_SYMBOL(__fscache_relinquish_cookie);
680 850
681/* 851/*
852 * Remove a cookie from the hash table.
853 */
854static void fscache_unhash_cookie(struct fscache_cookie *cookie)
855{
856 struct hlist_bl_head *h;
857 unsigned int bucket;
858
859 bucket = cookie->key_hash & (ARRAY_SIZE(fscache_cookie_hash) - 1);
860 h = &fscache_cookie_hash[bucket];
861
862 hlist_bl_lock(h);
863 hlist_bl_del(&cookie->hash_link);
864 hlist_bl_unlock(h);
865}
866
867/*
682 * Drop a reference to a cookie. 868 * Drop a reference to a cookie.
683 */ 869 */
684void fscache_cookie_put(struct fscache_cookie *cookie, 870void fscache_cookie_put(struct fscache_cookie *cookie,
@@ -698,12 +884,8 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
698 BUG_ON(usage < 0); 884 BUG_ON(usage < 0);
699 885
700 parent = cookie->parent; 886 parent = cookie->parent;
701 BUG_ON(!hlist_empty(&cookie->backing_objects)); 887 fscache_unhash_cookie(cookie);
702 if (cookie->aux_len > sizeof(cookie->inline_aux)) 888 fscache_free_cookie(cookie);
703 kfree(cookie->aux);
704 if (cookie->key_len > sizeof(cookie->inline_key))
705 kfree(cookie->key);
706 kmem_cache_free(fscache_cookie_jar, cookie);
707 889
708 cookie = parent; 890 cookie = parent;
709 where = fscache_cookie_put_parent; 891 where = fscache_cookie_put_parent;
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index 5f905a499306..500650f938fe 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -49,7 +49,14 @@ extern struct fscache_cache *fscache_select_cache_for_object(
49 */ 49 */
50extern struct kmem_cache *fscache_cookie_jar; 50extern struct kmem_cache *fscache_cookie_jar;
51 51
52extern void fscache_free_cookie(struct fscache_cookie *);
52extern void fscache_cookie_init_once(void *); 53extern void fscache_cookie_init_once(void *);
54extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *,
55 const struct fscache_cookie_def *,
56 const void *, size_t,
57 const void *, size_t,
58 void *, loff_t);
59extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *);
53extern void fscache_cookie_put(struct fscache_cookie *, 60extern void fscache_cookie_put(struct fscache_cookie *,
54 enum fscache_cookie_trace); 61 enum fscache_cookie_trace);
55 62
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index a5998dfab7e7..c2f605483cc5 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -14,85 +14,51 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include "internal.h" 15#include "internal.h"
16 16
17static LIST_HEAD(fscache_netfs_list);
18
19/* 17/*
20 * register a network filesystem for caching 18 * register a network filesystem for caching
21 */ 19 */
22int __fscache_register_netfs(struct fscache_netfs *netfs) 20int __fscache_register_netfs(struct fscache_netfs *netfs)
23{ 21{
24 struct fscache_netfs *ptr; 22 struct fscache_cookie *candidate, *cookie;
25 struct fscache_cookie *cookie;
26 int ret;
27 23
28 _enter("{%s}", netfs->name); 24 _enter("{%s}", netfs->name);
29 25
30 INIT_LIST_HEAD(&netfs->link);
31
32 /* allocate a cookie for the primary index */ 26 /* allocate a cookie for the primary index */
33 cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL); 27 candidate = fscache_alloc_cookie(&fscache_fsdef_index,
34 28 &fscache_fsdef_netfs_def,
35 if (!cookie) { 29 netfs->name, strlen(netfs->name),
30 &netfs->version, sizeof(netfs->version),
31 netfs, 0);
32 if (!candidate) {
36 _leave(" = -ENOMEM"); 33 _leave(" = -ENOMEM");
37 return -ENOMEM; 34 return -ENOMEM;
38 } 35 }
39 36
40 cookie->key_len = strlen(netfs->name); 37 candidate->flags = 1 << FSCACHE_COOKIE_ENABLED;
41 if (cookie->key_len <= sizeof(cookie->inline_key)) {
42 memcpy(cookie->inline_key, netfs->name, strlen(netfs->name));
43 } else {
44 ret = -ENOMEM;
45 cookie->key = kmemdup(netfs->name, cookie->key_len, GFP_KERNEL);
46 if (!cookie->key)
47 goto nomem;
48 }
49
50 cookie->aux_len = sizeof(netfs->version);
51 memcpy(cookie->inline_aux, &netfs->version, cookie->aux_len);
52
53 /* initialise the primary index cookie */
54 atomic_set(&cookie->usage, 1);
55 atomic_set(&cookie->n_children, 0);
56 atomic_set(&cookie->n_active, 1);
57
58 cookie->def = &fscache_fsdef_netfs_def;
59 cookie->parent = &fscache_fsdef_index;
60 cookie->netfs_data = netfs;
61 cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
62 cookie->type = FSCACHE_COOKIE_TYPE_INDEX;
63
64 spin_lock_init(&cookie->lock);
65 spin_lock_init(&cookie->stores_lock);
66 INIT_HLIST_HEAD(&cookie->backing_objects);
67 38
68 /* check the netfs type is not already present */ 39 /* check the netfs type is not already present */
69 down_write(&fscache_addremove_sem); 40 cookie = fscache_hash_cookie(candidate);
70 41 if (!cookie)
71 ret = -EEXIST; 42 goto already_registered;
72 list_for_each_entry(ptr, &fscache_netfs_list, link) { 43 if (cookie != candidate) {
73 if (strcmp(ptr->name, netfs->name) == 0) 44 trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
74 goto already_registered; 45 fscache_free_cookie(candidate);
75 } 46 }
76 47
77 fscache_cookie_get(cookie->parent, fscache_cookie_get_register_netfs); 48 fscache_cookie_get(cookie->parent, fscache_cookie_get_register_netfs);
78 atomic_inc(&cookie->parent->n_children); 49 atomic_inc(&cookie->parent->n_children);
79 50
80 netfs->primary_index = cookie; 51 netfs->primary_index = cookie;
81 list_add(&netfs->link, &fscache_netfs_list);
82 ret = 0;
83 52
84 pr_notice("Netfs '%s' registered for caching\n", netfs->name); 53 pr_notice("Netfs '%s' registered for caching\n", netfs->name);
85 trace_fscache_netfs(netfs); 54 trace_fscache_netfs(netfs);
55 _leave(" = 0");
56 return 0;
86 57
87already_registered: 58already_registered:
88 up_write(&fscache_addremove_sem); 59 fscache_cookie_put(candidate, fscache_cookie_put_dup_netfs);
89 60 _leave(" = -EEXIST");
90nomem: 61 return -EEXIST;
91 if (ret < 0)
92 kmem_cache_free(fscache_cookie_jar, cookie);
93
94 _leave(" = %d", ret);
95 return ret;
96} 62}
97EXPORT_SYMBOL(__fscache_register_netfs); 63EXPORT_SYMBOL(__fscache_register_netfs);
98 64
@@ -104,15 +70,8 @@ void __fscache_unregister_netfs(struct fscache_netfs *netfs)
104{ 70{
105 _enter("{%s.%u}", netfs->name, netfs->version); 71 _enter("{%s.%u}", netfs->name, netfs->version);
106 72
107 down_write(&fscache_addremove_sem);
108
109 list_del(&netfs->link);
110 fscache_relinquish_cookie(netfs->primary_index, NULL, false); 73 fscache_relinquish_cookie(netfs->primary_index, NULL, false);
111 74 pr_notice("Netfs '%s' unregistered from caching\n", netfs->name);
112 up_write(&fscache_addremove_sem);
113
114 pr_notice("Netfs '%s' unregistered from caching\n",
115 netfs->name);
116 75
117 _leave(""); 76 _leave("");
118} 77}
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index eb38f39cf832..84b90a79d75a 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -22,6 +22,7 @@
22#include <linux/list.h> 22#include <linux/list.h>
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/pagevec.h> 24#include <linux/pagevec.h>
25#include <linux/list_bl.h>
25 26
26#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) 27#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
27#define fscache_available() (1) 28#define fscache_available() (1)
@@ -124,7 +125,6 @@ struct fscache_netfs {
124 uint32_t version; /* indexing version */ 125 uint32_t version; /* indexing version */
125 const char *name; /* filesystem name */ 126 const char *name; /* filesystem name */
126 struct fscache_cookie *primary_index; 127 struct fscache_cookie *primary_index;
127 struct list_head link; /* internal link */
128}; 128};
129 129
130/* 130/*
@@ -143,6 +143,7 @@ struct fscache_cookie {
143 struct hlist_head backing_objects; /* object(s) backing this file/index */ 143 struct hlist_head backing_objects; /* object(s) backing this file/index */
144 const struct fscache_cookie_def *def; /* definition */ 144 const struct fscache_cookie_def *def; /* definition */
145 struct fscache_cookie *parent; /* parent of this entry */ 145 struct fscache_cookie *parent; /* parent of this entry */
146 struct hlist_bl_node hash_link; /* Link in hash table */
146 void *netfs_data; /* back pointer to netfs */ 147 void *netfs_data; /* back pointer to netfs */
147 struct radix_tree_root stores; /* pages to be stored on this cookie */ 148 struct radix_tree_root stores; /* pages to be stored on this cookie */
148#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */ 149#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */
@@ -156,11 +157,14 @@ struct fscache_cookie {
156#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */ 157#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */
157#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */ 158#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */
158#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */ 159#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */
159#define FSCACHE_COOKIE_AUX_UPDATED 7 /* T if the auxiliary data was updated */ 160#define FSCACHE_COOKIE_AUX_UPDATED 8 /* T if the auxiliary data was updated */
161#define FSCACHE_COOKIE_ACQUIRED 9 /* T if cookie is in use */
162#define FSCACHE_COOKIE_RELINQUISHING 10 /* T if cookie is being relinquished */
160 163
161 u8 type; /* Type of object */ 164 u8 type; /* Type of object */
162 u8 key_len; /* Length of index key */ 165 u8 key_len; /* Length of index key */
163 u8 aux_len; /* Length of auxiliary data */ 166 u8 aux_len; /* Length of auxiliary data */
167 u32 key_hash; /* Hash of parent, type, key, len */
164 union { 168 union {
165 void *key; /* Index key */ 169 void *key; /* Index key */
166 u8 inline_key[16]; /* - If the key is short enough */ 170 u8 inline_key[16]; /* - If the key is short enough */
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
index 82c060fe6635..686cfe997ed2 100644
--- a/include/trace/events/fscache.h
+++ b/include/trace/events/fscache.h
@@ -24,10 +24,14 @@
24#define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY 24#define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY
25 25
26enum fscache_cookie_trace { 26enum fscache_cookie_trace {
27 fscache_cookie_collision,
28 fscache_cookie_discard,
27 fscache_cookie_get_acquire_parent, 29 fscache_cookie_get_acquire_parent,
28 fscache_cookie_get_attach_object, 30 fscache_cookie_get_attach_object,
31 fscache_cookie_get_reacquire,
29 fscache_cookie_get_register_netfs, 32 fscache_cookie_get_register_netfs,
30 fscache_cookie_put_acquire_nobufs, 33 fscache_cookie_put_acquire_nobufs,
34 fscache_cookie_put_dup_netfs,
31 fscache_cookie_put_relinquish, 35 fscache_cookie_put_relinquish,
32 fscache_cookie_put_object, 36 fscache_cookie_put_object,
33 fscache_cookie_put_parent, 37 fscache_cookie_put_parent,
@@ -86,10 +90,14 @@ enum fscache_page_op_trace {
86 * Declare tracing information enums and their string mappings for display. 90 * Declare tracing information enums and their string mappings for display.
87 */ 91 */
88#define fscache_cookie_traces \ 92#define fscache_cookie_traces \
93 EM(fscache_cookie_collision, "*COLLISION*") \
94 EM(fscache_cookie_discard, "DISCARD") \
89 EM(fscache_cookie_get_acquire_parent, "GET prn") \ 95 EM(fscache_cookie_get_acquire_parent, "GET prn") \
90 EM(fscache_cookie_get_attach_object, "GET obj") \ 96 EM(fscache_cookie_get_attach_object, "GET obj") \
97 EM(fscache_cookie_get_reacquire, "GET raq") \
91 EM(fscache_cookie_get_register_netfs, "GET net") \ 98 EM(fscache_cookie_get_register_netfs, "GET net") \
92 EM(fscache_cookie_put_acquire_nobufs, "PUT nbf") \ 99 EM(fscache_cookie_put_acquire_nobufs, "PUT nbf") \
100 EM(fscache_cookie_put_dup_netfs, "PUT dnt") \
93 EM(fscache_cookie_put_relinquish, "PUT rlq") \ 101 EM(fscache_cookie_put_relinquish, "PUT rlq") \
94 EM(fscache_cookie_put_object, "PUT obj") \ 102 EM(fscache_cookie_put_object, "PUT obj") \
95 E_(fscache_cookie_put_parent, "PUT prn") 103 E_(fscache_cookie_put_parent, "PUT prn")