]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/fscache/object.c
FS-Cache: Actually requeue an object when requested
[net-next-2.6.git] / fs / fscache / object.c
1 /* FS-Cache object state machine handler
2  *
3  * Copyright (C) 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.
10  *
11  * See Documentation/filesystems/caching/object.txt for a description of the
12  * object state machine and the in-kernel representations.
13  */
14
15 #define FSCACHE_DEBUG_LEVEL COOKIE
16 #include <linux/module.h>
17 #include <linux/seq_file.h>
18 #include "internal.h"
19
20 const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
21         [FSCACHE_OBJECT_INIT]           = "OBJECT_INIT",
22         [FSCACHE_OBJECT_LOOKING_UP]     = "OBJECT_LOOKING_UP",
23         [FSCACHE_OBJECT_CREATING]       = "OBJECT_CREATING",
24         [FSCACHE_OBJECT_AVAILABLE]      = "OBJECT_AVAILABLE",
25         [FSCACHE_OBJECT_ACTIVE]         = "OBJECT_ACTIVE",
26         [FSCACHE_OBJECT_UPDATING]       = "OBJECT_UPDATING",
27         [FSCACHE_OBJECT_DYING]          = "OBJECT_DYING",
28         [FSCACHE_OBJECT_LC_DYING]       = "OBJECT_LC_DYING",
29         [FSCACHE_OBJECT_ABORT_INIT]     = "OBJECT_ABORT_INIT",
30         [FSCACHE_OBJECT_RELEASING]      = "OBJECT_RELEASING",
31         [FSCACHE_OBJECT_RECYCLING]      = "OBJECT_RECYCLING",
32         [FSCACHE_OBJECT_WITHDRAWING]    = "OBJECT_WITHDRAWING",
33         [FSCACHE_OBJECT_DEAD]           = "OBJECT_DEAD",
34 };
35 EXPORT_SYMBOL(fscache_object_states);
36
37 const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = {
38         [FSCACHE_OBJECT_INIT]           = "INIT",
39         [FSCACHE_OBJECT_LOOKING_UP]     = "LOOK",
40         [FSCACHE_OBJECT_CREATING]       = "CRTN",
41         [FSCACHE_OBJECT_AVAILABLE]      = "AVBL",
42         [FSCACHE_OBJECT_ACTIVE]         = "ACTV",
43         [FSCACHE_OBJECT_UPDATING]       = "UPDT",
44         [FSCACHE_OBJECT_DYING]          = "DYNG",
45         [FSCACHE_OBJECT_LC_DYING]       = "LCDY",
46         [FSCACHE_OBJECT_ABORT_INIT]     = "ABTI",
47         [FSCACHE_OBJECT_RELEASING]      = "RELS",
48         [FSCACHE_OBJECT_RECYCLING]      = "RCYC",
49         [FSCACHE_OBJECT_WITHDRAWING]    = "WTHD",
50         [FSCACHE_OBJECT_DEAD]           = "DEAD",
51 };
52
53 static void fscache_object_slow_work_put_ref(struct slow_work *);
54 static int  fscache_object_slow_work_get_ref(struct slow_work *);
55 static void fscache_object_slow_work_execute(struct slow_work *);
56 #ifdef CONFIG_SLOW_WORK_PROC
57 static void fscache_object_slow_work_desc(struct slow_work *, struct seq_file *);
58 #endif
59 static void fscache_initialise_object(struct fscache_object *);
60 static void fscache_lookup_object(struct fscache_object *);
61 static void fscache_object_available(struct fscache_object *);
62 static void fscache_release_object(struct fscache_object *);
63 static void fscache_withdraw_object(struct fscache_object *);
64 static void fscache_enqueue_dependents(struct fscache_object *);
65 static void fscache_dequeue_object(struct fscache_object *);
66
67 const struct slow_work_ops fscache_object_slow_work_ops = {
68         .owner          = THIS_MODULE,
69         .get_ref        = fscache_object_slow_work_get_ref,
70         .put_ref        = fscache_object_slow_work_put_ref,
71         .execute        = fscache_object_slow_work_execute,
72 #ifdef CONFIG_SLOW_WORK_PROC
73         .desc           = fscache_object_slow_work_desc,
74 #endif
75 };
76 EXPORT_SYMBOL(fscache_object_slow_work_ops);
77
78 /*
79  * we need to notify the parent when an op completes that we had outstanding
80  * upon it
81  */
82 static inline void fscache_done_parent_op(struct fscache_object *object)
83 {
84         struct fscache_object *parent = object->parent;
85
86         _enter("OBJ%x {OBJ%x,%x}",
87                object->debug_id, parent->debug_id, parent->n_ops);
88
89         spin_lock_nested(&parent->lock, 1);
90         parent->n_ops--;
91         parent->n_obj_ops--;
92         if (parent->n_ops == 0)
93                 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED);
94         spin_unlock(&parent->lock);
95 }
96
97 /*
98  * process events that have been sent to an object's state machine
99  * - initiates parent lookup
100  * - does object lookup
101  * - does object creation
102  * - does object recycling and retirement
103  * - does object withdrawal
104  */
105 static void fscache_object_state_machine(struct fscache_object *object)
106 {
107         enum fscache_object_state new_state;
108         struct fscache_cookie *cookie;
109
110         ASSERT(object != NULL);
111
112         _enter("{OBJ%x,%s,%lx}",
113                object->debug_id, fscache_object_states[object->state],
114                object->events);
115
116         switch (object->state) {
117                 /* wait for the parent object to become ready */
118         case FSCACHE_OBJECT_INIT:
119                 object->event_mask =
120                         ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED);
121                 fscache_initialise_object(object);
122                 goto done;
123
124                 /* look up the object metadata on disk */
125         case FSCACHE_OBJECT_LOOKING_UP:
126                 fscache_lookup_object(object);
127                 goto lookup_transit;
128
129                 /* create the object metadata on disk */
130         case FSCACHE_OBJECT_CREATING:
131                 fscache_lookup_object(object);
132                 goto lookup_transit;
133
134                 /* handle an object becoming available; start pending
135                  * operations and queue dependent operations for processing */
136         case FSCACHE_OBJECT_AVAILABLE:
137                 fscache_object_available(object);
138                 goto active_transit;
139
140                 /* normal running state */
141         case FSCACHE_OBJECT_ACTIVE:
142                 goto active_transit;
143
144                 /* update the object metadata on disk */
145         case FSCACHE_OBJECT_UPDATING:
146                 clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events);
147                 fscache_stat(&fscache_n_updates_run);
148                 fscache_stat(&fscache_n_cop_update_object);
149                 object->cache->ops->update_object(object);
150                 fscache_stat_d(&fscache_n_cop_update_object);
151                 goto active_transit;
152
153                 /* handle an object dying during lookup or creation */
154         case FSCACHE_OBJECT_LC_DYING:
155                 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE);
156                 fscache_stat(&fscache_n_cop_lookup_complete);
157                 object->cache->ops->lookup_complete(object);
158                 fscache_stat_d(&fscache_n_cop_lookup_complete);
159
160                 spin_lock(&object->lock);
161                 object->state = FSCACHE_OBJECT_DYING;
162                 cookie = object->cookie;
163                 if (cookie) {
164                         if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP,
165                                                &cookie->flags))
166                                 wake_up_bit(&cookie->flags,
167                                             FSCACHE_COOKIE_LOOKING_UP);
168                         if (test_and_clear_bit(FSCACHE_COOKIE_CREATING,
169                                                &cookie->flags))
170                                 wake_up_bit(&cookie->flags,
171                                             FSCACHE_COOKIE_CREATING);
172                 }
173                 spin_unlock(&object->lock);
174
175                 fscache_done_parent_op(object);
176
177                 /* wait for completion of all active operations on this object
178                  * and the death of all child objects of this object */
179         case FSCACHE_OBJECT_DYING:
180         dying:
181                 clear_bit(FSCACHE_OBJECT_EV_CLEARED, &object->events);
182                 spin_lock(&object->lock);
183                 _debug("dying OBJ%x {%d,%d}",
184                        object->debug_id, object->n_ops, object->n_children);
185                 if (object->n_ops == 0 && object->n_children == 0) {
186                         object->event_mask &=
187                                 ~(1 << FSCACHE_OBJECT_EV_CLEARED);
188                         object->event_mask |=
189                                 (1 << FSCACHE_OBJECT_EV_WITHDRAW) |
190                                 (1 << FSCACHE_OBJECT_EV_RETIRE) |
191                                 (1 << FSCACHE_OBJECT_EV_RELEASE) |
192                                 (1 << FSCACHE_OBJECT_EV_ERROR);
193                 } else {
194                         object->event_mask &=
195                                 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
196                                   (1 << FSCACHE_OBJECT_EV_RETIRE) |
197                                   (1 << FSCACHE_OBJECT_EV_RELEASE) |
198                                   (1 << FSCACHE_OBJECT_EV_ERROR));
199                         object->event_mask |=
200                                 1 << FSCACHE_OBJECT_EV_CLEARED;
201                 }
202                 spin_unlock(&object->lock);
203                 fscache_enqueue_dependents(object);
204                 fscache_start_operations(object);
205                 goto terminal_transit;
206
207                 /* handle an abort during initialisation */
208         case FSCACHE_OBJECT_ABORT_INIT:
209                 _debug("handle abort init %lx", object->events);
210                 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE);
211
212                 spin_lock(&object->lock);
213                 fscache_dequeue_object(object);
214
215                 object->state = FSCACHE_OBJECT_DYING;
216                 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING,
217                                        &object->cookie->flags))
218                         wake_up_bit(&object->cookie->flags,
219                                     FSCACHE_COOKIE_CREATING);
220                 spin_unlock(&object->lock);
221                 goto dying;
222
223                 /* handle the netfs releasing an object and possibly marking it
224                  * obsolete too */
225         case FSCACHE_OBJECT_RELEASING:
226         case FSCACHE_OBJECT_RECYCLING:
227                 object->event_mask &=
228                         ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
229                           (1 << FSCACHE_OBJECT_EV_RETIRE) |
230                           (1 << FSCACHE_OBJECT_EV_RELEASE) |
231                           (1 << FSCACHE_OBJECT_EV_ERROR));
232                 fscache_release_object(object);
233                 spin_lock(&object->lock);
234                 object->state = FSCACHE_OBJECT_DEAD;
235                 spin_unlock(&object->lock);
236                 fscache_stat(&fscache_n_object_dead);
237                 goto terminal_transit;
238
239                 /* handle the parent cache of this object being withdrawn from
240                  * active service */
241         case FSCACHE_OBJECT_WITHDRAWING:
242                 object->event_mask &=
243                         ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
244                           (1 << FSCACHE_OBJECT_EV_RETIRE) |
245                           (1 << FSCACHE_OBJECT_EV_RELEASE) |
246                           (1 << FSCACHE_OBJECT_EV_ERROR));
247                 fscache_withdraw_object(object);
248                 spin_lock(&object->lock);
249                 object->state = FSCACHE_OBJECT_DEAD;
250                 spin_unlock(&object->lock);
251                 fscache_stat(&fscache_n_object_dead);
252                 goto terminal_transit;
253
254                 /* complain about the object being woken up once it is
255                  * deceased */
256         case FSCACHE_OBJECT_DEAD:
257                 printk(KERN_ERR "FS-Cache:"
258                        " Unexpected event in dead state %lx\n",
259                        object->events & object->event_mask);
260                 BUG();
261
262         default:
263                 printk(KERN_ERR "FS-Cache: Unknown object state %u\n",
264                        object->state);
265                 BUG();
266         }
267
268         /* determine the transition from a lookup state */
269 lookup_transit:
270         switch (fls(object->events & object->event_mask) - 1) {
271         case FSCACHE_OBJECT_EV_WITHDRAW:
272         case FSCACHE_OBJECT_EV_RETIRE:
273         case FSCACHE_OBJECT_EV_RELEASE:
274         case FSCACHE_OBJECT_EV_ERROR:
275                 new_state = FSCACHE_OBJECT_LC_DYING;
276                 goto change_state;
277         case FSCACHE_OBJECT_EV_REQUEUE:
278                 goto done;
279         case -1:
280                 goto done; /* sleep until event */
281         default:
282                 goto unsupported_event;
283         }
284
285         /* determine the transition from an active state */
286 active_transit:
287         switch (fls(object->events & object->event_mask) - 1) {
288         case FSCACHE_OBJECT_EV_WITHDRAW:
289         case FSCACHE_OBJECT_EV_RETIRE:
290         case FSCACHE_OBJECT_EV_RELEASE:
291         case FSCACHE_OBJECT_EV_ERROR:
292                 new_state = FSCACHE_OBJECT_DYING;
293                 goto change_state;
294         case FSCACHE_OBJECT_EV_UPDATE:
295                 new_state = FSCACHE_OBJECT_UPDATING;
296                 goto change_state;
297         case -1:
298                 new_state = FSCACHE_OBJECT_ACTIVE;
299                 goto change_state; /* sleep until event */
300         default:
301                 goto unsupported_event;
302         }
303
304         /* determine the transition from a terminal state */
305 terminal_transit:
306         switch (fls(object->events & object->event_mask) - 1) {
307         case FSCACHE_OBJECT_EV_WITHDRAW:
308                 new_state = FSCACHE_OBJECT_WITHDRAWING;
309                 goto change_state;
310         case FSCACHE_OBJECT_EV_RETIRE:
311                 new_state = FSCACHE_OBJECT_RECYCLING;
312                 goto change_state;
313         case FSCACHE_OBJECT_EV_RELEASE:
314                 new_state = FSCACHE_OBJECT_RELEASING;
315                 goto change_state;
316         case FSCACHE_OBJECT_EV_ERROR:
317                 new_state = FSCACHE_OBJECT_WITHDRAWING;
318                 goto change_state;
319         case FSCACHE_OBJECT_EV_CLEARED:
320                 new_state = FSCACHE_OBJECT_DYING;
321                 goto change_state;
322         case -1:
323                 goto done; /* sleep until event */
324         default:
325                 goto unsupported_event;
326         }
327
328 change_state:
329         spin_lock(&object->lock);
330         object->state = new_state;
331         spin_unlock(&object->lock);
332
333 done:
334         _leave(" [->%s]", fscache_object_states[object->state]);
335         return;
336
337 unsupported_event:
338         printk(KERN_ERR "FS-Cache:"
339                " Unsupported event %lx [mask %lx] in state %s\n",
340                object->events, object->event_mask,
341                fscache_object_states[object->state]);
342         BUG();
343 }
344
345 /*
346  * execute an object
347  */
348 static void fscache_object_slow_work_execute(struct slow_work *work)
349 {
350         struct fscache_object *object =
351                 container_of(work, struct fscache_object, work);
352         unsigned long start;
353
354         _enter("{OBJ%x}", object->debug_id);
355
356         start = jiffies;
357         fscache_object_state_machine(object);
358         fscache_hist(fscache_objs_histogram, start);
359         if (object->events & object->event_mask)
360                 fscache_enqueue_object(object);
361         clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
362 }
363
364 /*
365  * describe an object for slow-work debugging
366  */
367 #ifdef CONFIG_SLOW_WORK_PROC
368 static void fscache_object_slow_work_desc(struct slow_work *work,
369                                           struct seq_file *m)
370 {
371         struct fscache_object *object =
372                 container_of(work, struct fscache_object, work);
373
374         seq_printf(m, "FSC: OBJ%x: %s",
375                    object->debug_id,
376                    fscache_object_states_short[object->state]);
377 }
378 #endif
379
380 /*
381  * initialise an object
382  * - check the specified object's parent to see if we can make use of it
383  *   immediately to do a creation
384  * - we may need to start the process of creating a parent and we need to wait
385  *   for the parent's lookup and creation to complete if it's not there yet
386  * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the
387  *   leaf-most cookies of the object and all its children
388  */
389 static void fscache_initialise_object(struct fscache_object *object)
390 {
391         struct fscache_object *parent;
392
393         _enter("");
394         ASSERT(object->cookie != NULL);
395         ASSERT(object->cookie->parent != NULL);
396         ASSERT(list_empty(&object->work.link));
397
398         if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) |
399                               (1 << FSCACHE_OBJECT_EV_RELEASE) |
400                               (1 << FSCACHE_OBJECT_EV_RETIRE) |
401                               (1 << FSCACHE_OBJECT_EV_WITHDRAW))) {
402                 _debug("abort init %lx", object->events);
403                 spin_lock(&object->lock);
404                 object->state = FSCACHE_OBJECT_ABORT_INIT;
405                 spin_unlock(&object->lock);
406                 return;
407         }
408
409         spin_lock(&object->cookie->lock);
410         spin_lock_nested(&object->cookie->parent->lock, 1);
411
412         parent = object->parent;
413         if (!parent) {
414                 _debug("no parent");
415                 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events);
416         } else {
417                 spin_lock(&object->lock);
418                 spin_lock_nested(&parent->lock, 1);
419                 _debug("parent %s", fscache_object_states[parent->state]);
420
421                 if (parent->state >= FSCACHE_OBJECT_DYING) {
422                         _debug("bad parent");
423                         set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events);
424                 } else if (parent->state < FSCACHE_OBJECT_AVAILABLE) {
425                         _debug("wait");
426
427                         /* we may get woken up in this state by child objects
428                          * binding on to us, so we need to make sure we don't
429                          * add ourself to the list multiple times */
430                         if (list_empty(&object->dep_link)) {
431                                 fscache_stat(&fscache_n_cop_grab_object);
432                                 object->cache->ops->grab_object(object);
433                                 fscache_stat_d(&fscache_n_cop_grab_object);
434                                 list_add(&object->dep_link,
435                                          &parent->dependents);
436
437                                 /* fscache_acquire_non_index_cookie() uses this
438                                  * to wake the chain up */
439                                 if (parent->state == FSCACHE_OBJECT_INIT)
440                                         fscache_enqueue_object(parent);
441                         }
442                 } else {
443                         _debug("go");
444                         parent->n_ops++;
445                         parent->n_obj_ops++;
446                         object->lookup_jif = jiffies;
447                         object->state = FSCACHE_OBJECT_LOOKING_UP;
448                         set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
449                 }
450
451                 spin_unlock(&parent->lock);
452                 spin_unlock(&object->lock);
453         }
454
455         spin_unlock(&object->cookie->parent->lock);
456         spin_unlock(&object->cookie->lock);
457         _leave("");
458 }
459
460 /*
461  * look an object up in the cache from which it was allocated
462  * - we hold an "access lock" on the parent object, so the parent object cannot
463  *   be withdrawn by either party till we've finished
464  * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the
465  *   leaf-most cookies of the object and all its children
466  */
467 static void fscache_lookup_object(struct fscache_object *object)
468 {
469         struct fscache_cookie *cookie = object->cookie;
470         struct fscache_object *parent;
471
472         _enter("");
473
474         parent = object->parent;
475         ASSERT(parent != NULL);
476         ASSERTCMP(parent->n_ops, >, 0);
477         ASSERTCMP(parent->n_obj_ops, >, 0);
478
479         /* make sure the parent is still available */
480         ASSERTCMP(parent->state, >=, FSCACHE_OBJECT_AVAILABLE);
481
482         if (parent->state >= FSCACHE_OBJECT_DYING ||
483             test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
484                 _debug("unavailable");
485                 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events);
486                 _leave("");
487                 return;
488         }
489
490         _debug("LOOKUP \"%s/%s\" in \"%s\"",
491                parent->cookie->def->name, cookie->def->name,
492                object->cache->tag->name);
493
494         fscache_stat(&fscache_n_object_lookups);
495         fscache_stat(&fscache_n_cop_lookup_object);
496         object->cache->ops->lookup_object(object);
497         fscache_stat_d(&fscache_n_cop_lookup_object);
498
499         if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events))
500                 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
501
502         _leave("");
503 }
504
505 /**
506  * fscache_object_lookup_negative - Note negative cookie lookup
507  * @object: Object pointing to cookie to mark
508  *
509  * Note negative lookup, permitting those waiting to read data from an already
510  * existing backing object to continue as there's no data for them to read.
511  */
512 void fscache_object_lookup_negative(struct fscache_object *object)
513 {
514         struct fscache_cookie *cookie = object->cookie;
515
516         _enter("{OBJ%x,%s}",
517                object->debug_id, fscache_object_states[object->state]);
518
519         spin_lock(&object->lock);
520         if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
521                 fscache_stat(&fscache_n_object_lookups_negative);
522
523                 /* transit here to allow write requests to begin stacking up
524                  * and read requests to begin returning ENODATA */
525                 object->state = FSCACHE_OBJECT_CREATING;
526                 spin_unlock(&object->lock);
527
528                 set_bit(FSCACHE_COOKIE_PENDING_FILL, &cookie->flags);
529                 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
530
531                 _debug("wake up lookup %p", &cookie->flags);
532                 smp_mb__before_clear_bit();
533                 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
534                 smp_mb__after_clear_bit();
535                 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
536                 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
537         } else {
538                 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING);
539                 spin_unlock(&object->lock);
540         }
541
542         _leave("");
543 }
544 EXPORT_SYMBOL(fscache_object_lookup_negative);
545
546 /**
547  * fscache_obtained_object - Note successful object lookup or creation
548  * @object: Object pointing to cookie to mark
549  *
550  * Note successful lookup and/or creation, permitting those waiting to write
551  * data to a backing object to continue.
552  *
553  * Note that after calling this, an object's cookie may be relinquished by the
554  * netfs, and so must be accessed with object lock held.
555  */
556 void fscache_obtained_object(struct fscache_object *object)
557 {
558         struct fscache_cookie *cookie = object->cookie;
559
560         _enter("{OBJ%x,%s}",
561                object->debug_id, fscache_object_states[object->state]);
562
563         /* if we were still looking up, then we must have a positive lookup
564          * result, in which case there may be data available */
565         spin_lock(&object->lock);
566         if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
567                 fscache_stat(&fscache_n_object_lookups_positive);
568
569                 clear_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
570
571                 object->state = FSCACHE_OBJECT_AVAILABLE;
572                 spin_unlock(&object->lock);
573
574                 smp_mb__before_clear_bit();
575                 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
576                 smp_mb__after_clear_bit();
577                 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
578                 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
579         } else {
580                 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING);
581                 fscache_stat(&fscache_n_object_created);
582
583                 object->state = FSCACHE_OBJECT_AVAILABLE;
584                 spin_unlock(&object->lock);
585                 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
586                 smp_wmb();
587         }
588
589         if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, &cookie->flags))
590                 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING);
591
592         _leave("");
593 }
594 EXPORT_SYMBOL(fscache_obtained_object);
595
596 /*
597  * handle an object that has just become available
598  */
599 static void fscache_object_available(struct fscache_object *object)
600 {
601         _enter("{OBJ%x}", object->debug_id);
602
603         spin_lock(&object->lock);
604
605         if (object->cookie &&
606             test_and_clear_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags))
607                 wake_up_bit(&object->cookie->flags, FSCACHE_COOKIE_CREATING);
608
609         fscache_done_parent_op(object);
610         if (object->n_in_progress == 0) {
611                 if (object->n_ops > 0) {
612                         ASSERTCMP(object->n_ops, >=, object->n_obj_ops);
613                         ASSERTIF(object->n_ops > object->n_obj_ops,
614                                  !list_empty(&object->pending_ops));
615                         fscache_start_operations(object);
616                 } else {
617                         ASSERT(list_empty(&object->pending_ops));
618                 }
619         }
620         spin_unlock(&object->lock);
621
622         fscache_stat(&fscache_n_cop_lookup_complete);
623         object->cache->ops->lookup_complete(object);
624         fscache_stat_d(&fscache_n_cop_lookup_complete);
625         fscache_enqueue_dependents(object);
626
627         fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif);
628         fscache_stat(&fscache_n_object_avail);
629
630         _leave("");
631 }
632
633 /*
634  * drop an object's attachments
635  */
636 static void fscache_drop_object(struct fscache_object *object)
637 {
638         struct fscache_object *parent = object->parent;
639         struct fscache_cache *cache = object->cache;
640
641         _enter("{OBJ%x,%d}", object->debug_id, object->n_children);
642
643         ASSERTCMP(object->cookie, ==, NULL);
644         ASSERT(hlist_unhashed(&object->cookie_link));
645
646         spin_lock(&cache->object_list_lock);
647         list_del_init(&object->cache_link);
648         spin_unlock(&cache->object_list_lock);
649
650         fscache_stat(&fscache_n_cop_drop_object);
651         cache->ops->drop_object(object);
652         fscache_stat_d(&fscache_n_cop_drop_object);
653
654         if (parent) {
655                 _debug("release parent OBJ%x {%d}",
656                        parent->debug_id, parent->n_children);
657
658                 spin_lock(&parent->lock);
659                 parent->n_children--;
660                 if (parent->n_children == 0)
661                         fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED);
662                 spin_unlock(&parent->lock);
663                 object->parent = NULL;
664         }
665
666         /* this just shifts the object release to the slow work processor */
667         fscache_stat(&fscache_n_cop_put_object);
668         object->cache->ops->put_object(object);
669         fscache_stat_d(&fscache_n_cop_put_object);
670
671         _leave("");
672 }
673
674 /*
675  * release or recycle an object that the netfs has discarded
676  */
677 static void fscache_release_object(struct fscache_object *object)
678 {
679         _enter("");
680
681         fscache_drop_object(object);
682 }
683
684 /*
685  * withdraw an object from active service
686  */
687 static void fscache_withdraw_object(struct fscache_object *object)
688 {
689         struct fscache_cookie *cookie;
690         bool detached;
691
692         _enter("");
693
694         spin_lock(&object->lock);
695         cookie = object->cookie;
696         if (cookie) {
697                 /* need to get the cookie lock before the object lock, starting
698                  * from the object pointer */
699                 atomic_inc(&cookie->usage);
700                 spin_unlock(&object->lock);
701
702                 detached = false;
703                 spin_lock(&cookie->lock);
704                 spin_lock(&object->lock);
705
706                 if (object->cookie == cookie) {
707                         hlist_del_init(&object->cookie_link);
708                         object->cookie = NULL;
709                         detached = true;
710                 }
711                 spin_unlock(&cookie->lock);
712                 fscache_cookie_put(cookie);
713                 if (detached)
714                         fscache_cookie_put(cookie);
715         }
716
717         spin_unlock(&object->lock);
718
719         fscache_drop_object(object);
720 }
721
722 /*
723  * withdraw an object from active service at the behest of the cache
724  * - need break the links to a cached object cookie
725  * - called under two situations:
726  *   (1) recycler decides to reclaim an in-use object
727  *   (2) a cache is unmounted
728  * - have to take care as the cookie can be being relinquished by the netfs
729  *   simultaneously
730  * - the object is pinned by the caller holding a refcount on it
731  */
732 void fscache_withdrawing_object(struct fscache_cache *cache,
733                                 struct fscache_object *object)
734 {
735         bool enqueue = false;
736
737         _enter(",OBJ%x", object->debug_id);
738
739         spin_lock(&object->lock);
740         if (object->state < FSCACHE_OBJECT_WITHDRAWING) {
741                 object->state = FSCACHE_OBJECT_WITHDRAWING;
742                 enqueue = true;
743         }
744         spin_unlock(&object->lock);
745
746         if (enqueue)
747                 fscache_enqueue_object(object);
748
749         _leave("");
750 }
751
752 /*
753  * allow the slow work item processor to get a ref on an object
754  */
755 static int fscache_object_slow_work_get_ref(struct slow_work *work)
756 {
757         struct fscache_object *object =
758                 container_of(work, struct fscache_object, work);
759         int ret;
760
761         fscache_stat(&fscache_n_cop_grab_object);
762         ret = object->cache->ops->grab_object(object) ? 0 : -EAGAIN;
763         fscache_stat_d(&fscache_n_cop_grab_object);
764         return ret;
765 }
766
767 /*
768  * allow the slow work item processor to discard a ref on a work item
769  */
770 static void fscache_object_slow_work_put_ref(struct slow_work *work)
771 {
772         struct fscache_object *object =
773                 container_of(work, struct fscache_object, work);
774
775         fscache_stat(&fscache_n_cop_put_object);
776         object->cache->ops->put_object(object);
777         fscache_stat_d(&fscache_n_cop_put_object);
778 }
779
780 /*
781  * enqueue an object for metadata-type processing
782  */
783 void fscache_enqueue_object(struct fscache_object *object)
784 {
785         _enter("{OBJ%x}", object->debug_id);
786
787         slow_work_enqueue(&object->work);
788 }
789
790 /*
791  * enqueue the dependents of an object for metadata-type processing
792  * - the caller must hold the object's lock
793  * - this may cause an already locked object to wind up being processed again
794  */
795 static void fscache_enqueue_dependents(struct fscache_object *object)
796 {
797         struct fscache_object *dep;
798
799         _enter("{OBJ%x}", object->debug_id);
800
801         if (list_empty(&object->dependents))
802                 return;
803
804         spin_lock(&object->lock);
805
806         while (!list_empty(&object->dependents)) {
807                 dep = list_entry(object->dependents.next,
808                                  struct fscache_object, dep_link);
809                 list_del_init(&dep->dep_link);
810
811
812                 /* sort onto appropriate lists */
813                 fscache_enqueue_object(dep);
814                 fscache_stat(&fscache_n_cop_put_object);
815                 dep->cache->ops->put_object(dep);
816                 fscache_stat_d(&fscache_n_cop_put_object);
817
818                 if (!list_empty(&object->dependents))
819                         cond_resched_lock(&object->lock);
820         }
821
822         spin_unlock(&object->lock);
823 }
824
825 /*
826  * remove an object from whatever queue it's waiting on
827  * - the caller must hold object->lock
828  */
829 void fscache_dequeue_object(struct fscache_object *object)
830 {
831         _enter("{OBJ%x}", object->debug_id);
832
833         if (!list_empty(&object->dep_link)) {
834                 spin_lock(&object->parent->lock);
835                 list_del_init(&object->dep_link);
836                 spin_unlock(&object->parent->lock);
837         }
838
839         _leave("");
840 }
841
842 /**
843  * fscache_check_aux - Ask the netfs whether an object on disk is still valid
844  * @object: The object to ask about
845  * @data: The auxiliary data for the object
846  * @datalen: The size of the auxiliary data
847  *
848  * This function consults the netfs about the coherency state of an object
849  */
850 enum fscache_checkaux fscache_check_aux(struct fscache_object *object,
851                                         const void *data, uint16_t datalen)
852 {
853         enum fscache_checkaux result;
854
855         if (!object->cookie->def->check_aux) {
856                 fscache_stat(&fscache_n_checkaux_none);
857                 return FSCACHE_CHECKAUX_OKAY;
858         }
859
860         result = object->cookie->def->check_aux(object->cookie->netfs_data,
861                                                 data, datalen);
862         switch (result) {
863                 /* entry okay as is */
864         case FSCACHE_CHECKAUX_OKAY:
865                 fscache_stat(&fscache_n_checkaux_okay);
866                 break;
867
868                 /* entry requires update */
869         case FSCACHE_CHECKAUX_NEEDS_UPDATE:
870                 fscache_stat(&fscache_n_checkaux_update);
871                 break;
872
873                 /* entry requires deletion */
874         case FSCACHE_CHECKAUX_OBSOLETE:
875                 fscache_stat(&fscache_n_checkaux_obsolete);
876                 break;
877
878         default:
879                 BUG();
880         }
881
882         return result;
883 }
884 EXPORT_SYMBOL(fscache_check_aux);