This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / fscache / cookie.c
1 /* cookie.c: general filesystem cache cookie management
2  *
3  * Copyright (C) 2004-5 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.
10  */
11
12 #include <linux/module.h>
13 #include "fscache-int.h"
14
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;
20
21 kmem_cache_t *fscache_cookie_jar;
22
23 static void fscache_withdraw_object(struct fscache_cache *cache,
24                                     struct fscache_object *object);
25
26 static void __fscache_cookie_put(struct fscache_cookie *cookie);
27
28 static inline void fscache_cookie_put(struct fscache_cookie *cookie)
29 {
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);
34 #endif
35
36         BUG_ON(atomic_read(&cookie->usage) <= 0);
37
38         if (atomic_dec_and_test(&cookie->usage))
39                 __fscache_cookie_put(cookie);
40
41 }
42
43 /*****************************************************************************/
44 /*
45  * look up a cache tag
46  */
47 struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
48 {
49         struct fscache_cache_tag *tag, *xtag;
50
51         /* firstly check for the existence of the tag under read lock */
52         down_read(&fscache_addremove_sem);
53
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);
58                         return tag;
59                 }
60         }
61
62         up_read(&fscache_addremove_sem);
63
64         /* the tag does not exist - create a candidate */
65         xtag = kmalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL);
66         if (!xtag)
67                 /* return a dummy tag if out of memory */
68                 return &fscache_nomem_tag;
69
70         atomic_set(&xtag->usage, 1);
71         strcpy(xtag->name, name);
72
73         /* write lock, search again and add if still not present */
74         down_write(&fscache_addremove_sem);
75
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);
80                         kfree(xtag);
81                         return tag;
82                 }
83         }
84
85         list_add_tail(&xtag->link, &fscache_cache_tag_list);
86         up_write(&fscache_addremove_sem);
87         return xtag;
88 }
89
90 /*****************************************************************************/
91 /*
92  * release a reference to a cache tag
93  */
94 void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
95 {
96         if (tag != &fscache_nomem_tag) {
97                 down_write(&fscache_addremove_sem);
98
99                 if (atomic_dec_and_test(&tag->usage))
100                         list_del_init(&tag->link);
101                 else
102                         tag = NULL;
103
104                 up_write(&fscache_addremove_sem);
105
106                 kfree(tag);
107         }
108 }
109
110 /*****************************************************************************/
111 /*
112  * register a network filesystem for caching
113  */
114 int __fscache_register_netfs(struct fscache_netfs *netfs)
115 {
116         struct fscache_netfs *ptr;
117         int ret;
118
119         _enter("{%s}", netfs->name);
120
121         INIT_LIST_HEAD(&netfs->link);
122
123         /* allocate a cookie for the primary index */
124         netfs->primary_index =
125                 kmem_cache_zalloc(fscache_cookie_jar, SLAB_KERNEL);
126
127         if (!netfs->primary_index) {
128                 _leave(" = -ENOMEM");
129                 return -ENOMEM;
130         }
131
132         /* initialise the primary index cookie */
133         atomic_set(&netfs->primary_index->usage, 1);
134         atomic_set(&netfs->primary_index->children, 0);
135
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;
140
141         atomic_inc(&netfs->primary_index->parent->usage);
142         atomic_inc(&netfs->primary_index->parent->children);
143
144         init_rwsem(&netfs->primary_index->sem);
145         INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
146
147         /* check the netfs type is not already present */
148         down_write(&fscache_addremove_sem);
149
150         ret = -EEXIST;
151         list_for_each_entry(ptr, &fscache_netfs_list, link) {
152                 if (strcmp(ptr->name, netfs->name) == 0)
153                         goto already_registered;
154         }
155
156         list_add(&netfs->link, &fscache_netfs_list);
157         ret = 0;
158
159         printk("FS-Cache: netfs '%s' registered for caching\n", netfs->name);
160
161 already_registered:
162         up_write(&fscache_addremove_sem);
163
164         if (ret < 0) {
165                 netfs->primary_index->parent = NULL;
166                 __fscache_cookie_put(netfs->primary_index);
167                 netfs->primary_index = NULL;
168         }
169
170         _leave(" = %d", ret);
171         return ret;
172 }
173
174 EXPORT_SYMBOL(__fscache_register_netfs);
175
176 /*****************************************************************************/
177 /*
178  * unregister a network filesystem from the cache
179  * - all cookies must have been released first
180  */
181 void __fscache_unregister_netfs(struct fscache_netfs *netfs)
182 {
183         _enter("{%s.%u}", netfs->name, netfs->version);
184
185         down_write(&fscache_addremove_sem);
186
187         list_del(&netfs->link);
188         fscache_relinquish_cookie(netfs->primary_index, 0);
189
190         up_write(&fscache_addremove_sem);
191
192         printk("FS-Cache: netfs '%s' unregistered from caching\n",
193                netfs->name);
194
195         _leave("");
196 }
197
198 EXPORT_SYMBOL(__fscache_unregister_netfs);
199
200 /*****************************************************************************/
201 /*
202  * initialise a cache record
203  */
204 void fscache_init_cache(struct fscache_cache *cache,
205                         struct fscache_cache_ops *ops,
206                         const char *idfmt,
207                         ...)
208 {
209         va_list va;
210
211         memset(cache, 0, sizeof(*cache));
212
213         cache->ops = ops;
214
215         va_start(va, idfmt);
216         vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va);
217         va_end(va);
218
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);
223 }
224
225 EXPORT_SYMBOL(fscache_init_cache);
226
227 /*****************************************************************************/
228 /*
229  * declare a mounted cache as being open for business
230  */
231 int fscache_add_cache(struct fscache_cache *cache,
232                       struct fscache_object *ifsdef,
233                       const char *tagname)
234 {
235         struct fscache_cache_tag *tag;
236
237         BUG_ON(!cache->ops);
238         BUG_ON(!ifsdef);
239
240         cache->flags = 0;
241
242         if (!tagname)
243                 tagname = cache->identifier;
244
245         BUG_ON(!tagname[0]);
246
247         _enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname);
248
249         if (!cache->ops->grab_object(ifsdef))
250                 BUG();
251
252         ifsdef->cookie = &fscache_fsdef_index;
253         ifsdef->cache = cache;
254         cache->fsdef = ifsdef;
255
256         down_write(&fscache_addremove_sem);
257
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) {
261                         if (tag->cache) {
262                                 printk(KERN_ERR
263                                        "FS-Cache: cache tag '%s' already in use\n",
264                                        tagname);
265                                 up_write(&fscache_addremove_sem);
266                                 return -EEXIST;
267                         }
268
269                         atomic_inc(&tag->usage);
270                         goto found_cache_tag;
271                 }
272         }
273
274         tag = kmalloc(sizeof(*tag) + strlen(tagname) + 1, GFP_KERNEL);
275         if (!tag) {
276                 up_write(&fscache_addremove_sem);
277                 return -ENOMEM;
278         }
279
280         atomic_set(&tag->usage, 1);
281         strcpy(tag->name, tagname);
282         list_add_tail(&tag->link, &fscache_cache_tag_list);
283
284 found_cache_tag:
285         tag->cache = cache;
286         cache->tag = tag;
287
288         /* add the cache to the list */
289         list_add(&cache->link, &fscache_cache_list);
290
291         /* add the cache's netfs definition index object to the cache's
292          * list */
293         spin_lock(&cache->object_list_lock);
294         list_add_tail(&ifsdef->cache_link, &cache->object_list);
295         spin_unlock(&cache->object_list_lock);
296
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);
300
301         hlist_add_head(&ifsdef->cookie_link,
302                        &fscache_fsdef_index.backing_objects);
303
304         atomic_inc(&fscache_fsdef_index.usage);
305
306         /* done */
307         up_write(&fscache_fsdef_index.sem);
308         up_write(&fscache_addremove_sem);
309
310         printk(KERN_NOTICE
311                "FS-Cache: Cache \"%s\" added (type %s)\n",
312                cache->tag->name, cache->ops->name);
313
314         _leave(" = 0 [%s]", cache->identifier);
315         return 0;
316 }
317
318 EXPORT_SYMBOL(fscache_add_cache);
319
320 /*****************************************************************************/
321 /*
322  * note a cache I/O error
323  */
324 void fscache_io_error(struct fscache_cache *cache)
325 {
326         set_bit(FSCACHE_IOERROR, &cache->flags);
327
328         printk(KERN_ERR "FS-Cache: Cache %s stopped due to I/O error\n",
329                cache->ops->name);
330 }
331
332 EXPORT_SYMBOL(fscache_io_error);
333
334 /*****************************************************************************/
335 /*
336  * withdraw an unmounted cache from the active service
337  */
338 void fscache_withdraw_cache(struct fscache_cache *cache)
339 {
340         struct fscache_object *object;
341
342         _enter("");
343
344         printk(KERN_NOTICE
345                "FS-Cache: Withdrawing cache \"%s\"\n",
346                cache->tag->name);
347
348         /* make the cache unavailable for cookie acquisition */
349         down_write(&cache->withdrawal_sem);
350
351         down_write(&fscache_addremove_sem);
352         list_del_init(&cache->link);
353         cache->tag->cache = NULL;
354         up_write(&fscache_addremove_sem);
355
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);
360         }
361         spin_unlock(&cache->object_list_lock);
362
363         /* make sure all pages pinned by operations on behalf of the netfs are
364          * written to disc */
365         cache->ops->sync_cache(cache);
366
367         /* dissociate all the netfs pages backed by this cache from the block
368          * mappings in the cache */
369         cache->ops->dissociate_pages(cache);
370
371         /* we now have to destroy all the active objects pertaining to this
372          * cache */
373         spin_lock(&cache->object_list_lock);
374
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);
380
381                 _debug("withdraw %p", object->cookie);
382
383                 /* we've extracted an active object from the tree - now dispose
384                  * of it */
385                 fscache_withdraw_object(cache, object);
386
387                 spin_lock(&cache->object_list_lock);
388         }
389
390         spin_unlock(&cache->object_list_lock);
391
392         fscache_release_cache_tag(cache->tag);
393         cache->tag = NULL;
394
395         _leave("");
396 }
397
398 EXPORT_SYMBOL(fscache_withdraw_cache);
399
400 /*****************************************************************************/
401 /*
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
408  *   simultaneously
409  * - the active object is pinned by the caller holding a refcount on it
410  */
411 static void fscache_withdraw_object(struct fscache_cache *cache,
412                                     struct fscache_object *object)
413 {
414         struct fscache_cookie *cookie, *xcookie = NULL;
415
416         _enter(",%p", object);
417
418         /* first of all we have to break the links between the object and the
419          * cookie
420          * - we have to hold both semaphores BUT we have to get the cookie sem
421          *   FIRST
422          */
423         cache->ops->lock_object(object);
424
425         cookie = object->cookie;
426         if (cookie) {
427                 /* pin the cookie so that is doesn't escape */
428                 atomic_inc(&cookie->usage);
429
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);
434
435                 /* erase references from the object to the cookie */
436                 hlist_del_init(&object->cookie_link);
437
438                 xcookie = object->cookie;
439                 object->cookie = NULL;
440
441                 up_write(&cookie->sem);
442         }
443
444         cache->ops->unlock_object(object);
445
446         /* we've broken the links between cookie and object */
447         if (xcookie) {
448                 fscache_cookie_put(xcookie);
449                 cache->ops->put_object(object);
450         }
451
452         /* unpin the cookie */
453         if (cookie) {
454                 if (cookie->def && cookie->def->now_uncached)
455                         cookie->def->now_uncached(cookie->netfs_data);
456                 fscache_cookie_put(cookie);
457         }
458
459         _leave("");
460 }
461
462 /*****************************************************************************/
463 /*
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
467  */
468 static struct fscache_cache *fscache_select_cache_for_object(struct fscache_cookie *cookie)
469 {
470         struct fscache_cache_tag *tag;
471         struct fscache_object *object;
472         struct fscache_cache *cache;
473
474         _enter("");
475
476         if (list_empty(&fscache_cache_list)) {
477                 _leave(" = NULL [no cache]");
478                 return NULL;
479         }
480
481         /* we check the parent to determine the cache to use */
482         down_read(&cookie->parent->sem);
483
484         /* the first in the parent's backing list should be the preferred
485          * cache */
486         if (!hlist_empty(&cookie->parent->backing_objects)) {
487                 object = hlist_entry(cookie->parent->backing_objects.first,
488                                      struct fscache_object, cookie_link);
489
490                 cache = object->cache;
491                 if (test_bit(FSCACHE_IOERROR, &cache->flags))
492                         cache = NULL;
493
494                 up_read(&cookie->parent->sem);
495                 _leave(" = %p [parent]", cache);
496                 return cache;
497         }
498
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]");
504                 return NULL;
505         }
506
507         up_read(&cookie->parent->sem);
508
509         if (!cookie->parent->def->select_cache)
510                 goto no_preference;
511
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);
516
517         if (!tag)
518                 goto no_preference;
519
520         if (tag == &fscache_nomem_tag) {
521                 _leave(" = NULL [nomem tag]");
522                 return NULL;
523         }
524
525         if (!tag->cache) {
526                 _leave(" = NULL [unbacked tag]");
527                 return NULL;
528         }
529
530         if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
531                 return NULL;
532
533         _leave(" = %p [specific]", tag->cache);
534         return tag->cache;
535
536 no_preference:
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);
541         return cache;
542 }
543
544 /*****************************************************************************/
545 /*
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
549  */
550 static struct fscache_object *fscache_lookup_object(struct fscache_cookie *cookie,
551                                                     struct fscache_cache *cache)
552 {
553         struct fscache_cookie *parent = cookie->parent;
554         struct fscache_object *pobject, *object;
555         struct hlist_node *_p;
556
557         _enter("{%s/%s},",
558                parent && parent->def ? parent->def->name : "",
559                cookie->def ? (char *) cookie->def->name : "<file>");
560
561         if (test_bit(FSCACHE_IOERROR, &cache->flags))
562                 return NULL;
563
564         /* see if we have the backing object for this cookie + cache immediately
565          * to hand
566          */
567         object = NULL;
568         hlist_for_each_entry(object, _p,
569                              &cookie->backing_objects, cookie_link
570                              ) {
571                 if (object->cache == cache)
572                         break;
573         }
574
575         if (object) {
576                 _leave(" = %p [old]", object);
577                 return object;
578         }
579
580         BUG_ON(!parent); /* FSDEF entries don't have a parent */
581
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
586          */
587         down_read(&parent->sem);
588
589         pobject = NULL;
590         hlist_for_each_entry(pobject, _p,
591                              &parent->backing_objects, cookie_link
592                              ) {
593                 if (pobject->cache == cache)
594                         break;
595         }
596
597         if (!pobject) {
598                 /* we don't know about the parent object */
599                 up_read(&parent->sem);
600                 down_write(&parent->sem);
601
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));
606                         return pobject;
607                 }
608
609                 _debug("pobject=%p", pobject);
610
611                 BUG_ON(pobject->cookie != parent);
612
613                 downgrade_write(&parent->sem);
614         }
615
616         /* now we can attempt to look up this object in the parent, possibly
617          * creating a representation on disc when we do so
618          */
619         object = cache->ops->lookup_object(cache, pobject, cookie);
620         up_read(&parent->sem);
621
622         if (IS_ERR(object)) {
623                 _leave(" = %ld [no obj]", PTR_ERR(object));
624                 return object;
625         }
626
627         /* keep track of it */
628         cache->ops->lock_object(object);
629
630         BUG_ON(!hlist_unhashed(&object->cookie_link));
631
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);
637         }
638
639         /* attach to the cookie */
640         object->cookie = cookie;
641         atomic_inc(&cookie->usage);
642         hlist_add_head(&object->cookie_link, &cookie->backing_objects);
643
644         /* done */
645         cache->ops->unlock_object(object);
646         _leave(" = %p [new]", object);
647         return object;
648 }
649
650 /*****************************************************************************/
651 /*
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
660  *   needs storing
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
665  */
666 struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent,
667                                                 struct fscache_cookie_def *def,
668                                                 void *netfs_data)
669 {
670         struct fscache_cookie *cookie;
671         struct fscache_cache *cache;
672         struct fscache_object *object;
673         int ret = 0;
674
675         BUG_ON(!def);
676
677         _enter("{%s},{%s},%p",
678                parent ? (char *) parent->def->name : "<no-parent>",
679                def->name, netfs_data);
680
681         /* if there's no parent cookie, then we don't create one here either */
682         if (!parent) {
683                 _leave(" [no parent]");
684                 return NULL;
685         }
686
687         /* validate the definition */
688         BUG_ON(!def->get_key);
689         BUG_ON(!def->name[0]);
690
691         BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
692                parent->def->type != FSCACHE_COOKIE_TYPE_INDEX);
693
694         /* allocate and initialise a cookie */
695         cookie = kmem_cache_alloc(fscache_cookie_jar, SLAB_KERNEL);
696         if (!cookie) {
697                 _leave(" [ENOMEM]");
698                 return NULL;
699         }
700
701         atomic_set(&cookie->usage, 1);
702         atomic_set(&cookie->children, 0);
703
704         atomic_inc(&parent->usage);
705         atomic_inc(&parent->children);
706
707         cookie->def             = def;
708         cookie->parent          = parent;
709         cookie->netfs           = parent->netfs;
710         cookie->netfs_data      = netfs_data;
711
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);
715
716         if (list_empty(&fscache_cache_list)) {
717                 up_read(&fscache_addremove_sem);
718                 _leave(" = %p [no caches]", cookie);
719                 return cookie;
720         }
721
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
724          * multiple caches */
725         if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
726                 down_write(&cookie->sem);
727
728                 /* the object is a file - we need to select a cache in which to
729                  * store it */
730                 cache = fscache_select_cache_for_object(cookie);
731                 if (!cache)
732                         goto no_cache; /* couldn't decide on a cache */
733
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);
739                         goto error;
740                 }
741
742                 up_write(&cookie->sem);
743         }
744 out:
745         up_read(&fscache_addremove_sem);
746         _leave(" = %p", cookie);
747         return cookie;
748
749 no_cache:
750         ret = -ENOMEDIUM;
751         goto error_cleanup;
752 error:
753         printk(KERN_ERR "FS-Cache: error from cache: %d\n", ret);
754 error_cleanup:
755         if (cookie) {
756                 up_write(&cookie->sem);
757                 __fscache_cookie_put(cookie);
758                 cookie = NULL;
759                 atomic_dec(&parent->children);
760         }
761
762         goto out;
763 }
764
765 EXPORT_SYMBOL(__fscache_acquire_cookie);
766
767 /*****************************************************************************/
768 /*
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)
773  */
774 void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
775 {
776         struct fscache_cache *cache;
777         struct fscache_object *object;
778         struct hlist_node *_p;
779
780         if (!cookie) {
781                 _leave(" [no cookie]");
782                 return;
783         }
784
785         _enter("%p{%s},%d", cookie, cookie->def->name, retire);
786
787         if (atomic_read(&cookie->children) != 0) {
788                 printk("FS-Cache: cookie still has children\n");
789                 BUG();
790         }
791
792         /* detach pointers back to the netfs */
793         down_write(&cookie->sem);
794
795         cookie->netfs_data      = NULL;
796         cookie->def             = NULL;
797
798         /* mark retired objects for recycling */
799         if (retire) {
800                 hlist_for_each_entry(object, _p,
801                                      &cookie->backing_objects,
802                                      cookie_link
803                                      ) {
804                         set_bit(FSCACHE_OBJECT_RECYCLING, &object->flags);
805                 }
806         }
807
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,
812                                      cookie_link);
813
814                 /* detach each cache object from the object cookie */
815                 set_bit(FSCACHE_OBJECT_RELEASING, &object->flags);
816
817                 hlist_del_init(&object->cookie_link);
818
819                 cache = object->cache;
820                 cache->ops->lock_object(object);
821                 object->cookie = NULL;
822                 cache->ops->unlock_object(object);
823
824                 if (atomic_dec_and_test(&cookie->usage))
825                         /* the cookie refcount shouldn't be reduced to 0 yet */
826                         BUG();
827
828                 spin_lock(&cache->object_list_lock);
829                 list_del_init(&object->cache_link);
830                 spin_unlock(&cache->object_list_lock);
831
832                 cache->ops->put_object(object);
833         }
834
835         up_write(&cookie->sem);
836
837         if (cookie->parent) {
838 #ifdef CONFIG_DEBUG_SLAB
839                 BUG_ON((atomic_read(&cookie->parent->children) & 0xffff0000) == 0x6b6b0000);
840 #endif
841                 atomic_dec(&cookie->parent->children);
842         }
843
844         /* finally dispose of the cookie */
845         fscache_cookie_put(cookie);
846
847         _leave("");
848 }
849
850 EXPORT_SYMBOL(__fscache_relinquish_cookie);
851
852 /*****************************************************************************/
853 /*
854  * update the index entries backing a cookie
855  */
856 void __fscache_update_cookie(struct fscache_cookie *cookie)
857 {
858         struct fscache_object *object;
859         struct hlist_node *_p;
860
861         if (!cookie) {
862                 _leave(" [no cookie]");
863                 return;
864         }
865
866         _enter("{%s}", cookie->def->name);
867
868         BUG_ON(!cookie->def->get_aux);
869
870         down_write(&cookie->sem);
871         down_read(&cookie->parent->sem);
872
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
876                              ) {
877                 if (!test_bit(FSCACHE_IOERROR, &object->cache->flags))
878                         object->cache->ops->update_object(object);
879         }
880
881         up_read(&cookie->parent->sem);
882         up_write(&cookie->sem);
883         _leave("");
884 }
885
886 EXPORT_SYMBOL(__fscache_update_cookie);
887
888 /*****************************************************************************/
889 /*
890  * destroy a cookie
891  */
892 static void __fscache_cookie_put(struct fscache_cookie *cookie)
893 {
894         struct fscache_cookie *parent;
895
896         _enter("%p", cookie);
897
898         for (;;) {
899                 parent = cookie->parent;
900                 BUG_ON(!hlist_empty(&cookie->backing_objects));
901                 kmem_cache_free(fscache_cookie_jar, cookie);
902
903                 if (!parent)
904                         break;
905
906                 cookie = parent;
907                 BUG_ON(atomic_read(&cookie->usage) <= 0);
908                 if (!atomic_dec_and_test(&cookie->usage))
909                         break;
910         }
911
912         _leave("");
913 }
914
915 /*****************************************************************************/
916 /*
917  * initialise an cookie jar slab element prior to any use
918  */
919 void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep,
920                               unsigned long flags)
921 {
922         struct fscache_cookie *cookie = _cookie;
923
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);
929         }
930 }
931
932 /*****************************************************************************/
933 /*
934  * pin an object into the cache
935  */
936 int __fscache_pin_cookie(struct fscache_cookie *cookie)
937 {
938         struct fscache_object *object;
939         int ret;
940
941         _enter("%p", cookie);
942
943         if (hlist_empty(&cookie->backing_objects)) {
944                 _leave(" = -ENOBUFS");
945                 return -ENOBUFS;
946         }
947
948         /* not supposed to use this for indexes */
949         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
950
951         /* prevent the file from being uncached whilst we access it and exclude
952          * read and write attempts on pages
953          */
954         down_write(&cookie->sem);
955
956         ret = -ENOBUFS;
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);
961
962                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
963                         goto out;
964
965                 if (!object->cache->ops->pin_object) {
966                         ret = -EOPNOTSUPP;
967                         goto out;
968                 }
969
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);
975
976                                 object->cache->ops->put_object(object);
977                         }
978
979                         fscache_operation_unlock(object);
980                 }
981         }
982
983 out:
984         up_write(&cookie->sem);
985         _leave(" = %d", ret);
986         return ret;
987 }
988
989 EXPORT_SYMBOL(__fscache_pin_cookie);
990
991 /*****************************************************************************/
992 /*
993  * unpin an object into the cache
994  */
995 void __fscache_unpin_cookie(struct fscache_cookie *cookie)
996 {
997         struct fscache_object *object;
998         int ret;
999
1000         _enter("%p", cookie);
1001
1002         if (hlist_empty(&cookie->backing_objects)) {
1003                 _leave(" [no obj]");
1004                 return;
1005         }
1006
1007         /* not supposed to use this for indexes */
1008         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
1009
1010         /* prevent the file from being uncached whilst we access it and exclude
1011          * read and write attempts on pages
1012          */
1013         down_write(&cookie->sem);
1014
1015         ret = -ENOBUFS;
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);
1020
1021                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
1022                         goto out;
1023
1024                 if (!object->cache->ops->unpin_object)
1025                         goto out;
1026
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);
1032
1033                                 object->cache->ops->put_object(object);
1034                         }
1035
1036                         fscache_operation_unlock(object);
1037                 }
1038         }
1039
1040 out:
1041         up_write(&cookie->sem);
1042         _leave("");
1043 }
1044
1045 EXPORT_SYMBOL(__fscache_unpin_cookie);