diff options
-rw-r--r-- | fs/fscache/cookie.c | 294 | ||||
-rw-r--r-- | fs/fscache/internal.h | 7 | ||||
-rw-r--r-- | fs/fscache/netfs.c | 81 | ||||
-rw-r--r-- | include/linux/fscache.h | 8 | ||||
-rw-r--r-- | include/trace/events/fscache.h | 8 |
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 | ||
22 | static atomic_t fscache_object_debug_id = ATOMIC_INIT(0); | 22 | static atomic_t fscache_object_debug_id = ATOMIC_INIT(0); |
23 | 23 | ||
24 | #define fscache_cookie_hash_shift 15 | ||
25 | static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift]; | ||
26 | |||
24 | static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, | 27 | static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, |
25 | loff_t object_size); | 28 | loff_t object_size); |
26 | static int fscache_alloc_object(struct fscache_cache *cache, | 29 | static int fscache_alloc_object(struct fscache_cache *cache, |
@@ -28,6 +31,44 @@ static int fscache_alloc_object(struct fscache_cache *cache, | |||
28 | static int fscache_attach_object(struct fscache_cookie *cookie, | 31 | static int fscache_attach_object(struct fscache_cookie *cookie, |
29 | struct fscache_object *object); | 32 | struct fscache_object *object); |
30 | 33 | ||
34 | static 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 | |||
60 | void 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 | */ | ||
91 | static 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 | |||
126 | static 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 | */ | ||
153 | struct 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 | |||
201 | nomem: | ||
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 | */ | ||
210 | struct 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 | |||
233 | collision: | ||
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 | ||
184 | nomem: | 358 | out: |
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 | } |
192 | EXPORT_SYMBOL(__fscache_acquire_cookie); | 362 | EXPORT_SYMBOL(__fscache_acquire_cookie); |
193 | 363 | ||
@@ -679,6 +849,22 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, | |||
679 | EXPORT_SYMBOL(__fscache_relinquish_cookie); | 849 | EXPORT_SYMBOL(__fscache_relinquish_cookie); |
680 | 850 | ||
681 | /* | 851 | /* |
852 | * Remove a cookie from the hash table. | ||
853 | */ | ||
854 | static 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 | */ |
684 | void fscache_cookie_put(struct fscache_cookie *cookie, | 870 | void 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 | */ |
50 | extern struct kmem_cache *fscache_cookie_jar; | 50 | extern struct kmem_cache *fscache_cookie_jar; |
51 | 51 | ||
52 | extern void fscache_free_cookie(struct fscache_cookie *); | ||
52 | extern void fscache_cookie_init_once(void *); | 53 | extern void fscache_cookie_init_once(void *); |
54 | extern 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); | ||
59 | extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *); | ||
53 | extern void fscache_cookie_put(struct fscache_cookie *, | 60 | extern 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 | ||
17 | static LIST_HEAD(fscache_netfs_list); | ||
18 | |||
19 | /* | 17 | /* |
20 | * register a network filesystem for caching | 18 | * register a network filesystem for caching |
21 | */ | 19 | */ |
22 | int __fscache_register_netfs(struct fscache_netfs *netfs) | 20 | int __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 | ||
87 | already_registered: | 58 | already_registered: |
88 | up_write(&fscache_addremove_sem); | 59 | fscache_cookie_put(candidate, fscache_cookie_put_dup_netfs); |
89 | 60 | _leave(" = -EEXIST"); | |
90 | nomem: | 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 | } |
97 | EXPORT_SYMBOL(__fscache_register_netfs); | 63 | EXPORT_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 | ||
26 | enum fscache_cookie_trace { | 26 | enum 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") |