1 /* cookie.c: general filesystem cache cookie management
3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/module.h>
13 #include "fscache-int.h"
15 static LIST_HEAD(fscache_cache_tag_list);
16 static LIST_HEAD(fscache_cache_list);
17 static LIST_HEAD(fscache_netfs_list);
18 static DECLARE_RWSEM(fscache_addremove_sem);
19 static struct fscache_cache_tag fscache_nomem_tag;
21 kmem_cache_t *fscache_cookie_jar;
23 static void fscache_withdraw_object(struct fscache_cache *cache,
24 struct fscache_object *object);
26 static void __fscache_cookie_put(struct fscache_cookie *cookie);
28 static inline void fscache_cookie_put(struct fscache_cookie *cookie)
30 /* check to see whether the cookie has already been released by looking
31 * for the poison when slab debugging is on */
32 #ifdef CONFIG_DEBUG_SLAB
33 BUG_ON((atomic_read(&cookie->usage) & 0xffff0000) == 0x6b6b0000);
36 BUG_ON(atomic_read(&cookie->usage) <= 0);
38 if (atomic_dec_and_test(&cookie->usage))
39 __fscache_cookie_put(cookie);
43 /*****************************************************************************/
47 struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
49 struct fscache_cache_tag *tag, *xtag;
51 /* firstly check for the existence of the tag under read lock */
52 down_read(&fscache_addremove_sem);
54 list_for_each_entry(tag, &fscache_cache_tag_list, link) {
55 if (strcmp(tag->name, name) == 0) {
56 atomic_inc(&tag->usage);
57 up_read(&fscache_addremove_sem);
62 up_read(&fscache_addremove_sem);
64 /* the tag does not exist - create a candidate */
65 xtag = kmalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL);
67 /* return a dummy tag if out of memory */
68 return &fscache_nomem_tag;
70 atomic_set(&xtag->usage, 1);
71 strcpy(xtag->name, name);
73 /* write lock, search again and add if still not present */
74 down_write(&fscache_addremove_sem);
76 list_for_each_entry(tag, &fscache_cache_tag_list, link) {
77 if (strcmp(tag->name, name) == 0) {
78 atomic_inc(&tag->usage);
79 up_write(&fscache_addremove_sem);
85 list_add_tail(&xtag->link, &fscache_cache_tag_list);
86 up_write(&fscache_addremove_sem);
90 /*****************************************************************************/
92 * release a reference to a cache tag
94 void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
96 if (tag != &fscache_nomem_tag) {
97 down_write(&fscache_addremove_sem);
99 if (atomic_dec_and_test(&tag->usage))
100 list_del_init(&tag->link);
104 up_write(&fscache_addremove_sem);
110 /*****************************************************************************/
112 * register a network filesystem for caching
114 int __fscache_register_netfs(struct fscache_netfs *netfs)
116 struct fscache_netfs *ptr;
119 _enter("{%s}", netfs->name);
121 INIT_LIST_HEAD(&netfs->link);
123 /* allocate a cookie for the primary index */
124 netfs->primary_index =
125 kmem_cache_zalloc(fscache_cookie_jar, SLAB_KERNEL);
127 if (!netfs->primary_index) {
128 _leave(" = -ENOMEM");
132 /* initialise the primary index cookie */
133 atomic_set(&netfs->primary_index->usage, 1);
134 atomic_set(&netfs->primary_index->children, 0);
136 netfs->primary_index->def = &fscache_fsdef_netfs_def;
137 netfs->primary_index->parent = &fscache_fsdef_index;
138 netfs->primary_index->netfs = netfs;
139 netfs->primary_index->netfs_data = netfs;
141 atomic_inc(&netfs->primary_index->parent->usage);
142 atomic_inc(&netfs->primary_index->parent->children);
144 init_rwsem(&netfs->primary_index->sem);
145 INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
147 /* check the netfs type is not already present */
148 down_write(&fscache_addremove_sem);
151 list_for_each_entry(ptr, &fscache_netfs_list, link) {
152 if (strcmp(ptr->name, netfs->name) == 0)
153 goto already_registered;
156 list_add(&netfs->link, &fscache_netfs_list);
159 printk("FS-Cache: netfs '%s' registered for caching\n", netfs->name);
162 up_write(&fscache_addremove_sem);
165 netfs->primary_index->parent = NULL;
166 __fscache_cookie_put(netfs->primary_index);
167 netfs->primary_index = NULL;
170 _leave(" = %d", ret);
174 EXPORT_SYMBOL(__fscache_register_netfs);
176 /*****************************************************************************/
178 * unregister a network filesystem from the cache
179 * - all cookies must have been released first
181 void __fscache_unregister_netfs(struct fscache_netfs *netfs)
183 _enter("{%s.%u}", netfs->name, netfs->version);
185 down_write(&fscache_addremove_sem);
187 list_del(&netfs->link);
188 fscache_relinquish_cookie(netfs->primary_index, 0);
190 up_write(&fscache_addremove_sem);
192 printk("FS-Cache: netfs '%s' unregistered from caching\n",
198 EXPORT_SYMBOL(__fscache_unregister_netfs);
200 /*****************************************************************************/
202 * initialise a cache record
204 void fscache_init_cache(struct fscache_cache *cache,
205 struct fscache_cache_ops *ops,
211 memset(cache, 0, sizeof(*cache));
216 vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va);
219 INIT_LIST_HEAD(&cache->link);
220 INIT_LIST_HEAD(&cache->object_list);
221 spin_lock_init(&cache->object_list_lock);
222 init_rwsem(&cache->withdrawal_sem);
225 EXPORT_SYMBOL(fscache_init_cache);
227 /*****************************************************************************/
229 * declare a mounted cache as being open for business
231 int fscache_add_cache(struct fscache_cache *cache,
232 struct fscache_object *ifsdef,
235 struct fscache_cache_tag *tag;
243 tagname = cache->identifier;
247 _enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname);
249 if (!cache->ops->grab_object(ifsdef))
252 ifsdef->cookie = &fscache_fsdef_index;
253 ifsdef->cache = cache;
254 cache->fsdef = ifsdef;
256 down_write(&fscache_addremove_sem);
258 /* instantiate or allocate a cache tag */
259 list_for_each_entry(tag, &fscache_cache_tag_list, link) {
260 if (strcmp(tag->name, tagname) == 0) {
263 "FS-Cache: cache tag '%s' already in use\n",
265 up_write(&fscache_addremove_sem);
269 atomic_inc(&tag->usage);
270 goto found_cache_tag;
274 tag = kmalloc(sizeof(*tag) + strlen(tagname) + 1, GFP_KERNEL);
276 up_write(&fscache_addremove_sem);
280 atomic_set(&tag->usage, 1);
281 strcpy(tag->name, tagname);
282 list_add_tail(&tag->link, &fscache_cache_tag_list);
288 /* add the cache to the list */
289 list_add(&cache->link, &fscache_cache_list);
291 /* add the cache's netfs definition index object to the cache's
293 spin_lock(&cache->object_list_lock);
294 list_add_tail(&ifsdef->cache_link, &cache->object_list);
295 spin_unlock(&cache->object_list_lock);
297 /* add the cache's netfs definition index object to the top level index
298 * cookie as a known backing object */
299 down_write(&fscache_fsdef_index.sem);
301 hlist_add_head(&ifsdef->cookie_link,
302 &fscache_fsdef_index.backing_objects);
304 atomic_inc(&fscache_fsdef_index.usage);
307 up_write(&fscache_fsdef_index.sem);
308 up_write(&fscache_addremove_sem);
311 "FS-Cache: Cache \"%s\" added (type %s)\n",
312 cache->tag->name, cache->ops->name);
314 _leave(" = 0 [%s]", cache->identifier);
318 EXPORT_SYMBOL(fscache_add_cache);
320 /*****************************************************************************/
322 * note a cache I/O error
324 void fscache_io_error(struct fscache_cache *cache)
326 set_bit(FSCACHE_IOERROR, &cache->flags);
328 printk(KERN_ERR "FS-Cache: Cache %s stopped due to I/O error\n",
332 EXPORT_SYMBOL(fscache_io_error);
334 /*****************************************************************************/
336 * withdraw an unmounted cache from the active service
338 void fscache_withdraw_cache(struct fscache_cache *cache)
340 struct fscache_object *object;
345 "FS-Cache: Withdrawing cache \"%s\"\n",
348 /* make the cache unavailable for cookie acquisition */
349 down_write(&cache->withdrawal_sem);
351 down_write(&fscache_addremove_sem);
352 list_del_init(&cache->link);
353 cache->tag->cache = NULL;
354 up_write(&fscache_addremove_sem);
356 /* mark all objects as being withdrawn */
357 spin_lock(&cache->object_list_lock);
358 list_for_each_entry(object, &cache->object_list, cache_link) {
359 set_bit(FSCACHE_OBJECT_WITHDRAWN, &object->flags);
361 spin_unlock(&cache->object_list_lock);
363 /* make sure all pages pinned by operations on behalf of the netfs are
365 cache->ops->sync_cache(cache);
367 /* dissociate all the netfs pages backed by this cache from the block
368 * mappings in the cache */
369 cache->ops->dissociate_pages(cache);
371 /* we now have to destroy all the active objects pertaining to this
373 spin_lock(&cache->object_list_lock);
375 while (!list_empty(&cache->object_list)) {
376 object = list_entry(cache->object_list.next,
377 struct fscache_object, cache_link);
378 list_del_init(&object->cache_link);
379 spin_unlock(&cache->object_list_lock);
381 _debug("withdraw %p", object->cookie);
383 /* we've extracted an active object from the tree - now dispose
385 fscache_withdraw_object(cache, object);
387 spin_lock(&cache->object_list_lock);
390 spin_unlock(&cache->object_list_lock);
392 fscache_release_cache_tag(cache->tag);
398 EXPORT_SYMBOL(fscache_withdraw_cache);
400 /*****************************************************************************/
402 * withdraw an object from active service at the behest of the cache
403 * - need break the links to a cached object cookie
404 * - called under two situations:
405 * (1) recycler decides to reclaim an in-use object
406 * (2) a cache is unmounted
407 * - have to take care as the cookie can be being relinquished by the netfs
409 * - the active object is pinned by the caller holding a refcount on it
411 static void fscache_withdraw_object(struct fscache_cache *cache,
412 struct fscache_object *object)
414 struct fscache_cookie *cookie, *xcookie = NULL;
416 _enter(",%p", object);
418 /* first of all we have to break the links between the object and the
420 * - we have to hold both semaphores BUT we have to get the cookie sem
423 cache->ops->lock_object(object);
425 cookie = object->cookie;
427 /* pin the cookie so that is doesn't escape */
428 atomic_inc(&cookie->usage);
430 /* re-order the locks to avoid deadlock */
431 cache->ops->unlock_object(object);
432 down_write(&cookie->sem);
433 cache->ops->lock_object(object);
435 /* erase references from the object to the cookie */
436 hlist_del_init(&object->cookie_link);
438 xcookie = object->cookie;
439 object->cookie = NULL;
441 up_write(&cookie->sem);
444 cache->ops->unlock_object(object);
446 /* we've broken the links between cookie and object */
448 fscache_cookie_put(xcookie);
449 cache->ops->put_object(object);
452 /* unpin the cookie */
454 if (cookie->def && cookie->def->now_uncached)
455 cookie->def->now_uncached(cookie->netfs_data);
456 fscache_cookie_put(cookie);
462 /*****************************************************************************/
464 * select a cache on which to store an object
465 * - the cache addremove semaphore must be at least read-locked by the caller
466 * - the object will never be an index
468 static struct fscache_cache *fscache_select_cache_for_object(struct fscache_cookie *cookie)
470 struct fscache_cache_tag *tag;
471 struct fscache_object *object;
472 struct fscache_cache *cache;
476 if (list_empty(&fscache_cache_list)) {
477 _leave(" = NULL [no cache]");
481 /* we check the parent to determine the cache to use */
482 down_read(&cookie->parent->sem);
484 /* the first in the parent's backing list should be the preferred
486 if (!hlist_empty(&cookie->parent->backing_objects)) {
487 object = hlist_entry(cookie->parent->backing_objects.first,
488 struct fscache_object, cookie_link);
490 cache = object->cache;
491 if (test_bit(FSCACHE_IOERROR, &cache->flags))
494 up_read(&cookie->parent->sem);
495 _leave(" = %p [parent]", cache);
499 /* the parent is unbacked */
500 if (cookie->parent->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
501 /* parent not an index and is unbacked */
502 up_read(&cookie->parent->sem);
503 _leave(" = NULL [parent ubni]");
507 up_read(&cookie->parent->sem);
509 if (!cookie->parent->def->select_cache)
512 /* ask the netfs for its preference */
513 tag = cookie->parent->def->select_cache(
514 cookie->parent->parent->netfs_data,
515 cookie->parent->netfs_data);
520 if (tag == &fscache_nomem_tag) {
521 _leave(" = NULL [nomem tag]");
526 _leave(" = NULL [unbacked tag]");
530 if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
533 _leave(" = %p [specific]", tag->cache);
537 /* netfs has no preference - just select first cache */
538 cache = list_entry(fscache_cache_list.next,
539 struct fscache_cache, link);
540 _leave(" = %p [first]", cache);
544 /*****************************************************************************/
546 * get a backing object for a cookie from the chosen cache
547 * - the cookie must be write-locked by the caller
548 * - all parent indexes will be obtained recursively first
550 static struct fscache_object *fscache_lookup_object(struct fscache_cookie *cookie,
551 struct fscache_cache *cache)
553 struct fscache_cookie *parent = cookie->parent;
554 struct fscache_object *pobject, *object;
555 struct hlist_node *_p;
558 parent && parent->def ? parent->def->name : "",
559 cookie->def ? (char *) cookie->def->name : "<file>");
561 if (test_bit(FSCACHE_IOERROR, &cache->flags))
564 /* see if we have the backing object for this cookie + cache immediately
568 hlist_for_each_entry(object, _p,
569 &cookie->backing_objects, cookie_link
571 if (object->cache == cache)
576 _leave(" = %p [old]", object);
580 BUG_ON(!parent); /* FSDEF entries don't have a parent */
582 /* we don't have a backing cookie, so we need to consult the object's
583 * parent index in the selected cache and maybe insert an entry
584 * therein; so the first thing to do is make sure that the parent index
585 * is represented on disc
587 down_read(&parent->sem);
590 hlist_for_each_entry(pobject, _p,
591 &parent->backing_objects, cookie_link
593 if (pobject->cache == cache)
598 /* we don't know about the parent object */
599 up_read(&parent->sem);
600 down_write(&parent->sem);
602 pobject = fscache_lookup_object(parent, cache);
603 if (IS_ERR(pobject)) {
604 up_write(&parent->sem);
605 _leave(" = %ld [no ipobj]", PTR_ERR(pobject));
609 _debug("pobject=%p", pobject);
611 BUG_ON(pobject->cookie != parent);
613 downgrade_write(&parent->sem);
616 /* now we can attempt to look up this object in the parent, possibly
617 * creating a representation on disc when we do so
619 object = cache->ops->lookup_object(cache, pobject, cookie);
620 up_read(&parent->sem);
622 if (IS_ERR(object)) {
623 _leave(" = %ld [no obj]", PTR_ERR(object));
627 /* keep track of it */
628 cache->ops->lock_object(object);
630 BUG_ON(!hlist_unhashed(&object->cookie_link));
632 /* attach to the cache's object list */
633 if (list_empty(&object->cache_link)) {
634 spin_lock(&cache->object_list_lock);
635 list_add(&object->cache_link, &cache->object_list);
636 spin_unlock(&cache->object_list_lock);
639 /* attach to the cookie */
640 object->cookie = cookie;
641 atomic_inc(&cookie->usage);
642 hlist_add_head(&object->cookie_link, &cookie->backing_objects);
645 cache->ops->unlock_object(object);
646 _leave(" = %p [new]", object);
650 /*****************************************************************************/
652 * request a cookie to represent an object (index, datafile, xattr, etc)
653 * - parent specifies the parent object
654 * - the top level index cookie for each netfs is stored in the fscache_netfs
655 * struct upon registration
656 * - idef points to the definition
657 * - the netfs_data will be passed to the functions pointed to in *def
658 * - all attached caches will be searched to see if they contain this object
659 * - index objects aren't stored on disk until there's a dependent file that
661 * - other objects are stored in a selected cache immediately, and all the
662 * indexes forming the path to it are instantiated if necessary
663 * - we never let on to the netfs about errors
664 * - we may set a negative cookie pointer, but that's okay
666 struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent,
667 struct fscache_cookie_def *def,
670 struct fscache_cookie *cookie;
671 struct fscache_cache *cache;
672 struct fscache_object *object;
677 _enter("{%s},{%s},%p",
678 parent ? (char *) parent->def->name : "<no-parent>",
679 def->name, netfs_data);
681 /* if there's no parent cookie, then we don't create one here either */
683 _leave(" [no parent]");
687 /* validate the definition */
688 BUG_ON(!def->get_key);
689 BUG_ON(!def->name[0]);
691 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
692 parent->def->type != FSCACHE_COOKIE_TYPE_INDEX);
694 /* allocate and initialise a cookie */
695 cookie = kmem_cache_alloc(fscache_cookie_jar, SLAB_KERNEL);
701 atomic_set(&cookie->usage, 1);
702 atomic_set(&cookie->children, 0);
704 atomic_inc(&parent->usage);
705 atomic_inc(&parent->children);
708 cookie->parent = parent;
709 cookie->netfs = parent->netfs;
710 cookie->netfs_data = netfs_data;
712 /* now we need to see whether the backing objects for this cookie yet
713 * exist, if not there'll be nothing to search */
714 down_read(&fscache_addremove_sem);
716 if (list_empty(&fscache_cache_list)) {
717 up_read(&fscache_addremove_sem);
718 _leave(" = %p [no caches]", cookie);
722 /* if the object is an index then we need do nothing more here - we
723 * create indexes on disk when we need them as an index may exist in
725 if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
726 down_write(&cookie->sem);
728 /* the object is a file - we need to select a cache in which to
730 cache = fscache_select_cache_for_object(cookie);
732 goto no_cache; /* couldn't decide on a cache */
734 /* create a file index entry on disc, along with all the
735 * indexes required to find it again later */
736 object = fscache_lookup_object(cookie, cache);
737 if (IS_ERR(object)) {
738 ret = PTR_ERR(object);
742 up_write(&cookie->sem);
745 up_read(&fscache_addremove_sem);
746 _leave(" = %p", cookie);
753 printk(KERN_ERR "FS-Cache: error from cache: %d\n", ret);
756 up_write(&cookie->sem);
757 __fscache_cookie_put(cookie);
759 atomic_dec(&parent->children);
765 EXPORT_SYMBOL(__fscache_acquire_cookie);
767 /*****************************************************************************/
769 * release a cookie back to the cache
770 * - the object will be marked as recyclable on disc if retire is true
771 * - all dependents of this cookie must have already been unregistered
772 * (indexes/files/pages)
774 void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
776 struct fscache_cache *cache;
777 struct fscache_object *object;
778 struct hlist_node *_p;
781 _leave(" [no cookie]");
785 _enter("%p{%s},%d", cookie, cookie->def->name, retire);
787 if (atomic_read(&cookie->children) != 0) {
788 printk("FS-Cache: cookie still has children\n");
792 /* detach pointers back to the netfs */
793 down_write(&cookie->sem);
795 cookie->netfs_data = NULL;
798 /* mark retired objects for recycling */
800 hlist_for_each_entry(object, _p,
801 &cookie->backing_objects,
804 set_bit(FSCACHE_OBJECT_RECYCLING, &object->flags);
808 /* break links with all the active objects */
809 while (!hlist_empty(&cookie->backing_objects)) {
810 object = hlist_entry(cookie->backing_objects.first,
811 struct fscache_object,
814 /* detach each cache object from the object cookie */
815 set_bit(FSCACHE_OBJECT_RELEASING, &object->flags);
817 hlist_del_init(&object->cookie_link);
819 cache = object->cache;
820 cache->ops->lock_object(object);
821 object->cookie = NULL;
822 cache->ops->unlock_object(object);
824 if (atomic_dec_and_test(&cookie->usage))
825 /* the cookie refcount shouldn't be reduced to 0 yet */
828 spin_lock(&cache->object_list_lock);
829 list_del_init(&object->cache_link);
830 spin_unlock(&cache->object_list_lock);
832 cache->ops->put_object(object);
835 up_write(&cookie->sem);
837 if (cookie->parent) {
838 #ifdef CONFIG_DEBUG_SLAB
839 BUG_ON((atomic_read(&cookie->parent->children) & 0xffff0000) == 0x6b6b0000);
841 atomic_dec(&cookie->parent->children);
844 /* finally dispose of the cookie */
845 fscache_cookie_put(cookie);
850 EXPORT_SYMBOL(__fscache_relinquish_cookie);
852 /*****************************************************************************/
854 * update the index entries backing a cookie
856 void __fscache_update_cookie(struct fscache_cookie *cookie)
858 struct fscache_object *object;
859 struct hlist_node *_p;
862 _leave(" [no cookie]");
866 _enter("{%s}", cookie->def->name);
868 BUG_ON(!cookie->def->get_aux);
870 down_write(&cookie->sem);
871 down_read(&cookie->parent->sem);
873 /* update the index entry on disc in each cache backing this cookie */
874 hlist_for_each_entry(object, _p,
875 &cookie->backing_objects, cookie_link
877 if (!test_bit(FSCACHE_IOERROR, &object->cache->flags))
878 object->cache->ops->update_object(object);
881 up_read(&cookie->parent->sem);
882 up_write(&cookie->sem);
886 EXPORT_SYMBOL(__fscache_update_cookie);
888 /*****************************************************************************/
892 static void __fscache_cookie_put(struct fscache_cookie *cookie)
894 struct fscache_cookie *parent;
896 _enter("%p", cookie);
899 parent = cookie->parent;
900 BUG_ON(!hlist_empty(&cookie->backing_objects));
901 kmem_cache_free(fscache_cookie_jar, cookie);
907 BUG_ON(atomic_read(&cookie->usage) <= 0);
908 if (!atomic_dec_and_test(&cookie->usage))
915 /*****************************************************************************/
917 * initialise an cookie jar slab element prior to any use
919 void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep,
922 struct fscache_cookie *cookie = _cookie;
924 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
925 SLAB_CTOR_CONSTRUCTOR) {
926 memset(cookie, 0, sizeof(*cookie));
927 init_rwsem(&cookie->sem);
928 INIT_HLIST_HEAD(&cookie->backing_objects);
932 /*****************************************************************************/
934 * pin an object into the cache
936 int __fscache_pin_cookie(struct fscache_cookie *cookie)
938 struct fscache_object *object;
941 _enter("%p", cookie);
943 if (hlist_empty(&cookie->backing_objects)) {
944 _leave(" = -ENOBUFS");
948 /* not supposed to use this for indexes */
949 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
951 /* prevent the file from being uncached whilst we access it and exclude
952 * read and write attempts on pages
954 down_write(&cookie->sem);
957 if (!hlist_empty(&cookie->backing_objects)) {
958 /* get and pin the backing object */
959 object = hlist_entry(cookie->backing_objects.first,
960 struct fscache_object, cookie_link);
962 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
965 if (!object->cache->ops->pin_object) {
970 /* prevent the cache from being withdrawn */
971 if (fscache_operation_lock(object)) {
972 if (object->cache->ops->grab_object(object)) {
973 /* ask the cache to honour the operation */
974 ret = object->cache->ops->pin_object(object);
976 object->cache->ops->put_object(object);
979 fscache_operation_unlock(object);
984 up_write(&cookie->sem);
985 _leave(" = %d", ret);
989 EXPORT_SYMBOL(__fscache_pin_cookie);
991 /*****************************************************************************/
993 * unpin an object into the cache
995 void __fscache_unpin_cookie(struct fscache_cookie *cookie)
997 struct fscache_object *object;
1000 _enter("%p", cookie);
1002 if (hlist_empty(&cookie->backing_objects)) {
1003 _leave(" [no obj]");
1007 /* not supposed to use this for indexes */
1008 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
1010 /* prevent the file from being uncached whilst we access it and exclude
1011 * read and write attempts on pages
1013 down_write(&cookie->sem);
1016 if (!hlist_empty(&cookie->backing_objects)) {
1017 /* get and unpin the backing object */
1018 object = hlist_entry(cookie->backing_objects.first,
1019 struct fscache_object, cookie_link);
1021 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
1024 if (!object->cache->ops->unpin_object)
1027 /* prevent the cache from being withdrawn */
1028 if (fscache_operation_lock(object)) {
1029 if (object->cache->ops->grab_object(object)) {
1030 /* ask the cache to honour the operation */
1031 object->cache->ops->unpin_object(object);
1033 object->cache->ops->put_object(object);
1036 fscache_operation_unlock(object);
1041 up_write(&cookie->sem);
1045 EXPORT_SYMBOL(__fscache_unpin_cookie);