2874c5fd28426 (Thomas Gleixner 2019-05-27 08:55:01 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 2) /* FS-Cache object state machine handler
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 3) *
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 4) * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 5) * Written by David Howells (dhowells@redhat.com)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 6) *
67145c23e70b0 (Mauro Carvalho Chehab 2020-04-27 23:16:53 +0200 7) * See Documentation/filesystems/caching/object.rst for a description of the
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 8) * object state machine and the in-kernel representations.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 9) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 10)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 11) #define FSCACHE_DEBUG_LEVEL COOKIE
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 12) #include <linux/module.h>
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 13) #include <linux/slab.h>
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 14) #include <linux/prefetch.h>
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 15) #include "internal.h"
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 16)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 17) static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 18) static const struct fscache_state *fscache_kill_dependents(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 19) static const struct fscache_state *fscache_drop_object(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 20) static const struct fscache_state *fscache_initialise_object(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 21) static const struct fscache_state *fscache_invalidate_object(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 22) static const struct fscache_state *fscache_jumpstart_dependents(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 23) static const struct fscache_state *fscache_kill_object(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 24) static const struct fscache_state *fscache_lookup_failure(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 25) static const struct fscache_state *fscache_look_up_object(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 26) static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 27) static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 28) static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 29) static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 30)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 31) #define __STATE_NAME(n) fscache_osm_##n
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 32) #define STATE(n) (&__STATE_NAME(n))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 33)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 34) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 35) * Define a work state. Work states are execution states. No event processing
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 36) * is performed by them. The function attached to a work state returns a
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 37) * pointer indicating the next state to which the state machine should
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 38) * transition. Returning NO_TRANSIT repeats the current state, but goes back
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 39) * to the scheduler first.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 40) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 41) #define WORK_STATE(n, sn, f) \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 42) const struct fscache_state __STATE_NAME(n) = { \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 43) .name = #n, \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 44) .short_name = sn, \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 45) .work = f \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 46) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 47)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 48) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 49) * Returns from work states.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 50) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 51) #define transit_to(state) ({ prefetch(&STATE(state)->work); STATE(state); })
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 52)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 53) #define NO_TRANSIT ((struct fscache_state *)NULL)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 54)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 55) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 56) * Define a wait state. Wait states are event processing states. No execution
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 57) * is performed by them. Wait states are just tables of "if event X occurs,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 58) * clear it and transition to state Y". The dispatcher returns to the
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 59) * scheduler if none of the events in which the wait state has an interest are
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 60) * currently pending.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 61) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 62) #define WAIT_STATE(n, sn, ...) \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 63) const struct fscache_state __STATE_NAME(n) = { \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 64) .name = #n, \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 65) .short_name = sn, \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 66) .work = NULL, \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 67) .transitions = { __VA_ARGS__, { 0, NULL } } \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 68) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 69)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 70) #define TRANSIT_TO(state, emask) \
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 71) { .events = (emask), .transit_to = STATE(state) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 72)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 73) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 74) * The object state machine.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 75) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 76) static WORK_STATE(INIT_OBJECT, "INIT", fscache_initialise_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 77) static WORK_STATE(PARENT_READY, "PRDY", fscache_parent_ready);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 78) static WORK_STATE(ABORT_INIT, "ABRT", fscache_abort_initialisation);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 79) static WORK_STATE(LOOK_UP_OBJECT, "LOOK", fscache_look_up_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 80) static WORK_STATE(CREATE_OBJECT, "CRTO", fscache_look_up_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 81) static WORK_STATE(OBJECT_AVAILABLE, "AVBL", fscache_object_available);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 82) static WORK_STATE(JUMPSTART_DEPS, "JUMP", fscache_jumpstart_dependents);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 83)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 84) static WORK_STATE(INVALIDATE_OBJECT, "INVL", fscache_invalidate_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 85) static WORK_STATE(UPDATE_OBJECT, "UPDT", fscache_update_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 86)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 87) static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 88) static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 89) static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 90) static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 91) static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 92)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 93) static WAIT_STATE(WAIT_FOR_INIT, "?INI",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 94) TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 95)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 96) static WAIT_STATE(WAIT_FOR_PARENT, "?PRN",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 97) TRANSIT_TO(PARENT_READY, 1 << FSCACHE_OBJECT_EV_PARENT_READY));
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 98)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 99) static WAIT_STATE(WAIT_FOR_CMD, "?CMD",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 100) TRANSIT_TO(INVALIDATE_OBJECT, 1 << FSCACHE_OBJECT_EV_INVALIDATE),
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 101) TRANSIT_TO(UPDATE_OBJECT, 1 << FSCACHE_OBJECT_EV_UPDATE),
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 102) TRANSIT_TO(JUMPSTART_DEPS, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 103)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 104) static WAIT_STATE(WAIT_FOR_CLEARANCE, "?CLR",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 105) TRANSIT_TO(KILL_OBJECT, 1 << FSCACHE_OBJECT_EV_CLEARED));
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 106)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 107) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 108) * Out-of-band event transition tables. These are for handling unexpected
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 109) * events, such as an I/O error. If an OOB event occurs, the state machine
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 110) * clears and disables the event and forces a transition to the nominated work
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 111) * state (acurrently executing work states will complete first).
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 112) *
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 113) * In such a situation, object->state remembers the state the machine should
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 114) * have been in/gone to and returning NO_TRANSIT returns to that.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 115) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 116) static const struct fscache_transition fscache_osm_init_oob[] = {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 117) TRANSIT_TO(ABORT_INIT,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 118) (1 << FSCACHE_OBJECT_EV_ERROR) |
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 119) (1 << FSCACHE_OBJECT_EV_KILL)),
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 120) { 0, NULL }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 121) };
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 122)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 123) static const struct fscache_transition fscache_osm_lookup_oob[] = {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 124) TRANSIT_TO(LOOKUP_FAILURE,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 125) (1 << FSCACHE_OBJECT_EV_ERROR) |
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 126) (1 << FSCACHE_OBJECT_EV_KILL)),
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 127) { 0, NULL }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 128) };
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 129)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 130) static const struct fscache_transition fscache_osm_run_oob[] = {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 131) TRANSIT_TO(KILL_OBJECT,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 132) (1 << FSCACHE_OBJECT_EV_ERROR) |
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 133) (1 << FSCACHE_OBJECT_EV_KILL)),
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 134) { 0, NULL }
440f0affe247e (David Howells 2009-11-19 18:11:01 +0000 135) };
440f0affe247e (David Howells 2009-11-19 18:11:01 +0000 136)
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 137) static int fscache_get_object(struct fscache_object *,
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 138) enum fscache_obj_ref_trace);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 139) static void fscache_put_object(struct fscache_object *,
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 140) enum fscache_obj_ref_trace);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 141) static bool fscache_enqueue_dependents(struct fscache_object *, int);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 142) static void fscache_dequeue_object(struct fscache_object *);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 143) static void fscache_update_aux_data(struct fscache_object *);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 144)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 145) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 146) * we need to notify the parent when an op completes that we had outstanding
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 147) * upon it
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 148) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 149) static inline void fscache_done_parent_op(struct fscache_object *object)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 150) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 151) struct fscache_object *parent = object->parent;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 152)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 153) _enter("OBJ%x {OBJ%x,%x}",
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 154) object->debug_id, parent->debug_id, parent->n_ops);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 155)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 156) spin_lock_nested(&parent->lock, 1);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 157) parent->n_obj_ops--;
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 158) parent->n_ops--;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 159) if (parent->n_ops == 0)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 160) fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 161) spin_unlock(&parent->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 162) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 163)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 164) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 165) * Object state machine dispatcher.
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 166) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 167) static void fscache_object_sm_dispatcher(struct fscache_object *object)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 168) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 169) const struct fscache_transition *t;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 170) const struct fscache_state *state, *new_state;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 171) unsigned long events, event_mask;
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 172) bool oob;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 173) int event = -1;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 174)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 175) ASSERT(object != NULL);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 176)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 177) _enter("{OBJ%x,%s,%lx}",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 178) object->debug_id, object->state->name, object->events);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 179)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 180) event_mask = object->event_mask;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 181) restart:
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 182) object->event_mask = 0; /* Mask normal event handling */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 183) state = object->state;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 184) restart_masked:
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 185) events = object->events;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 186)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 187) /* Handle any out-of-band events (typically an error) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 188) if (events & object->oob_event_mask) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 189) _debug("{OBJ%x} oob %lx",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 190) object->debug_id, events & object->oob_event_mask);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 191) oob = true;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 192) for (t = object->oob_table; t->events; t++) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 193) if (events & t->events) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 194) state = t->transit_to;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 195) ASSERT(state->work != NULL);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 196) event = fls(events & t->events) - 1;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 197) __clear_bit(event, &object->oob_event_mask);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 198) clear_bit(event, &object->events);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 199) goto execute_work_state;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 200) }
d461d26dde901 (David Howells 2009-11-19 18:11:41 +0000 201) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 202) }
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 203) oob = false;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 204)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 205) /* Wait states are just transition tables */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 206) if (!state->work) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 207) if (events & event_mask) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 208) for (t = state->transitions; t->events; t++) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 209) if (events & t->events) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 210) new_state = t->transit_to;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 211) event = fls(events & t->events) - 1;
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 212) trace_fscache_osm(object, state,
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 213) true, false, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 214) clear_bit(event, &object->events);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 215) _debug("{OBJ%x} ev %d: %s -> %s",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 216) object->debug_id, event,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 217) state->name, new_state->name);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 218) object->state = state = new_state;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 219) goto execute_work_state;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 220) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 221) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 222)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 223) /* The event mask didn't include all the tabled bits */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 224) BUG();
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 225) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 226) /* Randomly woke up */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 227) goto unmask_events;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 228) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 229)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 230) execute_work_state:
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 231) _debug("{OBJ%x} exec %s", object->debug_id, state->name);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 232)
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 233) trace_fscache_osm(object, state, false, oob, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 234) new_state = state->work(object, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 235) event = -1;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 236) if (new_state == NO_TRANSIT) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 237) _debug("{OBJ%x} %s notrans", object->debug_id, state->name);
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 238) if (unlikely(state == STATE(OBJECT_DEAD))) {
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 239) _leave(" [dead]");
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 240) return;
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 241) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 242) fscache_enqueue_object(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 243) event_mask = object->oob_event_mask;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 244) goto unmask_events;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 245) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 246)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 247) _debug("{OBJ%x} %s -> %s",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 248) object->debug_id, state->name, new_state->name);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 249) object->state = state = new_state;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 250)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 251) if (state->work) {
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 252) if (unlikely(state == STATE(OBJECT_DEAD))) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 253) _leave(" [dead]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 254) return;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 255) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 256) goto restart_masked;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 257) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 258)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 259) /* Transited to wait state */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 260) event_mask = object->oob_event_mask;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 261) for (t = state->transitions; t->events; t++)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 262) event_mask |= t->events;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 263)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 264) unmask_events:
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 265) object->event_mask = event_mask;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 266) smp_mb();
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 267) events = object->events;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 268) if (events & event_mask)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 269) goto restart;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 270) _leave(" [msk %lx]", event_mask);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 271) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 272)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 273) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 274) * execute an object
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 275) */
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 276) static void fscache_object_work_func(struct work_struct *work)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 277) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 278) struct fscache_object *object =
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 279) container_of(work, struct fscache_object, work);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 280) unsigned long start;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 281)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 282) _enter("{OBJ%x}", object->debug_id);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 283)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 284) start = jiffies;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 285) fscache_object_sm_dispatcher(object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 286) fscache_hist(fscache_objs_histogram, start);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 287) fscache_put_object(object, fscache_obj_put_work);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 288) }
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 289)
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 290) /**
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 291) * fscache_object_init - Initialise a cache object description
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 292) * @object: Object description
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 293) * @cookie: Cookie object will be attached to
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 294) * @cache: Cache in which backing object will be found
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 295) *
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 296) * Initialise a cache object description to its basic values.
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 297) *
0e822145b5642 (Mauro Carvalho Chehab 2020-04-27 23:16:58 +0200 298) * See Documentation/filesystems/caching/backend-api.rst for a complete
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 299) * description.
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 300) */
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 301) void fscache_object_init(struct fscache_object *object,
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 302) struct fscache_cookie *cookie,
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 303) struct fscache_cache *cache)
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 304) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 305) const struct fscache_transition *t;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 306)
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 307) atomic_inc(&cache->object_count);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 308)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 309) object->state = STATE(WAIT_FOR_INIT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 310) object->oob_table = fscache_osm_init_oob;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 311) object->flags = 1 << FSCACHE_OBJECT_IS_LIVE;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 312) spin_lock_init(&object->lock);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 313) INIT_LIST_HEAD(&object->cache_link);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 314) INIT_HLIST_NODE(&object->cookie_link);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 315) INIT_WORK(&object->work, fscache_object_work_func);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 316) INIT_LIST_HEAD(&object->dependents);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 317) INIT_LIST_HEAD(&object->dep_link);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 318) INIT_LIST_HEAD(&object->pending_ops);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 319) object->n_children = 0;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 320) object->n_ops = object->n_in_progress = object->n_exclusive = 0;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 321) object->events = 0;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 322) object->store_limit = 0;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 323) object->store_limit_l = 0;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 324) object->cache = cache;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 325) object->cookie = cookie;
f29507ce66701 (Kiran Kumar Modukuri 2018-06-21 13:31:44 -0700 326) fscache_cookie_get(cookie, fscache_cookie_get_attach_object);
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 327) object->parent = NULL;
7026f1929e189 (David Howells 2014-02-17 15:01:47 +0000 328) #ifdef CONFIG_FSCACHE_OBJECT_LIST
7026f1929e189 (David Howells 2014-02-17 15:01:47 +0000 329) RB_CLEAR_NODE(&object->objlist_link);
7026f1929e189 (David Howells 2014-02-17 15:01:47 +0000 330) #endif
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 331)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 332) object->oob_event_mask = 0;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 333) for (t = object->oob_table; t->events; t++)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 334) object->oob_event_mask |= t->events;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 335) object->event_mask = object->oob_event_mask;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 336) for (t = object->state->transitions; t->events; t++)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 337) object->event_mask |= t->events;
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 338) }
610be24ee434a (David Howells 2013-05-10 19:50:25 +0100 339) EXPORT_SYMBOL(fscache_object_init);
440f0affe247e (David Howells 2009-11-19 18:11:01 +0000 340)
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 341) /*
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 342) * Mark the object as no longer being live, making sure that we synchronise
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 343) * against op submission.
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 344) */
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 345) static inline void fscache_mark_object_dead(struct fscache_object *object)
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 346) {
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 347) spin_lock(&object->lock);
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 348) clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 349) spin_unlock(&object->lock);
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 350) }
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 351)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 352) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 353) * Abort object initialisation before we start it.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 354) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 355) static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 356) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 357) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 358) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 359)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 360) object->oob_event_mask = 0;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 361) fscache_dequeue_object(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 362) return transit_to(KILL_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 363) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 364)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 365) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 366) * initialise an object
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 367) * - check the specified object's parent to see if we can make use of it
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 368) * immediately to do a creation
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 369) * - we may need to start the process of creating a parent and we need to wait
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 370) * for the parent's lookup and creation to complete if it's not there yet
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 371) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 372) static const struct fscache_state *fscache_initialise_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 373) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 374) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 375) struct fscache_object *parent;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 376) bool success;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 377)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 378) _enter("{OBJ%x},%d", object->debug_id, event);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 379)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 380) ASSERT(list_empty(&object->dep_link));
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 381)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 382) parent = object->parent;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 383) if (!parent) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 384) _leave(" [no parent]");
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 385) return transit_to(DROP_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 386) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 387)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 388) _debug("parent: %s of:%lx", parent->state->name, parent->flags);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 389)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 390) if (fscache_object_is_dying(parent)) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 391) _leave(" [bad parent]");
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 392) return transit_to(DROP_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 393) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 394)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 395) if (fscache_object_is_available(parent)) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 396) _leave(" [ready]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 397) return transit_to(PARENT_READY);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 398) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 399)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 400) _debug("wait");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 401)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 402) spin_lock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 403) fscache_stat(&fscache_n_cop_grab_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 404) success = false;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 405) if (fscache_object_is_live(parent) &&
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 406) object->cache->ops->grab_object(object, fscache_obj_get_add_to_deps)) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 407) list_add(&object->dep_link, &parent->dependents);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 408) success = true;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 409) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 410) fscache_stat_d(&fscache_n_cop_grab_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 411) spin_unlock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 412) if (!success) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 413) _leave(" [grab failed]");
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 414) return transit_to(DROP_OBJECT);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 415) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 416)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 417) /* fscache_acquire_non_index_cookie() uses this
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 418) * to wake the chain up */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 419) fscache_raise_event(parent, FSCACHE_OBJECT_EV_NEW_CHILD);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 420) _leave(" [wait]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 421) return transit_to(WAIT_FOR_PARENT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 422) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 423)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 424) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 425) * Once the parent object is ready, we should kick off our lookup op.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 426) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 427) static const struct fscache_state *fscache_parent_ready(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 428) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 429) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 430) struct fscache_object *parent = object->parent;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 431)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 432) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 433)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 434) ASSERT(parent != NULL);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 435)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 436) spin_lock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 437) parent->n_ops++;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 438) parent->n_obj_ops++;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 439) object->lookup_jif = jiffies;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 440) spin_unlock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 441)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 442) _leave("");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 443) return transit_to(LOOK_UP_OBJECT);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 444) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 445)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 446) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 447) * look an object up in the cache from which it was allocated
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 448) * - we hold an "access lock" on the parent object, so the parent object cannot
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 449) * be withdrawn by either party till we've finished
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 450) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 451) static const struct fscache_state *fscache_look_up_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 452) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 453) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 454) struct fscache_cookie *cookie = object->cookie;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 455) struct fscache_object *parent = object->parent;
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 456) int ret;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 457)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 458) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 459)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 460) object->oob_table = fscache_osm_lookup_oob;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 461)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 462) ASSERT(parent != NULL);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 463) ASSERTCMP(parent->n_ops, >, 0);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 464) ASSERTCMP(parent->n_obj_ops, >, 0);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 465)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 466) /* make sure the parent is still available */
493f7bc11457b (David Howells 2013-05-10 19:50:26 +0100 467) ASSERT(fscache_object_is_available(parent));
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 468)
493f7bc11457b (David Howells 2013-05-10 19:50:26 +0100 469) if (fscache_object_is_dying(parent) ||
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 470) test_bit(FSCACHE_IOERROR, &object->cache->flags) ||
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 471) !fscache_use_cookie(object)) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 472) _leave(" [unavailable]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 473) return transit_to(LOOKUP_FAILURE);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 474) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 475)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 476) _debug("LOOKUP \"%s\" in \"%s\"",
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 477) cookie->def->name, object->cache->tag->name);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 478)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 479) fscache_stat(&fscache_n_object_lookups);
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 480) fscache_stat(&fscache_n_cop_lookup_object);
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 481) ret = object->cache->ops->lookup_object(object);
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 482) fscache_stat_d(&fscache_n_cop_lookup_object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 483)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 484) fscache_unuse_cookie(object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 485)
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 486) if (ret == -ETIMEDOUT) {
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 487) /* probably stuck behind another object, so move this one to
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 488) * the back of the queue */
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 489) fscache_stat(&fscache_n_object_lookups_timed_out);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 490) _leave(" [timeout]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 491) return NO_TRANSIT;
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 492) }
fee096deb4f33 (David Howells 2009-11-19 18:12:05 +0000 493)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 494) if (ret < 0) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 495) _leave(" [error]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 496) return transit_to(LOOKUP_FAILURE);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 497) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 498)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 499) _leave(" [ok]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 500) return transit_to(OBJECT_AVAILABLE);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 501) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 502)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 503) /**
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 504) * fscache_object_lookup_negative - Note negative cookie lookup
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 505) * @object: Object pointing to cookie to mark
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 506) *
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 507) * Note negative lookup, permitting those waiting to read data from an already
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 508) * existing backing object to continue as there's no data for them to read.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 509) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 510) void fscache_object_lookup_negative(struct fscache_object *object)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 511) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 512) struct fscache_cookie *cookie = object->cookie;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 513)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 514) _enter("{OBJ%x,%s}", object->debug_id, object->state->name);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 515)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 516) if (!test_and_set_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 517) fscache_stat(&fscache_n_object_lookups_negative);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 518)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 519) /* Allow write requests to begin stacking up and read requests to begin
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 520) * returning ENODATA.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 521) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 522) set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
94d30ae90a00c (David Howells 2013-09-21 00:09:31 +0100 523) clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 524)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 525) _debug("wake up lookup %p", &cookie->flags);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 526) clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 527) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 528) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 529) _leave("");
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 530) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 531) EXPORT_SYMBOL(fscache_object_lookup_negative);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 532)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 533) /**
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 534) * fscache_obtained_object - Note successful object lookup or creation
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 535) * @object: Object pointing to cookie to mark
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 536) *
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 537) * Note successful lookup and/or creation, permitting those waiting to write
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 538) * data to a backing object to continue.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 539) *
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 540) * Note that after calling this, an object's cookie may be relinquished by the
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 541) * netfs, and so must be accessed with object lock held.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 542) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 543) void fscache_obtained_object(struct fscache_object *object)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 544) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 545) struct fscache_cookie *cookie = object->cookie;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 546)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 547) _enter("{OBJ%x,%s}", object->debug_id, object->state->name);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 548)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 549) /* if we were still looking up, then we must have a positive lookup
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 550) * result, in which case there may be data available */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 551) if (!test_and_set_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 552) fscache_stat(&fscache_n_object_lookups_positive);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 553)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 554) /* We do (presumably) have data */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 555) clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
94d30ae90a00c (David Howells 2013-09-21 00:09:31 +0100 556) clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 557)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 558) /* Allow write requests to begin stacking up and read requests
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 559) * to begin shovelling data.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 560) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 561) clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 562) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 563) } else {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 564) fscache_stat(&fscache_n_object_created);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 565) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 566)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 567) set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 568) _leave("");
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 569) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 570) EXPORT_SYMBOL(fscache_obtained_object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 571)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 572) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 573) * handle an object that has just become available
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 574) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 575) static const struct fscache_state *fscache_object_available(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 576) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 577) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 578) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 579)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 580) object->oob_table = fscache_osm_run_oob;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 581)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 582) spin_lock(&object->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 583)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 584) fscache_done_parent_op(object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 585) if (object->n_in_progress == 0) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 586) if (object->n_ops > 0) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 587) ASSERTCMP(object->n_ops, >=, object->n_obj_ops);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 588) fscache_start_operations(object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 589) } else {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 590) ASSERT(list_empty(&object->pending_ops));
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 591) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 592) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 593) spin_unlock(&object->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 594)
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 595) fscache_stat(&fscache_n_cop_lookup_complete);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 596) object->cache->ops->lookup_complete(object);
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 597) fscache_stat_d(&fscache_n_cop_lookup_complete);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 598)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 599) fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 600) fscache_stat(&fscache_n_object_avail);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 601)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 602) _leave("");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 603) return transit_to(JUMPSTART_DEPS);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 604) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 605)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 606) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 607) * Wake up this object's dependent objects now that we've become available.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 608) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 609) static const struct fscache_state *fscache_jumpstart_dependents(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 610) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 611) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 612) _enter("{OBJ%x},%d", object->debug_id, event);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 613)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 614) if (!fscache_enqueue_dependents(object, FSCACHE_OBJECT_EV_PARENT_READY))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 615) return NO_TRANSIT; /* Not finished; requeue */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 616) return transit_to(WAIT_FOR_CMD);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 617) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 618)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 619) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 620) * Handle lookup or creation failute.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 621) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 622) static const struct fscache_state *fscache_lookup_failure(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 623) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 624) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 625) struct fscache_cookie *cookie;
6897e3df8fc37 (David Howells 2009-11-19 18:11:22 +0000 626)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 627) _enter("{OBJ%x},%d", object->debug_id, event);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 628)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 629) object->oob_event_mask = 0;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 630)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 631) fscache_stat(&fscache_n_cop_lookup_complete);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 632) object->cache->ops->lookup_complete(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 633) fscache_stat_d(&fscache_n_cop_lookup_complete);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 634)
6515d1dbf424c (David Howells 2015-02-25 11:53:57 +0000 635) set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags);
6515d1dbf424c (David Howells 2015-02-25 11:53:57 +0000 636)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 637) cookie = object->cookie;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 638) set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 639) if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 640) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 641)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 642) fscache_done_parent_op(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 643) return transit_to(KILL_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 644) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 645)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 646) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 647) * Wait for completion of all active operations on this object and the death of
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 648) * all child objects of this object.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 649) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 650) static const struct fscache_state *fscache_kill_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 651) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 652) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 653) _enter("{OBJ%x,%d,%d},%d",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 654) object->debug_id, object->n_ops, object->n_children, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 655)
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 656) fscache_mark_object_dead(object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 657) object->oob_event_mask = 0;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 658)
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 659) if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 660) /* Reject any new read/write ops and abort any that are pending. */
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 661) clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 662) fscache_cancel_all_ops(object);
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 663) }
6bdded59c8933 (David Howells 2017-01-18 14:29:25 +0000 664)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 665) if (list_empty(&object->dependents) &&
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 666) object->n_ops == 0 &&
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 667) object->n_children == 0)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 668) return transit_to(DROP_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 669)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 670) if (object->n_in_progress == 0) {
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 671) spin_lock(&object->lock);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 672) if (object->n_ops > 0 && object->n_in_progress == 0)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 673) fscache_start_operations(object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 674) spin_unlock(&object->lock);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 675) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 676)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 677) if (!list_empty(&object->dependents))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 678) return transit_to(KILL_DEPENDENTS);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 679)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 680) return transit_to(WAIT_FOR_CLEARANCE);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 681) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 682)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 683) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 684) * Kill dependent objects.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 685) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 686) static const struct fscache_state *fscache_kill_dependents(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 687) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 688) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 689) _enter("{OBJ%x},%d", object->debug_id, event);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 690)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 691) if (!fscache_enqueue_dependents(object, FSCACHE_OBJECT_EV_KILL))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 692) return NO_TRANSIT; /* Not finished */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 693) return transit_to(WAIT_FOR_CLEARANCE);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 694) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 695)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 696) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 697) * Drop an object's attachments
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 698) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 699) static const struct fscache_state *fscache_drop_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 700) int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 701) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 702) struct fscache_object *parent = object->parent;
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 703) struct fscache_cookie *cookie = object->cookie;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 704) struct fscache_cache *cache = object->cache;
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 705) bool awaken = false;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 706)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 707) _enter("{OBJ%x,%d},%d", object->debug_id, object->n_children, event);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 708)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 709) ASSERT(cookie != NULL);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 710) ASSERT(!hlist_unhashed(&object->cookie_link));
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 711)
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 712) if (test_bit(FSCACHE_COOKIE_AUX_UPDATED, &cookie->flags)) {
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 713) _debug("final update");
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 714) fscache_update_aux_data(object);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 715) }
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 716)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 717) /* Make sure the cookie no longer points here and that the netfs isn't
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 718) * waiting for us.
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 719) */
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 720) spin_lock(&cookie->lock);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 721) hlist_del_init(&object->cookie_link);
94d30ae90a00c (David Howells 2013-09-21 00:09:31 +0100 722) if (hlist_empty(&cookie->backing_objects) &&
94d30ae90a00c (David Howells 2013-09-21 00:09:31 +0100 723) test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 724) awaken = true;
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 725) spin_unlock(&cookie->lock);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 726)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 727) if (awaken)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 728) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
c5a94f434c825 (NeilBrown 2018-10-26 17:16:29 +1100 729) if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
c5a94f434c825 (NeilBrown 2018-10-26 17:16:29 +1100 730) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
c5a94f434c825 (NeilBrown 2018-10-26 17:16:29 +1100 731)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 732)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 733) /* Prevent a race with our last child, which has to signal EV_CLEARED
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 734) * before dropping our spinlock.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 735) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 736) spin_lock(&object->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 737) spin_unlock(&object->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 738)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 739) /* Discard from the cache's collection of objects */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 740) spin_lock(&cache->object_list_lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 741) list_del_init(&object->cache_link);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 742) spin_unlock(&cache->object_list_lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 743)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 744) fscache_stat(&fscache_n_cop_drop_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 745) cache->ops->drop_object(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 746) fscache_stat_d(&fscache_n_cop_drop_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 747)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 748) /* The parent object wants to know when all it dependents have gone */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 749) if (parent) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 750) _debug("release parent OBJ%x {%d}",
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 751) parent->debug_id, parent->n_children);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 752)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 753) spin_lock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 754) parent->n_children--;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 755) if (parent->n_children == 0)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 756) fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 757) spin_unlock(&parent->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 758) object->parent = NULL;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 759) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 760)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 761) /* this just shifts the object release to the work processor */
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 762) fscache_put_object(object, fscache_obj_put_drop_obj);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 763) fscache_stat(&fscache_n_object_dead);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 764)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 765) _leave("");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 766) return transit_to(OBJECT_DEAD);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 767) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 768)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 769) /*
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 770) * get a ref on an object
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 771) */
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 772) static int fscache_get_object(struct fscache_object *object,
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 773) enum fscache_obj_ref_trace why)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 774) {
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 775) int ret;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 776)
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 777) fscache_stat(&fscache_n_cop_grab_object);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 778) ret = object->cache->ops->grab_object(object, why) ? 0 : -EAGAIN;
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 779) fscache_stat_d(&fscache_n_cop_grab_object);
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 780) return ret;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 781) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 782)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 783) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 784) * Discard a ref on an object
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 785) */
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 786) static void fscache_put_object(struct fscache_object *object,
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 787) enum fscache_obj_ref_trace why)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 788) {
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 789) fscache_stat(&fscache_n_cop_put_object);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 790) object->cache->ops->put_object(object, why);
52bd75fdb135d (David Howells 2009-11-19 18:11:08 +0000 791) fscache_stat_d(&fscache_n_cop_put_object);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 792) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 793)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 794) /**
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 795) * fscache_object_destroy - Note that a cache object is about to be destroyed
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 796) * @object: The object to be destroyed
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 797) *
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 798) * Note the imminent destruction and deallocation of a cache object record.
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 799) */
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 800) void fscache_object_destroy(struct fscache_object *object)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 801) {
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 802) fscache_objlist_remove(object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 803)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 804) /* We can get rid of the cookie now */
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 805) fscache_cookie_put(object->cookie, fscache_cookie_put_object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 806) object->cookie = NULL;
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 807) }
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 808) EXPORT_SYMBOL(fscache_object_destroy);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 809)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 810) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 811) * enqueue an object for metadata-type processing
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 812) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 813) void fscache_enqueue_object(struct fscache_object *object)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 814) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 815) _enter("{OBJ%x}", object->debug_id);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 816)
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 817) if (fscache_get_object(object, fscache_obj_get_queue) >= 0) {
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 818) wait_queue_head_t *cong_wq =
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 819) &get_cpu_var(fscache_object_cong_wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 820)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 821) if (queue_work(fscache_object_wq, &object->work)) {
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 822) if (fscache_object_congested())
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 823) wake_up(cong_wq);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 824) } else
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 825) fscache_put_object(object, fscache_obj_put_queue);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 826)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 827) put_cpu_var(fscache_object_cong_wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 828) }
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 829) }
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 830)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 831) /**
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 832) * fscache_object_sleep_till_congested - Sleep until object wq is congested
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 833) * @timeoutp: Scheduler sleep timeout
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 834) *
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 835) * Allow an object handler to sleep until the object workqueue is congested.
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 836) *
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 837) * The caller must set up a wake up event before calling this and must have set
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 838) * the appropriate sleep mode (such as TASK_UNINTERRUPTIBLE) and tested its own
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 839) * condition before calling this function as no test is made here.
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 840) *
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 841) * %true is returned if the object wq is congested, %false otherwise.
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 842) */
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 843) bool fscache_object_sleep_till_congested(signed long *timeoutp)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 844) {
170d800af83f3 (Christoph Lameter 2013-10-15 12:22:29 -0600 845) wait_queue_head_t *cong_wq = this_cpu_ptr(&fscache_object_cong_wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 846) DEFINE_WAIT(wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 847)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 848) if (fscache_object_congested())
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 849) return true;
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 850)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 851) add_wait_queue_exclusive(cong_wq, &wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 852) if (!fscache_object_congested())
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 853) *timeoutp = schedule_timeout(*timeoutp);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 854) finish_wait(cong_wq, &wait);
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 855)
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 856) return fscache_object_congested();
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 857) }
8b8edefa2fffb (Tejun Heo 2010-07-20 22:09:01 +0200 858) EXPORT_SYMBOL_GPL(fscache_object_sleep_till_congested);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 859)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 860) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 861) * Enqueue the dependents of an object for metadata-type processing.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 862) *
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 863) * If we don't manage to finish the list before the scheduler wants to run
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 864) * again then return false immediately. We return true if the list was
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 865) * cleared.
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 866) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 867) static bool fscache_enqueue_dependents(struct fscache_object *object, int event)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 868) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 869) struct fscache_object *dep;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 870) bool ret = true;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 871)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 872) _enter("{OBJ%x}", object->debug_id);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 873)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 874) if (list_empty(&object->dependents))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 875) return true;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 876)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 877) spin_lock(&object->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 878)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 879) while (!list_empty(&object->dependents)) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 880) dep = list_entry(object->dependents.next,
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 881) struct fscache_object, dep_link);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 882) list_del_init(&dep->dep_link);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 883)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 884) fscache_raise_event(dep, event);
a18feb55769b7 (David Howells 2018-04-04 13:41:27 +0100 885) fscache_put_object(dep, fscache_obj_put_enq_dep);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 886)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 887) if (!list_empty(&object->dependents) && need_resched()) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 888) ret = false;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 889) break;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 890) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 891) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 892)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 893) spin_unlock(&object->lock);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 894) return ret;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 895) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 896)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 897) /*
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 898) * remove an object from whatever queue it's waiting on
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 899) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 900) static void fscache_dequeue_object(struct fscache_object *object)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 901) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 902) _enter("{OBJ%x}", object->debug_id);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 903)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 904) if (!list_empty(&object->dep_link)) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 905) spin_lock(&object->parent->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 906) list_del_init(&object->dep_link);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 907) spin_unlock(&object->parent->lock);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 908) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 909)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 910) _leave("");
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 911) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 912)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 913) /**
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 914) * fscache_check_aux - Ask the netfs whether an object on disk is still valid
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 915) * @object: The object to ask about
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 916) * @data: The auxiliary data for the object
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 917) * @datalen: The size of the auxiliary data
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 918) *
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 919) * This function consults the netfs about the coherency state of an object.
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 920) * The caller must be holding a ref on cookie->n_active (held by
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 921) * fscache_look_up_object() on behalf of the cache backend during object lookup
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 922) * and creation).
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 923) */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 924) enum fscache_checkaux fscache_check_aux(struct fscache_object *object,
ee1235a9a0681 (David Howells 2018-04-04 13:41:28 +0100 925) const void *data, uint16_t datalen,
ee1235a9a0681 (David Howells 2018-04-04 13:41:28 +0100 926) loff_t object_size)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 927) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 928) enum fscache_checkaux result;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 929)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 930) if (!object->cookie->def->check_aux) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 931) fscache_stat(&fscache_n_checkaux_none);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 932) return FSCACHE_CHECKAUX_OKAY;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 933) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 934)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 935) result = object->cookie->def->check_aux(object->cookie->netfs_data,
ee1235a9a0681 (David Howells 2018-04-04 13:41:28 +0100 936) data, datalen, object_size);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 937) switch (result) {
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 938) /* entry okay as is */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 939) case FSCACHE_CHECKAUX_OKAY:
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 940) fscache_stat(&fscache_n_checkaux_okay);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 941) break;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 942)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 943) /* entry requires update */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 944) case FSCACHE_CHECKAUX_NEEDS_UPDATE:
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 945) fscache_stat(&fscache_n_checkaux_update);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 946) break;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 947)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 948) /* entry requires deletion */
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 949) case FSCACHE_CHECKAUX_OBSOLETE:
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 950) fscache_stat(&fscache_n_checkaux_obsolete);
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 951) break;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 952)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 953) default:
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 954) BUG();
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 955) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 956)
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 957) return result;
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 958) }
36c9559022850 (David Howells 2009-04-03 16:42:38 +0100 959) EXPORT_SYMBOL(fscache_check_aux);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 960)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 961) /*
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 962) * Asynchronously invalidate an object.
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 963) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 964) static const struct fscache_state *_fscache_invalidate_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 965) int event)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 966) {
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 967) struct fscache_operation *op;
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 968) struct fscache_cookie *cookie = object->cookie;
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 969)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 970) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 971)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 972) /* We're going to need the cookie. If the cookie is not available then
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 973) * retire the object instead.
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 974) */
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 975) if (!fscache_use_cookie(object)) {
e5a955419642e (Matthew Wilcox 2018-04-10 16:36:48 -0700 976) ASSERT(radix_tree_empty(&object->cookie->stores));
94d30ae90a00c (David Howells 2013-09-21 00:09:31 +0100 977) set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 978) _leave(" [no cookie]");
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 979) return transit_to(KILL_OBJECT);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 980) }
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 981)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 982) /* Reject any new read/write ops and abort any that are pending. */
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 983) fscache_invalidate_writes(cookie);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 984) clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 985) fscache_cancel_all_ops(object);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 986)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 987) /* Now we have to wait for in-progress reads and writes */
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 988) op = kzalloc(sizeof(*op), GFP_KERNEL);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 989) if (!op)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 990) goto nomem;
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 991)
08c2e3d087840 (David Howells 2018-04-04 13:41:27 +0100 992) fscache_operation_init(cookie, op, object->cache->ops->invalidate_object,
d3b97ca4a99e4 (David Howells 2015-02-24 10:05:29 +0000 993) NULL, NULL);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 994) op->flags = FSCACHE_OP_ASYNC |
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 995) (1 << FSCACHE_OP_EXCLUSIVE) |
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 996) (1 << FSCACHE_OP_UNUSE_COOKIE);
08c2e3d087840 (David Howells 2018-04-04 13:41:27 +0100 997) trace_fscache_page_op(cookie, NULL, op, fscache_page_op_invalidate);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 998)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 999) spin_lock(&cookie->lock);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1000) if (fscache_submit_exclusive_op(object, op) < 0)
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1001) goto submit_op_failed;
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1002) spin_unlock(&cookie->lock);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1003) fscache_put_operation(op);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1004)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1005) /* Once we've completed the invalidation, we know there will be no data
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1006) * stored in the cache and thus we can reinstate the data-check-skip
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1007) * optimisation.
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1008) */
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1009) set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1010)
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1011) /* We can allow read and write requests to come in once again. They'll
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1012) * queue up behind our exclusive invalidation operation.
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1013) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1014) if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1015) wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1016) _leave(" [ok]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1017) return transit_to(UPDATE_OBJECT);
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1018)
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 1019) nomem:
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 1020) fscache_mark_object_dead(object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 1021) fscache_unuse_cookie(object);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 1022) _leave(" [ENOMEM]");
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 1023) return transit_to(KILL_OBJECT);
1362729b169b7 (David Howells 2013-05-10 19:50:26 +0100 1024)
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1025) submit_op_failed:
f09b443d0e09f (David Howells 2015-02-24 10:05:28 +0000 1026) fscache_mark_object_dead(object);
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1027) spin_unlock(&cookie->lock);
920bce20d7481 (Milosz Tanski 2014-08-13 12:58:21 -0400 1028) fscache_unuse_cookie(object);
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1029) kfree(op);
8d76349d35906 (David Howells 2012-12-05 13:34:48 +0000 1030) _leave(" [EIO]");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1031) return transit_to(KILL_OBJECT);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1032) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1033)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1034) static const struct fscache_state *fscache_invalidate_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1035) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1036) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1037) const struct fscache_state *s;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1038)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1039) fscache_stat(&fscache_n_invalidates_run);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1040) fscache_stat(&fscache_n_cop_invalidate_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1041) s = _fscache_invalidate_object(object, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1042) fscache_stat_d(&fscache_n_cop_invalidate_object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1043) return s;
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1044) }
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1045)
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1046) /*
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1047) * Update auxiliary data.
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1048) */
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1049) static void fscache_update_aux_data(struct fscache_object *object)
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1050) {
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1051) fscache_stat(&fscache_n_updates_run);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1052) fscache_stat(&fscache_n_cop_update_object);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1053) object->cache->ops->update_object(object);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1054) fscache_stat_d(&fscache_n_cop_update_object);
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1055) }
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1056)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1057) /*
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1058) * Asynchronously update an object.
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1059) */
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1060) static const struct fscache_state *fscache_update_object(struct fscache_object *object,
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1061) int event)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1062) {
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1063) _enter("{OBJ%x},%d", object->debug_id, event);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1064)
402cb8dda949d (David Howells 2018-04-04 13:41:28 +0100 1065) fscache_update_aux_data(object);
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1066)
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1067) _leave("");
caaef6900befb (David Howells 2013-05-10 19:50:26 +0100 1068) return transit_to(WAIT_FOR_CMD);
ef778e7ae67cd (David Howells 2012-12-20 21:52:36 +0000 1069) }
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1070)
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1071) /**
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1072) * fscache_object_retrying_stale - Note retrying stale object
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1073) * @object: The object that will be retried
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1074) *
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1075) * Note that an object lookup found an on-disk object that was adjudged to be
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1076) * stale and has been deleted. The lookup will be retried.
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1077) */
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1078) void fscache_object_retrying_stale(struct fscache_object *object)
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1079) {
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1080) fscache_stat(&fscache_n_cache_no_space_reject);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1081) }
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1082) EXPORT_SYMBOL(fscache_object_retrying_stale);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1083)
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1084) /**
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1085) * fscache_object_mark_killed - Note that an object was killed
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1086) * @object: The object that was culled
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1087) * @why: The reason the object was killed.
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1088) *
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1089) * Note that an object was killed. Returns true if the object was
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1090) * already marked killed, false if it wasn't.
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1091) */
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1092) void fscache_object_mark_killed(struct fscache_object *object,
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1093) enum fscache_why_object_killed why)
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1094) {
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1095) if (test_and_set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags)) {
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1096) pr_err("Error: Object already killed by cache [%s]\n",
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1097) object->cache->identifier);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1098) return;
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1099) }
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1100)
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1101) switch (why) {
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1102) case FSCACHE_OBJECT_NO_SPACE:
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1103) fscache_stat(&fscache_n_cache_no_space_reject);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1104) break;
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1105) case FSCACHE_OBJECT_IS_STALE:
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1106) fscache_stat(&fscache_n_cache_stale_objects);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1107) break;
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1108) case FSCACHE_OBJECT_WAS_RETIRED:
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1109) fscache_stat(&fscache_n_cache_retired_objects);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1110) break;
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1111) case FSCACHE_OBJECT_WAS_CULLED:
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1112) fscache_stat(&fscache_n_cache_culled_objects);
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1113) break;
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1114) }
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1115) }
182d919b84902 (David Howells 2015-02-19 23:47:31 +0000 1116) EXPORT_SYMBOL(fscache_object_mark_killed);
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1117)
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1118) /*
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1119) * The object is dead. We can get here if an object gets queued by an event
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1120) * that would lead to its death (such as EV_KILL) when the dispatcher is
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1121) * already running (and so can be requeued) but hasn't yet cleared the event
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1122) * mask.
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1123) */
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1124) static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1125) int event)
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1126) {
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1127) if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1128) &object->flags))
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1129) return NO_TRANSIT;
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1130)
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1131) WARN(true, "FS-Cache object redispatched after death");
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1132) return NO_TRANSIT;
e26bfebdfc0d2 (David Howells 2017-01-31 09:45:28 +0000 1133) }