fscache: Attach the index key and aux data to the cookie
[linux-2.6-block.git] / fs / fscache / cookie.c
CommitLineData
955d0091
DH
1/* netfs cookie management
2 *
3 * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
ccc4fc3d
DH
10 *
11 * See Documentation/filesystems/caching/netfs-api.txt for more information on
12 * the netfs API.
955d0091
DH
13 */
14
15#define FSCACHE_DEBUG_LEVEL COOKIE
16#include <linux/module.h>
17#include <linux/slab.h>
18#include "internal.h"
19
20struct kmem_cache *fscache_cookie_jar;
21
ccc4fc3d
DH
22static atomic_t fscache_object_debug_id = ATOMIC_INIT(0);
23
24static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie);
25static int fscache_alloc_object(struct fscache_cache *cache,
26 struct fscache_cookie *cookie);
27static int fscache_attach_object(struct fscache_cookie *cookie,
28 struct fscache_object *object);
29
955d0091
DH
30/*
31 * initialise an cookie jar slab element prior to any use
32 */
33void fscache_cookie_init_once(void *_cookie)
34{
35 struct fscache_cookie *cookie = _cookie;
36
37 memset(cookie, 0, sizeof(*cookie));
38 spin_lock_init(&cookie->lock);
1bccf513 39 spin_lock_init(&cookie->stores_lock);
955d0091
DH
40 INIT_HLIST_HEAD(&cookie->backing_objects);
41}
42
ccc4fc3d
DH
43/*
44 * request a cookie to represent an object (index, datafile, xattr, etc)
45 * - parent specifies the parent object
46 * - the top level index cookie for each netfs is stored in the fscache_netfs
47 * struct upon registration
48 * - def points to the definition
49 * - the netfs_data will be passed to the functions pointed to in *def
50 * - all attached caches will be searched to see if they contain this object
51 * - index objects aren't stored on disk until there's a dependent file that
52 * needs storing
53 * - other objects are stored in a selected cache immediately, and all the
54 * indices forming the path to it are instantiated if necessary
55 * - we never let on to the netfs about errors
56 * - we may set a negative cookie pointer, but that's okay
57 */
58struct fscache_cookie *__fscache_acquire_cookie(
59 struct fscache_cookie *parent,
60 const struct fscache_cookie_def *def,
402cb8dd
DH
61 const void *index_key, size_t index_key_len,
62 const void *aux_data, size_t aux_data_len,
94d30ae9
DH
63 void *netfs_data,
64 bool enable)
ccc4fc3d
DH
65{
66 struct fscache_cookie *cookie;
67
68 BUG_ON(!def);
69
94d30ae9 70 _enter("{%s},{%s},%p,%u",
ccc4fc3d 71 parent ? (char *) parent->def->name : "<no-parent>",
94d30ae9 72 def->name, netfs_data, enable);
ccc4fc3d 73
402cb8dd
DH
74 if (!index_key || !index_key_len || index_key_len > 255 || aux_data_len > 255)
75 return NULL;
76 if (!aux_data || !aux_data_len) {
77 aux_data = NULL;
78 aux_data_len = 0;
79 }
80
ccc4fc3d
DH
81 fscache_stat(&fscache_n_acquires);
82
83 /* if there's no parent cookie, then we don't create one here either */
84 if (!parent) {
85 fscache_stat(&fscache_n_acquires_null);
86 _leave(" [no parent]");
87 return NULL;
88 }
89
90 /* validate the definition */
ccc4fc3d
DH
91 BUG_ON(!def->name[0]);
92
93 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
402cb8dd 94 parent->type != FSCACHE_COOKIE_TYPE_INDEX);
ccc4fc3d
DH
95
96 /* allocate and initialise a cookie */
97 cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL);
98 if (!cookie) {
99 fscache_stat(&fscache_n_acquires_oom);
100 _leave(" [ENOMEM]");
101 return NULL;
102 }
103
402cb8dd
DH
104 cookie->key_len = index_key_len;
105 cookie->aux_len = aux_data_len;
106
107 if (cookie->key_len <= sizeof(cookie->inline_key)) {
108 memcpy(cookie->inline_key, index_key, cookie->key_len);
109 } else {
110 cookie->key = kmemdup(index_key, cookie->key_len, GFP_KERNEL);
111 if (!cookie->key)
112 goto nomem;
113 }
114
115 if (cookie->aux_len <= sizeof(cookie->inline_aux)) {
116 memcpy(cookie->inline_aux, aux_data, cookie->aux_len);
117 } else {
118 cookie->aux = kmemdup(aux_data, cookie->aux_len, GFP_KERNEL);
119 if (!cookie->aux)
120 goto nomem;
121 }
122
ccc4fc3d
DH
123 atomic_set(&cookie->usage, 1);
124 atomic_set(&cookie->n_children, 0);
125
1362729b
DH
126 /* We keep the active count elevated until relinquishment to prevent an
127 * attempt to wake up every time the object operations queue quiesces.
128 */
129 atomic_set(&cookie->n_active, 1);
130
a18feb55 131 fscache_cookie_get(parent, fscache_cookie_get_acquire_parent);
ccc4fc3d
DH
132 atomic_inc(&parent->n_children);
133
134 cookie->def = def;
135 cookie->parent = parent;
136 cookie->netfs_data = netfs_data;
94d30ae9 137 cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET);
402cb8dd
DH
138 cookie->type = def->type;
139
b34df792
DH
140 /* radix tree insertion won't use the preallocation pool unless it's
141 * told it may not wait */
d0164adc 142 INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
ccc4fc3d 143
402cb8dd 144 switch (cookie->type) {
ccc4fc3d
DH
145 case FSCACHE_COOKIE_TYPE_INDEX:
146 fscache_stat(&fscache_n_cookie_index);
147 break;
148 case FSCACHE_COOKIE_TYPE_DATAFILE:
149 fscache_stat(&fscache_n_cookie_data);
150 break;
151 default:
152 fscache_stat(&fscache_n_cookie_special);
153 break;
154 }
155
a18feb55
DH
156 trace_fscache_acquire(cookie);
157
94d30ae9
DH
158 if (enable) {
159 /* if the object is an index then we need do nothing more here
160 * - we create indices on disk when we need them as an index
161 * may exist in multiple caches */
402cb8dd 162 if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
94d30ae9
DH
163 if (fscache_acquire_non_index_cookie(cookie) == 0) {
164 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
165 } else {
166 atomic_dec(&parent->n_children);
a18feb55
DH
167 fscache_cookie_put(cookie,
168 fscache_cookie_put_acquire_nobufs);
94d30ae9
DH
169 fscache_stat(&fscache_n_acquires_nobufs);
170 _leave(" = NULL");
171 return NULL;
172 }
173 } else {
174 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
ccc4fc3d
DH
175 }
176 }
177
178 fscache_stat(&fscache_n_acquires_ok);
179 _leave(" = %p", cookie);
180 return cookie;
402cb8dd
DH
181
182nomem:
183 if (cookie->aux_len > sizeof(cookie->inline_aux))
184 kfree(cookie->aux);
185 if (cookie->key_len > sizeof(cookie->inline_key))
186 kfree(cookie->key);
187 kmem_cache_free(fscache_cookie_jar, cookie);
188 return NULL;
ccc4fc3d
DH
189}
190EXPORT_SYMBOL(__fscache_acquire_cookie);
191
94d30ae9
DH
192/*
193 * Enable a cookie to permit it to accept new operations.
194 */
195void __fscache_enable_cookie(struct fscache_cookie *cookie,
402cb8dd 196 const void *aux_data,
94d30ae9
DH
197 bool (*can_enable)(void *data),
198 void *data)
199{
200 _enter("%p", cookie);
201
a18feb55
DH
202 trace_fscache_enable(cookie);
203
94d30ae9 204 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
74316201 205 TASK_UNINTERRUPTIBLE);
94d30ae9 206
402cb8dd
DH
207 fscache_update_aux(cookie, aux_data);
208
94d30ae9
DH
209 if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
210 goto out_unlock;
211
212 if (can_enable && !can_enable(data)) {
213 /* The netfs decided it didn't want to enable after all */
402cb8dd 214 } else if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
94d30ae9
DH
215 /* Wait for outstanding disablement to complete */
216 __fscache_wait_on_invalidate(cookie);
217
218 if (fscache_acquire_non_index_cookie(cookie) == 0)
219 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
220 } else {
221 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
222 }
223
224out_unlock:
225 clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
226 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
227}
228EXPORT_SYMBOL(__fscache_enable_cookie);
229
ccc4fc3d
DH
230/*
231 * acquire a non-index cookie
232 * - this must make sure the index chain is instantiated and instantiate the
233 * object representation too
234 */
235static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
236{
237 struct fscache_object *object;
238 struct fscache_cache *cache;
239 uint64_t i_size;
240 int ret;
241
242 _enter("");
243
94d30ae9 244 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
ccc4fc3d
DH
245
246 /* now we need to see whether the backing objects for this cookie yet
247 * exist, if not there'll be nothing to search */
248 down_read(&fscache_addremove_sem);
249
250 if (list_empty(&fscache_cache_list)) {
251 up_read(&fscache_addremove_sem);
252 _leave(" = 0 [no caches]");
253 return 0;
254 }
255
256 /* select a cache in which to store the object */
257 cache = fscache_select_cache_for_object(cookie->parent);
258 if (!cache) {
259 up_read(&fscache_addremove_sem);
260 fscache_stat(&fscache_n_acquires_no_cache);
261 _leave(" = -ENOMEDIUM [no cache]");
262 return -ENOMEDIUM;
263 }
264
265 _debug("cache %s", cache->tag->name);
266
94d30ae9 267 set_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
ccc4fc3d
DH
268
269 /* ask the cache to allocate objects for this cookie and its parent
270 * chain */
271 ret = fscache_alloc_object(cache, cookie);
272 if (ret < 0) {
273 up_read(&fscache_addremove_sem);
274 _leave(" = %d", ret);
275 return ret;
276 }
277
278 /* pass on how big the object we're caching is supposed to be */
279 cookie->def->get_attr(cookie->netfs_data, &i_size);
280
281 spin_lock(&cookie->lock);
282 if (hlist_empty(&cookie->backing_objects)) {
283 spin_unlock(&cookie->lock);
284 goto unavailable;
285 }
286
287 object = hlist_entry(cookie->backing_objects.first,
288 struct fscache_object, cookie_link);
289
290 fscache_set_store_limit(object, i_size);
291
292 /* initiate the process of looking up all the objects in the chain
293 * (done by fscache_initialise_object()) */
caaef690 294 fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);
ccc4fc3d
DH
295
296 spin_unlock(&cookie->lock);
297
298 /* we may be required to wait for lookup to complete at this point */
299 if (!fscache_defer_lookup) {
300 _debug("non-deferred lookup %p", &cookie->flags);
301 wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
74316201 302 TASK_UNINTERRUPTIBLE);
ccc4fc3d
DH
303 _debug("complete");
304 if (test_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags))
305 goto unavailable;
306 }
307
308 up_read(&fscache_addremove_sem);
309 _leave(" = 0 [deferred]");
310 return 0;
311
312unavailable:
313 up_read(&fscache_addremove_sem);
314 _leave(" = -ENOBUFS");
315 return -ENOBUFS;
316}
317
318/*
319 * recursively allocate cache object records for a cookie/cache combination
320 * - caller must be holding the addremove sem
321 */
322static int fscache_alloc_object(struct fscache_cache *cache,
323 struct fscache_cookie *cookie)
324{
325 struct fscache_object *object;
ccc4fc3d
DH
326 int ret;
327
328 _enter("%p,%p{%s}", cache, cookie, cookie->def->name);
329
330 spin_lock(&cookie->lock);
b67bfe0d 331 hlist_for_each_entry(object, &cookie->backing_objects,
ccc4fc3d
DH
332 cookie_link) {
333 if (object->cache == cache)
334 goto object_already_extant;
335 }
336 spin_unlock(&cookie->lock);
337
338 /* ask the cache to allocate an object (we may end up with duplicate
339 * objects at this stage, but we sort that out later) */
52bd75fd 340 fscache_stat(&fscache_n_cop_alloc_object);
ccc4fc3d 341 object = cache->ops->alloc_object(cache, cookie);
52bd75fd 342 fscache_stat_d(&fscache_n_cop_alloc_object);
ccc4fc3d
DH
343 if (IS_ERR(object)) {
344 fscache_stat(&fscache_n_object_no_alloc);
345 ret = PTR_ERR(object);
346 goto error;
347 }
348
349 fscache_stat(&fscache_n_object_alloc);
350
351 object->debug_id = atomic_inc_return(&fscache_object_debug_id);
352
353 _debug("ALLOC OBJ%x: %s {%lx}",
354 object->debug_id, cookie->def->name, object->events);
355
356 ret = fscache_alloc_object(cache, cookie->parent);
357 if (ret < 0)
358 goto error_put;
359
360 /* only attach if we managed to allocate all we needed, otherwise
361 * discard the object we just allocated and instead use the one
362 * attached to the cookie */
52bd75fd
DH
363 if (fscache_attach_object(cookie, object) < 0) {
364 fscache_stat(&fscache_n_cop_put_object);
a18feb55 365 cache->ops->put_object(object, fscache_obj_put_attach_fail);
52bd75fd
DH
366 fscache_stat_d(&fscache_n_cop_put_object);
367 }
ccc4fc3d
DH
368
369 _leave(" = 0");
370 return 0;
371
372object_already_extant:
373 ret = -ENOBUFS;
87021526
DH
374 if (fscache_object_is_dying(object) ||
375 fscache_cache_is_broken(object)) {
ccc4fc3d
DH
376 spin_unlock(&cookie->lock);
377 goto error;
378 }
379 spin_unlock(&cookie->lock);
380 _leave(" = 0 [found]");
381 return 0;
382
383error_put:
52bd75fd 384 fscache_stat(&fscache_n_cop_put_object);
a18feb55 385 cache->ops->put_object(object, fscache_obj_put_alloc_fail);
52bd75fd 386 fscache_stat_d(&fscache_n_cop_put_object);
ccc4fc3d
DH
387error:
388 _leave(" = %d", ret);
389 return ret;
390}
391
392/*
393 * attach a cache object to a cookie
394 */
395static int fscache_attach_object(struct fscache_cookie *cookie,
396 struct fscache_object *object)
397{
398 struct fscache_object *p;
399 struct fscache_cache *cache = object->cache;
ccc4fc3d
DH
400 int ret;
401
402 _enter("{%s},{OBJ%x}", cookie->def->name, object->debug_id);
403
404 spin_lock(&cookie->lock);
405
406 /* there may be multiple initial creations of this object, but we only
407 * want one */
408 ret = -EEXIST;
b67bfe0d 409 hlist_for_each_entry(p, &cookie->backing_objects, cookie_link) {
ccc4fc3d 410 if (p->cache == object->cache) {
493f7bc1 411 if (fscache_object_is_dying(p))
ccc4fc3d
DH
412 ret = -ENOBUFS;
413 goto cant_attach_object;
414 }
415 }
416
417 /* pin the parent object */
418 spin_lock_nested(&cookie->parent->lock, 1);
b67bfe0d 419 hlist_for_each_entry(p, &cookie->parent->backing_objects,
ccc4fc3d
DH
420 cookie_link) {
421 if (p->cache == object->cache) {
493f7bc1 422 if (fscache_object_is_dying(p)) {
ccc4fc3d
DH
423 ret = -ENOBUFS;
424 spin_unlock(&cookie->parent->lock);
425 goto cant_attach_object;
426 }
427 object->parent = p;
428 spin_lock(&p->lock);
429 p->n_children++;
430 spin_unlock(&p->lock);
431 break;
432 }
433 }
434 spin_unlock(&cookie->parent->lock);
435
436 /* attach to the cache's object list */
437 if (list_empty(&object->cache_link)) {
438 spin_lock(&cache->object_list_lock);
439 list_add(&object->cache_link, &cache->object_list);
440 spin_unlock(&cache->object_list_lock);
441 }
442
443 /* attach to the cookie */
444 object->cookie = cookie;
a18feb55 445 fscache_cookie_get(cookie, fscache_cookie_get_attach_object);
ccc4fc3d 446 hlist_add_head(&object->cookie_link, &cookie->backing_objects);
4fbf4291
DH
447
448 fscache_objlist_add(object);
ccc4fc3d
DH
449 ret = 0;
450
451cant_attach_object:
452 spin_unlock(&cookie->lock);
453 _leave(" = %d", ret);
454 return ret;
455}
456
ef778e7a
DH
457/*
458 * Invalidate an object. Callable with spinlocks held.
459 */
460void __fscache_invalidate(struct fscache_cookie *cookie)
461{
462 struct fscache_object *object;
463
464 _enter("{%s}", cookie->def->name);
465
466 fscache_stat(&fscache_n_invalidates);
467
468 /* Only permit invalidation of data files. Invalidating an index will
469 * require the caller to release all its attachments to the tree rooted
470 * there, and if it's doing that, it may as well just retire the
471 * cookie.
472 */
402cb8dd 473 ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
ef778e7a
DH
474
475 /* If there's an object, we tell the object state machine to handle the
476 * invalidation on our behalf, otherwise there's nothing to do.
477 */
478 if (!hlist_empty(&cookie->backing_objects)) {
479 spin_lock(&cookie->lock);
480
94d30ae9
DH
481 if (fscache_cookie_enabled(cookie) &&
482 !hlist_empty(&cookie->backing_objects) &&
ef778e7a
DH
483 !test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
484 &cookie->flags)) {
485 object = hlist_entry(cookie->backing_objects.first,
486 struct fscache_object,
487 cookie_link);
493f7bc1 488 if (fscache_object_is_live(object))
ef778e7a
DH
489 fscache_raise_event(
490 object, FSCACHE_OBJECT_EV_INVALIDATE);
491 }
492
493 spin_unlock(&cookie->lock);
494 }
495
496 _leave("");
497}
498EXPORT_SYMBOL(__fscache_invalidate);
499
500/*
501 * Wait for object invalidation to complete.
502 */
503void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
504{
505 _enter("%p", cookie);
506
507 wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
ef778e7a
DH
508 TASK_UNINTERRUPTIBLE);
509
510 _leave("");
511}
512EXPORT_SYMBOL(__fscache_wait_on_invalidate);
513
ccc4fc3d
DH
514/*
515 * update the index entries backing a cookie
516 */
402cb8dd 517void __fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data)
ccc4fc3d
DH
518{
519 struct fscache_object *object;
ccc4fc3d
DH
520
521 fscache_stat(&fscache_n_updates);
522
523 if (!cookie) {
524 fscache_stat(&fscache_n_updates_null);
525 _leave(" [no cookie]");
526 return;
527 }
528
529 _enter("{%s}", cookie->def->name);
530
ccc4fc3d
DH
531 spin_lock(&cookie->lock);
532
402cb8dd
DH
533 fscache_update_aux(cookie, aux_data);
534
94d30ae9
DH
535 if (fscache_cookie_enabled(cookie)) {
536 /* update the index entry on disk in each cache backing this
537 * cookie.
538 */
539 hlist_for_each_entry(object,
540 &cookie->backing_objects, cookie_link) {
541 fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
542 }
ccc4fc3d
DH
543 }
544
545 spin_unlock(&cookie->lock);
546 _leave("");
547}
548EXPORT_SYMBOL(__fscache_update_cookie);
549
550/*
94d30ae9 551 * Disable a cookie to stop it from accepting new requests from the netfs.
ccc4fc3d 552 */
402cb8dd
DH
553void __fscache_disable_cookie(struct fscache_cookie *cookie,
554 const void *aux_data,
555 bool invalidate)
ccc4fc3d 556{
ccc4fc3d 557 struct fscache_object *object;
94d30ae9 558 bool awaken = false;
ccc4fc3d 559
94d30ae9 560 _enter("%p,%u", cookie, invalidate);
1362729b 561
a18feb55
DH
562 trace_fscache_disable(cookie);
563
1362729b 564 ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
ccc4fc3d
DH
565
566 if (atomic_read(&cookie->n_children) != 0) {
36dfd116 567 pr_err("Cookie '%s' still has children\n",
ccc4fc3d
DH
568 cookie->def->name);
569 BUG();
570 }
571
94d30ae9 572 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
74316201 573 TASK_UNINTERRUPTIBLE);
402cb8dd
DH
574
575 fscache_update_aux(cookie, aux_data);
576
94d30ae9
DH
577 if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
578 goto out_unlock_enable;
579
580 /* If the cookie is being invalidated, wait for that to complete first
581 * so that we can reuse the flag.
582 */
583 __fscache_wait_on_invalidate(cookie);
584
585 /* Dispose of the backing objects */
586 set_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags);
ccc4fc3d 587
ccc4fc3d 588 spin_lock(&cookie->lock);
94d30ae9
DH
589 if (!hlist_empty(&cookie->backing_objects)) {
590 hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
591 if (invalidate)
592 set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
6bdded59 593 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
94d30ae9
DH
594 fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
595 }
596 } else {
597 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
598 awaken = true;
ccc4fc3d 599 }
1362729b 600 spin_unlock(&cookie->lock);
94d30ae9
DH
601 if (awaken)
602 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
ccc4fc3d 603
1362729b 604 /* Wait for cessation of activity requiring access to the netfs (when
94d30ae9
DH
605 * n_active reaches 0). This makes sure outstanding reads and writes
606 * have completed.
1362729b 607 */
dc5d4afb
PZ
608 if (!atomic_dec_and_test(&cookie->n_active)) {
609 wait_var_event(&cookie->n_active,
610 !atomic_read(&cookie->n_active));
611 }
1362729b 612
6bdded59 613 /* Make sure any pending writes are cancelled. */
402cb8dd 614 if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX)
6bdded59
DH
615 fscache_invalidate_writes(cookie);
616
94d30ae9
DH
617 /* Reset the cookie state if it wasn't relinquished */
618 if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
619 atomic_inc(&cookie->n_active);
620 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
621 }
622
623out_unlock_enable:
624 clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
625 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
626 _leave("");
627}
628EXPORT_SYMBOL(__fscache_disable_cookie);
629
630/*
631 * release a cookie back to the cache
632 * - the object will be marked as recyclable on disk if retire is true
633 * - all dependents of this cookie must have already been unregistered
634 * (indices/files/pages)
635 */
402cb8dd
DH
636void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
637 const void *aux_data,
638 bool retire)
94d30ae9
DH
639{
640 fscache_stat(&fscache_n_relinquishes);
641 if (retire)
642 fscache_stat(&fscache_n_relinquishes_retire);
643
644 if (!cookie) {
645 fscache_stat(&fscache_n_relinquishes_null);
646 _leave(" [no cookie]");
647 return;
648 }
649
650 _enter("%p{%s,%p,%d},%d",
651 cookie, cookie->def->name, cookie->netfs_data,
652 atomic_read(&cookie->n_active), retire);
653
a18feb55
DH
654 trace_fscache_relinquish(cookie, retire);
655
94d30ae9 656 /* No further netfs-accessing operations on this cookie permitted */
d0fb31ec
DH
657 if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags))
658 BUG();
94d30ae9 659
402cb8dd 660 __fscache_disable_cookie(cookie, aux_data, retire);
94d30ae9 661
1362729b 662 /* Clear pointers back to the netfs */
7e311a20
DH
663 cookie->netfs_data = NULL;
664 cookie->def = NULL;
1362729b 665 BUG_ON(cookie->stores.rnode);
ccc4fc3d
DH
666
667 if (cookie->parent) {
668 ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0);
669 ASSERTCMP(atomic_read(&cookie->parent->n_children), >, 0);
670 atomic_dec(&cookie->parent->n_children);
671 }
672
1362729b 673 /* Dispose of the netfs's link to the cookie */
ccc4fc3d 674 ASSERTCMP(atomic_read(&cookie->usage), >, 0);
a18feb55 675 fscache_cookie_put(cookie, fscache_cookie_put_relinquish);
ccc4fc3d
DH
676
677 _leave("");
678}
679EXPORT_SYMBOL(__fscache_relinquish_cookie);
680
955d0091 681/*
a18feb55 682 * Drop a reference to a cookie.
955d0091 683 */
a18feb55
DH
684void fscache_cookie_put(struct fscache_cookie *cookie,
685 enum fscache_cookie_trace where)
955d0091
DH
686{
687 struct fscache_cookie *parent;
a18feb55 688 int usage;
955d0091
DH
689
690 _enter("%p", cookie);
691
a18feb55
DH
692 do {
693 usage = atomic_dec_return(&cookie->usage);
694 trace_fscache_cookie(cookie, where, usage);
695
696 if (usage > 0)
697 return;
698 BUG_ON(usage < 0);
699
955d0091
DH
700 parent = cookie->parent;
701 BUG_ON(!hlist_empty(&cookie->backing_objects));
402cb8dd
DH
702 if (cookie->aux_len > sizeof(cookie->inline_aux))
703 kfree(cookie->aux);
704 if (cookie->key_len > sizeof(cookie->inline_key))
705 kfree(cookie->key);
955d0091
DH
706 kmem_cache_free(fscache_cookie_jar, cookie);
707
955d0091 708 cookie = parent;
a18feb55
DH
709 where = fscache_cookie_put_parent;
710 } while (cookie);
955d0091
DH
711
712 _leave("");
713}
da9803bc
DH
714
715/*
716 * check the consistency between the netfs inode and the backing cache
717 *
718 * NOTE: it only serves no-index type
719 */
402cb8dd
DH
720int __fscache_check_consistency(struct fscache_cookie *cookie,
721 const void *aux_data)
da9803bc
DH
722{
723 struct fscache_operation *op;
724 struct fscache_object *object;
8fb883f3 725 bool wake_cookie = false;
da9803bc
DH
726 int ret;
727
728 _enter("%p,", cookie);
729
402cb8dd 730 ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
da9803bc
DH
731
732 if (fscache_wait_for_deferred_lookup(cookie) < 0)
733 return -ERESTARTSYS;
734
735 if (hlist_empty(&cookie->backing_objects))
736 return 0;
737
738 op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY);
739 if (!op)
740 return -ENOMEM;
741
08c2e3d0 742 fscache_operation_init(cookie, op, NULL, NULL, NULL);
da9803bc 743 op->flags = FSCACHE_OP_MYTHREAD |
9c89d629
MT
744 (1 << FSCACHE_OP_WAITING) |
745 (1 << FSCACHE_OP_UNUSE_COOKIE);
08c2e3d0 746 trace_fscache_page_op(cookie, NULL, op, fscache_page_op_check_consistency);
da9803bc
DH
747
748 spin_lock(&cookie->lock);
749
402cb8dd
DH
750 fscache_update_aux(cookie, aux_data);
751
94d30ae9
DH
752 if (!fscache_cookie_enabled(cookie) ||
753 hlist_empty(&cookie->backing_objects))
da9803bc
DH
754 goto inconsistent;
755 object = hlist_entry(cookie->backing_objects.first,
756 struct fscache_object, cookie_link);
757 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
758 goto inconsistent;
759
760 op->debug_id = atomic_inc_return(&fscache_op_debug_id);
761
8fb883f3 762 __fscache_use_cookie(cookie);
da9803bc
DH
763 if (fscache_submit_op(object, op) < 0)
764 goto submit_failed;
765
766 /* the work queue now carries its own ref on the object */
767 spin_unlock(&cookie->lock);
768
d3b97ca4 769 ret = fscache_wait_for_operation_activation(object, op, NULL, NULL);
da9803bc
DH
770 if (ret == 0) {
771 /* ask the cache to honour the operation */
772 ret = object->cache->ops->check_consistency(op);
773 fscache_op_complete(op, false);
774 } else if (ret == -ENOBUFS) {
775 ret = 0;
776 }
777
778 fscache_put_operation(op);
779 _leave(" = %d", ret);
780 return ret;
781
782submit_failed:
8fb883f3 783 wake_cookie = __fscache_unuse_cookie(cookie);
da9803bc
DH
784inconsistent:
785 spin_unlock(&cookie->lock);
8fb883f3
DH
786 if (wake_cookie)
787 __fscache_wake_unused_cookie(cookie);
da9803bc
DH
788 kfree(op);
789 _leave(" = -ESTALE");
790 return -ESTALE;
791}
792EXPORT_SYMBOL(__fscache_check_consistency);