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