aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fscache')
-rw-r--r--fs/fscache/cache.c32
-rw-r--r--fs/fscache/cookie.c9
-rw-r--r--fs/fscache/internal.h8
-rw-r--r--fs/fscache/object-list.c10
-rw-r--r--fs/fscache/object.c1018
-rw-r--r--fs/fscache/operation.c22
-rw-r--r--fs/fscache/page.c11
7 files changed, 571 insertions, 539 deletions
diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c
index 129ea537f023..f7cff367db7f 100644
--- a/fs/fscache/cache.c
+++ b/fs/fscache/cache.c
@@ -224,8 +224,10 @@ int fscache_add_cache(struct fscache_cache *cache,
224 BUG_ON(!ifsdef); 224 BUG_ON(!ifsdef);
225 225
226 cache->flags = 0; 226 cache->flags = 0;
227 ifsdef->event_mask = ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED); 227 ifsdef->event_mask =
228 ifsdef->state = FSCACHE_OBJECT_ACTIVE; 228 ((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
229 ~(1 << FSCACHE_OBJECT_EV_CLEARED);
230 __set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);
229 231
230 if (!tagname) 232 if (!tagname)
231 tagname = cache->identifier; 233 tagname = cache->identifier;
@@ -330,25 +332,25 @@ static void fscache_withdraw_all_objects(struct fscache_cache *cache,
330{ 332{
331 struct fscache_object *object; 333 struct fscache_object *object;
332 334
333 spin_lock(&cache->object_list_lock);
334
335 while (!list_empty(&cache->object_list)) { 335 while (!list_empty(&cache->object_list)) {
336 object = list_entry(cache->object_list.next, 336 spin_lock(&cache->object_list_lock);
337 struct fscache_object, cache_link);
338 list_move_tail(&object->cache_link, dying_objects);
339 337
340 _debug("withdraw %p", object->cookie); 338 if (!list_empty(&cache->object_list)) {
339 object = list_entry(cache->object_list.next,
340 struct fscache_object, cache_link);
341 list_move_tail(&object->cache_link, dying_objects);
341 342
342 spin_lock(&object->lock); 343 _debug("withdraw %p", object->cookie);
343 spin_unlock(&cache->object_list_lock); 344
344 fscache_raise_event(object, FSCACHE_OBJECT_EV_WITHDRAW); 345 /* This must be done under object_list_lock to prevent
345 spin_unlock(&object->lock); 346 * a race with fscache_drop_object().
347 */
348 fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
349 }
346 350
351 spin_unlock(&cache->object_list_lock);
347 cond_resched(); 352 cond_resched();
348 spin_lock(&cache->object_list_lock);
349 } 353 }
350
351 spin_unlock(&cache->object_list_lock);
352} 354}
353 355
354/** 356/**
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index a5f36c921e91..eee436646989 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -205,7 +205,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
205 205
206 /* initiate the process of looking up all the objects in the chain 206 /* initiate the process of looking up all the objects in the chain
207 * (done by fscache_initialise_object()) */ 207 * (done by fscache_initialise_object()) */
208 fscache_enqueue_object(object); 208 fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);
209 209
210 spin_unlock(&cookie->lock); 210 spin_unlock(&cookie->lock);
211 211
@@ -469,7 +469,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
469{ 469{
470 struct fscache_cache *cache; 470 struct fscache_cache *cache;
471 struct fscache_object *object; 471 struct fscache_object *object;
472 unsigned long event;
473 472
474 fscache_stat(&fscache_n_relinquishes); 473 fscache_stat(&fscache_n_relinquishes);
475 if (retire) 474 if (retire)
@@ -497,8 +496,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
497 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 496 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
498 } 497 }
499 498
500 event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
501
502try_again: 499try_again:
503 spin_lock(&cookie->lock); 500 spin_lock(&cookie->lock);
504 501
@@ -533,7 +530,9 @@ try_again:
533 530
534 cache = object->cache; 531 cache = object->cache;
535 object->cookie = NULL; 532 object->cookie = NULL;
536 fscache_raise_event(object, event); 533 if (retire)
534 set_bit(FSCACHE_OBJECT_RETIRE, &object->flags);
535 fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
537 spin_unlock(&object->lock); 536 spin_unlock(&object->lock);
538 537
539 if (atomic_dec_and_test(&cookie->usage)) 538 if (atomic_dec_and_test(&cookie->usage))
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index ee38fef4be51..3322d3c42ba8 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -97,10 +97,6 @@ extern int fscache_wait_bit_interruptible(void *);
97/* 97/*
98 * object.c 98 * object.c
99 */ 99 */
100extern const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5];
101
102extern void fscache_withdrawing_object(struct fscache_cache *,
103 struct fscache_object *);
104extern void fscache_enqueue_object(struct fscache_object *); 100extern void fscache_enqueue_object(struct fscache_object *);
105 101
106/* 102/*
@@ -291,6 +287,10 @@ static inline void fscache_raise_event(struct fscache_object *object,
291 unsigned event) 287 unsigned event)
292{ 288{
293 BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS); 289 BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS);
290#if 0
291 printk("*** fscache_raise_event(OBJ%d{%lx},%x)\n",
292 object->debug_id, object->event_mask, (1 << event));
293#endif
294 if (!test_and_set_bit(event, &object->events) && 294 if (!test_and_set_bit(event, &object->events) &&
295 test_bit(event, &object->event_mask)) 295 test_bit(event, &object->event_mask))
296 fscache_enqueue_object(object); 296 fscache_enqueue_object(object);
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index f27c89d17885..4a386b080e03 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -174,7 +174,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
174 174
175 if ((unsigned long) v == 1) { 175 if ((unsigned long) v == 1) {
176 seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS" 176 seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
177 " EM EV F S" 177 " EM EV FL S"
178 " | NETFS_COOKIE_DEF TY FL NETFS_DATA"); 178 " | NETFS_COOKIE_DEF TY FL NETFS_DATA");
179 if (config & (FSCACHE_OBJLIST_CONFIG_KEY | 179 if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
180 FSCACHE_OBJLIST_CONFIG_AUX)) 180 FSCACHE_OBJLIST_CONFIG_AUX))
@@ -193,7 +193,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
193 193
194 if ((unsigned long) v == 2) { 194 if ((unsigned long) v == 2) {
195 seq_puts(m, "======== ======== ==== ===== === === === == =====" 195 seq_puts(m, "======== ======== ==== ===== === === === == ====="
196 " == == = =" 196 " == == == ="
197 " | ================ == == ================"); 197 " | ================ == == ================");
198 if (config & (FSCACHE_OBJLIST_CONFIG_KEY | 198 if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
199 FSCACHE_OBJLIST_CONFIG_AUX)) 199 FSCACHE_OBJLIST_CONFIG_AUX))
@@ -219,7 +219,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
219 if (~config) { 219 if (~config) {
220 FILTER(obj->cookie, 220 FILTER(obj->cookie,
221 COOKIE, NOCOOKIE); 221 COOKIE, NOCOOKIE);
222 FILTER(obj->state != FSCACHE_OBJECT_ACTIVE || 222 FILTER(fscache_object_is_active(obj) ||
223 obj->n_ops != 0 || 223 obj->n_ops != 0 ||
224 obj->n_obj_ops != 0 || 224 obj->n_obj_ops != 0 ||
225 obj->flags || 225 obj->flags ||
@@ -235,10 +235,10 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
235 } 235 }
236 236
237 seq_printf(m, 237 seq_printf(m,
238 "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1x | ", 238 "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ",
239 obj->debug_id, 239 obj->debug_id,
240 obj->parent ? obj->parent->debug_id : -1, 240 obj->parent ? obj->parent->debug_id : -1,
241 fscache_object_states_short[obj->state], 241 obj->state->short_name,
242 obj->n_children, 242 obj->n_children,
243 obj->n_ops, 243 obj->n_ops,
244 obj->n_obj_ops, 244 obj->n_obj_ops,
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 863f6873c0f0..8f17debd7979 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -15,52 +15,133 @@
15#define FSCACHE_DEBUG_LEVEL COOKIE 15#define FSCACHE_DEBUG_LEVEL COOKIE
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/prefetch.h>
18#include "internal.h" 19#include "internal.h"
19 20
20const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { 21static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *, int);
21 [FSCACHE_OBJECT_INIT] = "OBJECT_INIT", 22static const struct fscache_state *fscache_kill_dependents(struct fscache_object *, int);
22 [FSCACHE_OBJECT_LOOKING_UP] = "OBJECT_LOOKING_UP", 23static const struct fscache_state *fscache_drop_object(struct fscache_object *, int);
23 [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", 24static const struct fscache_state *fscache_initialise_object(struct fscache_object *, int);
24 [FSCACHE_OBJECT_AVAILABLE] = "OBJECT_AVAILABLE", 25static const struct fscache_state *fscache_invalidate_object(struct fscache_object *, int);
25 [FSCACHE_OBJECT_ACTIVE] = "OBJECT_ACTIVE", 26static const struct fscache_state *fscache_jumpstart_dependents(struct fscache_object *, int);
26 [FSCACHE_OBJECT_INVALIDATING] = "OBJECT_INVALIDATING", 27static const struct fscache_state *fscache_kill_object(struct fscache_object *, int);
27 [FSCACHE_OBJECT_UPDATING] = "OBJECT_UPDATING", 28static const struct fscache_state *fscache_lookup_failure(struct fscache_object *, int);
28 [FSCACHE_OBJECT_DYING] = "OBJECT_DYING", 29static const struct fscache_state *fscache_look_up_object(struct fscache_object *, int);
29 [FSCACHE_OBJECT_LC_DYING] = "OBJECT_LC_DYING", 30static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
30 [FSCACHE_OBJECT_ABORT_INIT] = "OBJECT_ABORT_INIT", 31static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
31 [FSCACHE_OBJECT_RELEASING] = "OBJECT_RELEASING", 32static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
32 [FSCACHE_OBJECT_RECYCLING] = "OBJECT_RECYCLING", 33static const struct fscache_state *fscache_detach_from_cookie(struct fscache_object *, int);
33 [FSCACHE_OBJECT_WITHDRAWING] = "OBJECT_WITHDRAWING", 34
34 [FSCACHE_OBJECT_DEAD] = "OBJECT_DEAD", 35#define __STATE_NAME(n) fscache_osm_##n
36#define STATE(n) (&__STATE_NAME(n))
37
38/*
39 * Define a work state. Work states are execution states. No event processing
40 * is performed by them. The function attached to a work state returns a
41 * pointer indicating the next state to which the state machine should
42 * transition. Returning NO_TRANSIT repeats the current state, but goes back
43 * to the scheduler first.
44 */
45#define WORK_STATE(n, sn, f) \
46 const struct fscache_state __STATE_NAME(n) = { \
47 .name = #n, \
48 .short_name = sn, \
49 .work = f \
50 }
51
52/*
53 * Returns from work states.
54 */
55#define transit_to(state) ({ prefetch(&STATE(state)->work); STATE(state); })
56
57#define NO_TRANSIT ((struct fscache_state *)NULL)
58
59/*
60 * Define a wait state. Wait states are event processing states. No execution
61 * is performed by them. Wait states are just tables of "if event X occurs,
62 * clear it and transition to state Y". The dispatcher returns to the
63 * scheduler if none of the events in which the wait state has an interest are
64 * currently pending.
65 */
66#define WAIT_STATE(n, sn, ...) \
67 const struct fscache_state __STATE_NAME(n) = { \
68 .name = #n, \
69 .short_name = sn, \
70 .work = NULL, \
71 .transitions = { __VA_ARGS__, { 0, NULL } } \
72 }
73
74#define TRANSIT_TO(state, emask) \
75 { .events = (emask), .transit_to = STATE(state) }
76
77/*
78 * The object state machine.
79 */
80static WORK_STATE(INIT_OBJECT, "INIT", fscache_initialise_object);
81static WORK_STATE(PARENT_READY, "PRDY", fscache_parent_ready);
82static WORK_STATE(ABORT_INIT, "ABRT", fscache_abort_initialisation);
83static WORK_STATE(LOOK_UP_OBJECT, "LOOK", fscache_look_up_object);
84static WORK_STATE(CREATE_OBJECT, "CRTO", fscache_look_up_object);
85static WORK_STATE(OBJECT_AVAILABLE, "AVBL", fscache_object_available);
86static WORK_STATE(JUMPSTART_DEPS, "JUMP", fscache_jumpstart_dependents);
87
88static WORK_STATE(INVALIDATE_OBJECT, "INVL", fscache_invalidate_object);
89static WORK_STATE(UPDATE_OBJECT, "UPDT", fscache_update_object);
90
91static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
92static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
93static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
94static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
95static WORK_STATE(DETACH_FROM_COOKIE, "DTCH", fscache_detach_from_cookie);
96static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL);
97
98static WAIT_STATE(WAIT_FOR_INIT, "?INI",
99 TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
100
101static WAIT_STATE(WAIT_FOR_PARENT, "?PRN",
102 TRANSIT_TO(PARENT_READY, 1 << FSCACHE_OBJECT_EV_PARENT_READY));
103
104static WAIT_STATE(WAIT_FOR_CMD, "?CMD",
105 TRANSIT_TO(INVALIDATE_OBJECT, 1 << FSCACHE_OBJECT_EV_INVALIDATE),
106 TRANSIT_TO(UPDATE_OBJECT, 1 << FSCACHE_OBJECT_EV_UPDATE),
107 TRANSIT_TO(JUMPSTART_DEPS, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
108
109static WAIT_STATE(WAIT_FOR_CLEARANCE, "?CLR",
110 TRANSIT_TO(KILL_OBJECT, 1 << FSCACHE_OBJECT_EV_CLEARED));
111
112/*
113 * Out-of-band event transition tables. These are for handling unexpected
114 * events, such as an I/O error. If an OOB event occurs, the state machine
115 * clears and disables the event and forces a transition to the nominated work
116 * state (acurrently executing work states will complete first).
117 *
118 * In such a situation, object->state remembers the state the machine should
119 * have been in/gone to and returning NO_TRANSIT returns to that.
120 */
121static const struct fscache_transition fscache_osm_init_oob[] = {
122 TRANSIT_TO(ABORT_INIT,
123 (1 << FSCACHE_OBJECT_EV_ERROR) |
124 (1 << FSCACHE_OBJECT_EV_KILL)),
125 { 0, NULL }
35}; 126};
36EXPORT_SYMBOL(fscache_object_states); 127
37 128static const struct fscache_transition fscache_osm_lookup_oob[] = {
38const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = { 129 TRANSIT_TO(LOOKUP_FAILURE,
39 [FSCACHE_OBJECT_INIT] = "INIT", 130 (1 << FSCACHE_OBJECT_EV_ERROR) |
40 [FSCACHE_OBJECT_LOOKING_UP] = "LOOK", 131 (1 << FSCACHE_OBJECT_EV_KILL)),
41 [FSCACHE_OBJECT_CREATING] = "CRTN", 132 { 0, NULL }
42 [FSCACHE_OBJECT_AVAILABLE] = "AVBL", 133};
43 [FSCACHE_OBJECT_ACTIVE] = "ACTV", 134
44 [FSCACHE_OBJECT_INVALIDATING] = "INVL", 135static const struct fscache_transition fscache_osm_run_oob[] = {
45 [FSCACHE_OBJECT_UPDATING] = "UPDT", 136 TRANSIT_TO(KILL_OBJECT,
46 [FSCACHE_OBJECT_DYING] = "DYNG", 137 (1 << FSCACHE_OBJECT_EV_ERROR) |
47 [FSCACHE_OBJECT_LC_DYING] = "LCDY", 138 (1 << FSCACHE_OBJECT_EV_KILL)),
48 [FSCACHE_OBJECT_ABORT_INIT] = "ABTI", 139 { 0, NULL }
49 [FSCACHE_OBJECT_RELEASING] = "RELS",
50 [FSCACHE_OBJECT_RECYCLING] = "RCYC",
51 [FSCACHE_OBJECT_WITHDRAWING] = "WTHD",
52 [FSCACHE_OBJECT_DEAD] = "DEAD",
53}; 140};
54 141
55static int fscache_get_object(struct fscache_object *); 142static int fscache_get_object(struct fscache_object *);
56static void fscache_put_object(struct fscache_object *); 143static void fscache_put_object(struct fscache_object *);
57static void fscache_initialise_object(struct fscache_object *); 144static bool fscache_enqueue_dependents(struct fscache_object *, int);
58static void fscache_lookup_object(struct fscache_object *);
59static void fscache_object_available(struct fscache_object *);
60static void fscache_invalidate_object(struct fscache_object *);
61static void fscache_release_object(struct fscache_object *);
62static void fscache_withdraw_object(struct fscache_object *);
63static void fscache_enqueue_dependents(struct fscache_object *);
64static void fscache_dequeue_object(struct fscache_object *); 145static void fscache_dequeue_object(struct fscache_object *);
65 146
66/* 147/*
@@ -83,281 +164,102 @@ static inline void fscache_done_parent_op(struct fscache_object *object)
83} 164}
84 165
85/* 166/*
86 * Notify netfs of invalidation completion. 167 * Object state machine dispatcher.
87 */ 168 */
88static inline void fscache_invalidation_complete(struct fscache_cookie *cookie) 169static void fscache_object_sm_dispatcher(struct fscache_object *object)
89{ 170{
90 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) 171 const struct fscache_transition *t;
91 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING); 172 const struct fscache_state *state, *new_state;
92} 173 unsigned long events, event_mask;
93 174 int event = -1;
94/*
95 * process events that have been sent to an object's state machine
96 * - initiates parent lookup
97 * - does object lookup
98 * - does object creation
99 * - does object recycling and retirement
100 * - does object withdrawal
101 */
102static void fscache_object_state_machine(struct fscache_object *object)
103{
104 enum fscache_object_state new_state;
105 struct fscache_cookie *cookie;
106 int event;
107 175
108 ASSERT(object != NULL); 176 ASSERT(object != NULL);
109 177
110 _enter("{OBJ%x,%s,%lx}", 178 _enter("{OBJ%x,%s,%lx}",
111 object->debug_id, fscache_object_states[object->state], 179 object->debug_id, object->state->name, object->events);
112 object->events); 180
113 181 event_mask = object->event_mask;
114 switch (object->state) { 182restart:
115 /* wait for the parent object to become ready */ 183 object->event_mask = 0; /* Mask normal event handling */
116 case FSCACHE_OBJECT_INIT: 184 state = object->state;
117 object->event_mask = 185restart_masked:
118 FSCACHE_OBJECT_EVENTS_MASK & 186 events = object->events;
119 ~(1 << FSCACHE_OBJECT_EV_CLEARED); 187
120 fscache_initialise_object(object); 188 /* Handle any out-of-band events (typically an error) */
121 goto done; 189 if (events & object->oob_event_mask) {
122 190 _debug("{OBJ%x} oob %lx",
123 /* look up the object metadata on disk */ 191 object->debug_id, events & object->oob_event_mask);
124 case FSCACHE_OBJECT_LOOKING_UP: 192 for (t = object->oob_table; t->events; t++) {
125 fscache_lookup_object(object); 193 if (events & t->events) {
126 goto lookup_transit; 194 state = t->transit_to;
127 195 ASSERT(state->work != NULL);
128 /* create the object metadata on disk */ 196 event = fls(events & t->events) - 1;
129 case FSCACHE_OBJECT_CREATING: 197 __clear_bit(event, &object->oob_event_mask);
130 fscache_lookup_object(object); 198 clear_bit(event, &object->events);
131 goto lookup_transit; 199 goto execute_work_state;
132 200 }
133 /* handle an object becoming available; start pending
134 * operations and queue dependent operations for processing */
135 case FSCACHE_OBJECT_AVAILABLE:
136 fscache_object_available(object);
137 goto active_transit;
138
139 /* normal running state */
140 case FSCACHE_OBJECT_ACTIVE:
141 goto active_transit;
142
143 /* Invalidate an object on disk */
144 case FSCACHE_OBJECT_INVALIDATING:
145 clear_bit(FSCACHE_OBJECT_EV_INVALIDATE, &object->events);
146 fscache_stat(&fscache_n_invalidates_run);
147 fscache_stat(&fscache_n_cop_invalidate_object);
148 fscache_invalidate_object(object);
149 fscache_stat_d(&fscache_n_cop_invalidate_object);
150 fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
151 goto active_transit;
152
153 /* update the object metadata on disk */
154 case FSCACHE_OBJECT_UPDATING:
155 clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events);
156 fscache_stat(&fscache_n_updates_run);
157 fscache_stat(&fscache_n_cop_update_object);
158 object->cache->ops->update_object(object);
159 fscache_stat_d(&fscache_n_cop_update_object);
160 goto active_transit;
161
162 /* handle an object dying during lookup or creation */
163 case FSCACHE_OBJECT_LC_DYING:
164 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE);
165 fscache_stat(&fscache_n_cop_lookup_complete);
166 object->cache->ops->lookup_complete(object);
167 fscache_stat_d(&fscache_n_cop_lookup_complete);
168
169 spin_lock(&object->lock);
170 object->state = FSCACHE_OBJECT_DYING;
171 cookie = object->cookie;
172 if (cookie) {
173 if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP,
174 &cookie->flags))
175 wake_up_bit(&cookie->flags,
176 FSCACHE_COOKIE_LOOKING_UP);
177 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING,
178 &cookie->flags))
179 wake_up_bit(&cookie->flags,
180 FSCACHE_COOKIE_CREATING);
181 } 201 }
182 spin_unlock(&object->lock); 202 }
183 203
184 fscache_done_parent_op(object); 204 /* Wait states are just transition tables */
205 if (!state->work) {
206 if (events & event_mask) {
207 for (t = state->transitions; t->events; t++) {
208 if (events & t->events) {
209 new_state = t->transit_to;
210 event = fls(events & t->events) - 1;
211 clear_bit(event, &object->events);
212 _debug("{OBJ%x} ev %d: %s -> %s",
213 object->debug_id, event,
214 state->name, new_state->name);
215 object->state = state = new_state;
216 goto execute_work_state;
217 }
218 }
185 219
186 /* wait for completion of all active operations on this object 220 /* The event mask didn't include all the tabled bits */
187 * and the death of all child objects of this object */ 221 BUG();
188 case FSCACHE_OBJECT_DYING:
189 dying:
190 clear_bit(FSCACHE_OBJECT_EV_CLEARED, &object->events);
191 spin_lock(&object->lock);
192 _debug("dying OBJ%x {%d,%d}",
193 object->debug_id, object->n_ops, object->n_children);
194 if (object->n_ops == 0 && object->n_children == 0) {
195 object->event_mask &=
196 ~(1 << FSCACHE_OBJECT_EV_CLEARED);
197 object->event_mask |=
198 (1 << FSCACHE_OBJECT_EV_WITHDRAW) |
199 (1 << FSCACHE_OBJECT_EV_RETIRE) |
200 (1 << FSCACHE_OBJECT_EV_RELEASE) |
201 (1 << FSCACHE_OBJECT_EV_ERROR);
202 } else {
203 object->event_mask &=
204 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
205 (1 << FSCACHE_OBJECT_EV_RETIRE) |
206 (1 << FSCACHE_OBJECT_EV_RELEASE) |
207 (1 << FSCACHE_OBJECT_EV_ERROR));
208 object->event_mask |=
209 1 << FSCACHE_OBJECT_EV_CLEARED;
210 } 222 }
211 spin_unlock(&object->lock); 223 /* Randomly woke up */
212 fscache_enqueue_dependents(object); 224 goto unmask_events;
213 fscache_start_operations(object);
214 goto terminal_transit;
215
216 /* handle an abort during initialisation */
217 case FSCACHE_OBJECT_ABORT_INIT:
218 _debug("handle abort init %lx", object->events);
219 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE);
220
221 spin_lock(&object->lock);
222 fscache_dequeue_object(object);
223
224 object->state = FSCACHE_OBJECT_DYING;
225 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING,
226 &object->cookie->flags))
227 wake_up_bit(&object->cookie->flags,
228 FSCACHE_COOKIE_CREATING);
229 spin_unlock(&object->lock);
230 goto dying;
231
232 /* handle the netfs releasing an object and possibly marking it
233 * obsolete too */
234 case FSCACHE_OBJECT_RELEASING:
235 case FSCACHE_OBJECT_RECYCLING:
236 object->event_mask &=
237 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
238 (1 << FSCACHE_OBJECT_EV_RETIRE) |
239 (1 << FSCACHE_OBJECT_EV_RELEASE) |
240 (1 << FSCACHE_OBJECT_EV_ERROR));
241 fscache_release_object(object);
242 spin_lock(&object->lock);
243 object->state = FSCACHE_OBJECT_DEAD;
244 spin_unlock(&object->lock);
245 fscache_stat(&fscache_n_object_dead);
246 goto terminal_transit;
247
248 /* handle the parent cache of this object being withdrawn from
249 * active service */
250 case FSCACHE_OBJECT_WITHDRAWING:
251 object->event_mask &=
252 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) |
253 (1 << FSCACHE_OBJECT_EV_RETIRE) |
254 (1 << FSCACHE_OBJECT_EV_RELEASE) |
255 (1 << FSCACHE_OBJECT_EV_ERROR));
256 fscache_withdraw_object(object);
257 spin_lock(&object->lock);
258 object->state = FSCACHE_OBJECT_DEAD;
259 spin_unlock(&object->lock);
260 fscache_stat(&fscache_n_object_dead);
261 goto terminal_transit;
262
263 /* complain about the object being woken up once it is
264 * deceased */
265 case FSCACHE_OBJECT_DEAD:
266 printk(KERN_ERR "FS-Cache:"
267 " Unexpected event in dead state %lx\n",
268 object->events & object->event_mask);
269 BUG();
270
271 default:
272 printk(KERN_ERR "FS-Cache: Unknown object state %u\n",
273 object->state);
274 BUG();
275 } 225 }
276 226
277 /* determine the transition from a lookup state */ 227execute_work_state:
278lookup_transit: 228 _debug("{OBJ%x} exec %s", object->debug_id, state->name);
279 event = fls(object->events & object->event_mask) - 1;
280 switch (event) {
281 case FSCACHE_OBJECT_EV_WITHDRAW:
282 case FSCACHE_OBJECT_EV_RETIRE:
283 case FSCACHE_OBJECT_EV_RELEASE:
284 case FSCACHE_OBJECT_EV_ERROR:
285 new_state = FSCACHE_OBJECT_LC_DYING;
286 goto change_state;
287 case FSCACHE_OBJECT_EV_INVALIDATE:
288 new_state = FSCACHE_OBJECT_INVALIDATING;
289 goto change_state;
290 case FSCACHE_OBJECT_EV_REQUEUE:
291 goto done;
292 case -1:
293 goto done; /* sleep until event */
294 default:
295 goto unsupported_event;
296 }
297
298 /* determine the transition from an active state */
299active_transit:
300 event = fls(object->events & object->event_mask) - 1;
301 switch (event) {
302 case FSCACHE_OBJECT_EV_WITHDRAW:
303 case FSCACHE_OBJECT_EV_RETIRE:
304 case FSCACHE_OBJECT_EV_RELEASE:
305 case FSCACHE_OBJECT_EV_ERROR:
306 new_state = FSCACHE_OBJECT_DYING;
307 goto change_state;
308 case FSCACHE_OBJECT_EV_INVALIDATE:
309 new_state = FSCACHE_OBJECT_INVALIDATING;
310 goto change_state;
311 case FSCACHE_OBJECT_EV_UPDATE:
312 new_state = FSCACHE_OBJECT_UPDATING;
313 goto change_state;
314 case -1:
315 new_state = FSCACHE_OBJECT_ACTIVE;
316 goto change_state; /* sleep until event */
317 default:
318 goto unsupported_event;
319 }
320 229
321 /* determine the transition from a terminal state */ 230 new_state = state->work(object, event);
322terminal_transit: 231 event = -1;
323 event = fls(object->events & object->event_mask) - 1; 232 if (new_state == NO_TRANSIT) {
324 switch (event) { 233 _debug("{OBJ%x} %s notrans", object->debug_id, state->name);
325 case FSCACHE_OBJECT_EV_WITHDRAW: 234 fscache_enqueue_object(object);
326 new_state = FSCACHE_OBJECT_WITHDRAWING; 235 event_mask = object->oob_event_mask;
327 goto change_state; 236 goto unmask_events;
328 case FSCACHE_OBJECT_EV_RETIRE:
329 new_state = FSCACHE_OBJECT_RECYCLING;
330 goto change_state;
331 case FSCACHE_OBJECT_EV_RELEASE:
332 new_state = FSCACHE_OBJECT_RELEASING;
333 goto change_state;
334 case FSCACHE_OBJECT_EV_ERROR:
335 new_state = FSCACHE_OBJECT_WITHDRAWING;
336 goto change_state;
337 case FSCACHE_OBJECT_EV_CLEARED:
338 new_state = FSCACHE_OBJECT_DYING;
339 goto change_state;
340 case -1:
341 goto done; /* sleep until event */
342 default:
343 goto unsupported_event;
344 } 237 }
345 238
346change_state: 239 _debug("{OBJ%x} %s -> %s",
347 spin_lock(&object->lock); 240 object->debug_id, state->name, new_state->name);
348 object->state = new_state; 241 object->state = state = new_state;
349 spin_unlock(&object->lock);
350 242
351done: 243 if (state->work) {
352 _leave(" [->%s]", fscache_object_states[object->state]); 244 if (unlikely(state->work == ((void *)2UL))) {
353 return; 245 _leave(" [dead]");
246 return;
247 }
248 goto restart_masked;
249 }
354 250
355unsupported_event: 251 /* Transited to wait state */
356 printk(KERN_ERR "FS-Cache:" 252 event_mask = object->oob_event_mask;
357 " Unsupported event %d [%lx/%lx] in state %s\n", 253 for (t = state->transitions; t->events; t++)
358 event, object->events, object->event_mask, 254 event_mask |= t->events;
359 fscache_object_states[object->state]); 255
360 BUG(); 256unmask_events:
257 object->event_mask = event_mask;
258 smp_mb();
259 events = object->events;
260 if (events & event_mask)
261 goto restart;
262 _leave(" [msk %lx]", event_mask);
361} 263}
362 264
363/* 265/*
@@ -372,11 +274,8 @@ static void fscache_object_work_func(struct work_struct *work)
372 _enter("{OBJ%x}", object->debug_id); 274 _enter("{OBJ%x}", object->debug_id);
373 275
374 start = jiffies; 276 start = jiffies;
375 fscache_object_state_machine(object); 277 fscache_object_sm_dispatcher(object);
376 fscache_hist(fscache_objs_histogram, start); 278 fscache_hist(fscache_objs_histogram, start);
377 if (object->events & object->event_mask)
378 fscache_enqueue_object(object);
379 clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
380 fscache_put_object(object); 279 fscache_put_object(object);
381} 280}
382 281
@@ -395,9 +294,13 @@ void fscache_object_init(struct fscache_object *object,
395 struct fscache_cookie *cookie, 294 struct fscache_cookie *cookie,
396 struct fscache_cache *cache) 295 struct fscache_cache *cache)
397{ 296{
297 const struct fscache_transition *t;
298
398 atomic_inc(&cache->object_count); 299 atomic_inc(&cache->object_count);
399 300
400 object->state = FSCACHE_OBJECT_INIT; 301 object->state = STATE(WAIT_FOR_INIT);
302 object->oob_table = fscache_osm_init_oob;
303 object->flags = 1 << FSCACHE_OBJECT_IS_LIVE;
401 spin_lock_init(&object->lock); 304 spin_lock_init(&object->lock);
402 INIT_LIST_HEAD(&object->cache_link); 305 INIT_LIST_HEAD(&object->cache_link);
403 INIT_HLIST_NODE(&object->cookie_link); 306 INIT_HLIST_NODE(&object->cookie_link);
@@ -407,17 +310,48 @@ void fscache_object_init(struct fscache_object *object,
407 INIT_LIST_HEAD(&object->pending_ops); 310 INIT_LIST_HEAD(&object->pending_ops);
408 object->n_children = 0; 311 object->n_children = 0;
409 object->n_ops = object->n_in_progress = object->n_exclusive = 0; 312 object->n_ops = object->n_in_progress = object->n_exclusive = 0;
410 object->events = object->event_mask = 0; 313 object->events = 0;
411 object->flags = 0;
412 object->store_limit = 0; 314 object->store_limit = 0;
413 object->store_limit_l = 0; 315 object->store_limit_l = 0;
414 object->cache = cache; 316 object->cache = cache;
415 object->cookie = cookie; 317 object->cookie = cookie;
416 object->parent = NULL; 318 object->parent = NULL;
319
320 object->oob_event_mask = 0;
321 for (t = object->oob_table; t->events; t++)
322 object->oob_event_mask |= t->events;
323 object->event_mask = object->oob_event_mask;
324 for (t = object->state->transitions; t->events; t++)
325 object->event_mask |= t->events;
417} 326}
418EXPORT_SYMBOL(fscache_object_init); 327EXPORT_SYMBOL(fscache_object_init);
419 328
420/* 329/*
330 * Abort object initialisation before we start it.
331 */
332static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *object,
333 int event)
334{
335 struct fscache_cookie *cookie;
336
337 _enter("{OBJ%x},%d", object->debug_id, event);
338
339 object->oob_event_mask = 0;
340 clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
341
342 fscache_dequeue_object(object);
343
344 spin_lock(&object->lock);
345 cookie = object->cookie;
346 clear_bit_unlock(FSCACHE_COOKIE_CREATING, &cookie->flags);
347 spin_unlock(&object->lock);
348
349 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING);
350
351 return transit_to(KILL_OBJECT);
352}
353
354/*
421 * initialise an object 355 * initialise an object
422 * - check the specified object's parent to see if we can make use of it 356 * - check the specified object's parent to see if we can make use of it
423 * immediately to do a creation 357 * immediately to do a creation
@@ -426,74 +360,78 @@ EXPORT_SYMBOL(fscache_object_init);
426 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the 360 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the
427 * leaf-most cookies of the object and all its children 361 * leaf-most cookies of the object and all its children
428 */ 362 */
429static void fscache_initialise_object(struct fscache_object *object) 363static const struct fscache_state *fscache_initialise_object(struct fscache_object *object,
364 int event)
430{ 365{
431 struct fscache_object *parent; 366 struct fscache_object *parent;
367 bool success;
432 368
433 _enter(""); 369 _enter("{OBJ%x},%d", object->debug_id, event);
434 ASSERT(object->cookie != NULL);
435 ASSERT(object->cookie->parent != NULL);
436 370
437 if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | 371 ASSERT(list_empty(&object->dep_link));
438 (1 << FSCACHE_OBJECT_EV_RELEASE) |
439 (1 << FSCACHE_OBJECT_EV_RETIRE) |
440 (1 << FSCACHE_OBJECT_EV_WITHDRAW))) {
441 _debug("abort init %lx", object->events);
442 spin_lock(&object->lock);
443 object->state = FSCACHE_OBJECT_ABORT_INIT;
444 spin_unlock(&object->lock);
445 return;
446 }
447
448 spin_lock(&object->cookie->lock);
449 spin_lock_nested(&object->cookie->parent->lock, 1);
450 372
451 parent = object->parent; 373 parent = object->parent;
452 if (!parent) { 374 if (!parent) {
453 _debug("no parent"); 375 _leave(" [no parent]");
454 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events); 376 return transit_to(DETACH_FROM_COOKIE);
455 } else { 377 }
456 spin_lock(&object->lock);
457 spin_lock_nested(&parent->lock, 1);
458 _debug("parent %s", fscache_object_states[parent->state]);
459
460 if (fscache_object_is_dying(parent)) {
461 _debug("bad parent");
462 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events);
463 } else if (!fscache_object_is_available(parent)) {
464 _debug("wait");
465
466 /* we may get woken up in this state by child objects
467 * binding on to us, so we need to make sure we don't
468 * add ourself to the list multiple times */
469 if (list_empty(&object->dep_link)) {
470 fscache_stat(&fscache_n_cop_grab_object);
471 object->cache->ops->grab_object(object);
472 fscache_stat_d(&fscache_n_cop_grab_object);
473 list_add(&object->dep_link,
474 &parent->dependents);
475
476 /* fscache_acquire_non_index_cookie() uses this
477 * to wake the chain up */
478 if (parent->state == FSCACHE_OBJECT_INIT)
479 fscache_enqueue_object(parent);
480 }
481 } else {
482 _debug("go");
483 parent->n_ops++;
484 parent->n_obj_ops++;
485 object->lookup_jif = jiffies;
486 object->state = FSCACHE_OBJECT_LOOKING_UP;
487 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
488 }
489 378
490 spin_unlock(&parent->lock); 379 _debug("parent %s", parent->state->name);
491 spin_unlock(&object->lock); 380
381 if (fscache_object_is_dying(parent)) {
382 _leave(" [bad parent]");
383 return transit_to(DETACH_FROM_COOKIE);
384 }
385
386 if (fscache_object_is_available(parent)) {
387 _leave(" [ready]");
388 return transit_to(PARENT_READY);
389 }
390
391 _debug("wait");
392
393 spin_lock(&parent->lock);
394 fscache_stat(&fscache_n_cop_grab_object);
395 success = false;
396 if (fscache_object_is_live(parent) &&
397 object->cache->ops->grab_object(object)) {
398 list_add(&object->dep_link, &parent->dependents);
399 success = true;
400 }
401 fscache_stat_d(&fscache_n_cop_grab_object);
402 spin_unlock(&parent->lock);
403 if (!success) {
404 _leave(" [grab failed]");
405 return transit_to(DETACH_FROM_COOKIE);
492 } 406 }
493 407
494 spin_unlock(&object->cookie->parent->lock); 408 /* fscache_acquire_non_index_cookie() uses this
495 spin_unlock(&object->cookie->lock); 409 * to wake the chain up */
410 fscache_raise_event(parent, FSCACHE_OBJECT_EV_NEW_CHILD);
411 _leave(" [wait]");
412 return transit_to(WAIT_FOR_PARENT);
413}
414
415/*
416 * Once the parent object is ready, we should kick off our lookup op.
417 */
418static const struct fscache_state *fscache_parent_ready(struct fscache_object *object,
419 int event)
420{
421 struct fscache_object *parent = object->parent;
422
423 _enter("{OBJ%x},%d", object->debug_id, event);
424
425 ASSERT(parent != NULL);
426
427 spin_lock(&parent->lock);
428 parent->n_ops++;
429 parent->n_obj_ops++;
430 object->lookup_jif = jiffies;
431 spin_unlock(&parent->lock);
432
496 _leave(""); 433 _leave("");
434 return transit_to(LOOK_UP_OBJECT);
497} 435}
498 436
499/* 437/*
@@ -503,15 +441,17 @@ static void fscache_initialise_object(struct fscache_object *object)
503 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the 441 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the
504 * leaf-most cookies of the object and all its children 442 * leaf-most cookies of the object and all its children
505 */ 443 */
506static void fscache_lookup_object(struct fscache_object *object) 444static const struct fscache_state *fscache_look_up_object(struct fscache_object *object,
445 int event)
507{ 446{
508 struct fscache_cookie *cookie = object->cookie; 447 struct fscache_cookie *cookie = object->cookie;
509 struct fscache_object *parent; 448 struct fscache_object *parent = object->parent;
510 int ret; 449 int ret;
511 450
512 _enter(""); 451 _enter("{OBJ%x},%d", object->debug_id, event);
452
453 object->oob_table = fscache_osm_lookup_oob;
513 454
514 parent = object->parent;
515 ASSERT(parent != NULL); 455 ASSERT(parent != NULL);
516 ASSERTCMP(parent->n_ops, >, 0); 456 ASSERTCMP(parent->n_ops, >, 0);
517 ASSERTCMP(parent->n_obj_ops, >, 0); 457 ASSERTCMP(parent->n_obj_ops, >, 0);
@@ -521,10 +461,8 @@ static void fscache_lookup_object(struct fscache_object *object)
521 461
522 if (fscache_object_is_dying(parent) || 462 if (fscache_object_is_dying(parent) ||
523 test_bit(FSCACHE_IOERROR, &object->cache->flags)) { 463 test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
524 _debug("unavailable"); 464 _leave(" [unavailable]");
525 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events); 465 return transit_to(LOOKUP_FAILURE);
526 _leave("");
527 return;
528 } 466 }
529 467
530 _debug("LOOKUP \"%s/%s\" in \"%s\"", 468 _debug("LOOKUP \"%s/%s\" in \"%s\"",
@@ -543,10 +481,17 @@ static void fscache_lookup_object(struct fscache_object *object)
543 /* probably stuck behind another object, so move this one to 481 /* probably stuck behind another object, so move this one to
544 * the back of the queue */ 482 * the back of the queue */
545 fscache_stat(&fscache_n_object_lookups_timed_out); 483 fscache_stat(&fscache_n_object_lookups_timed_out);
546 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 484 _leave(" [timeout]");
485 return NO_TRANSIT;
547 } 486 }
548 487
549 _leave(""); 488 if (ret < 0) {
489 _leave(" [error]");
490 return transit_to(LOOKUP_FAILURE);
491 }
492
493 _leave(" [ok]");
494 return transit_to(OBJECT_AVAILABLE);
550} 495}
551 496
552/** 497/**
@@ -560,32 +505,20 @@ void fscache_object_lookup_negative(struct fscache_object *object)
560{ 505{
561 struct fscache_cookie *cookie = object->cookie; 506 struct fscache_cookie *cookie = object->cookie;
562 507
563 _enter("{OBJ%x,%s}", 508 _enter("{OBJ%x,%s}", object->debug_id, object->state->name);
564 object->debug_id, fscache_object_states[object->state]);
565 509
566 spin_lock(&object->lock); 510 if (!test_and_set_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
567 if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
568 fscache_stat(&fscache_n_object_lookups_negative); 511 fscache_stat(&fscache_n_object_lookups_negative);
569 512
570 /* transit here to allow write requests to begin stacking up 513 /* Allow write requests to begin stacking up and read requests to begin
571 * and read requests to begin returning ENODATA */ 514 * returning ENODATA.
572 object->state = FSCACHE_OBJECT_CREATING; 515 */
573 spin_unlock(&object->lock);
574
575 set_bit(FSCACHE_COOKIE_PENDING_FILL, &cookie->flags);
576 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 516 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
577 517
578 _debug("wake up lookup %p", &cookie->flags); 518 _debug("wake up lookup %p", &cookie->flags);
579 smp_mb__before_clear_bit(); 519 clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
580 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
581 smp_mb__after_clear_bit();
582 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP); 520 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
583 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
584 } else {
585 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING);
586 spin_unlock(&object->lock);
587 } 521 }
588
589 _leave(""); 522 _leave("");
590} 523}
591EXPORT_SYMBOL(fscache_object_lookup_negative); 524EXPORT_SYMBOL(fscache_object_lookup_negative);
@@ -604,37 +537,30 @@ void fscache_obtained_object(struct fscache_object *object)
604{ 537{
605 struct fscache_cookie *cookie = object->cookie; 538 struct fscache_cookie *cookie = object->cookie;
606 539
607 _enter("{OBJ%x,%s}", 540 _enter("{OBJ%x,%s}", object->debug_id, object->state->name);
608 object->debug_id, fscache_object_states[object->state]);
609 541
610 /* if we were still looking up, then we must have a positive lookup 542 /* if we were still looking up, then we must have a positive lookup
611 * result, in which case there may be data available */ 543 * result, in which case there may be data available */
612 spin_lock(&object->lock); 544 if (!test_and_set_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
613 if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
614 fscache_stat(&fscache_n_object_lookups_positive); 545 fscache_stat(&fscache_n_object_lookups_positive);
615 546
616 clear_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 547 /* We do (presumably) have data */
617 548 clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
618 object->state = FSCACHE_OBJECT_AVAILABLE;
619 spin_unlock(&object->lock);
620 549
621 smp_mb__before_clear_bit(); 550 /* Allow write requests to begin stacking up and read requests
622 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags); 551 * to begin shovelling data.
623 smp_mb__after_clear_bit(); 552 */
553 clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
624 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP); 554 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
625 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
626 } else { 555 } else {
627 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING);
628 fscache_stat(&fscache_n_object_created); 556 fscache_stat(&fscache_n_object_created);
629
630 object->state = FSCACHE_OBJECT_AVAILABLE;
631 spin_unlock(&object->lock);
632 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
633 smp_wmb();
634 } 557 }
635 558
636 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, &cookie->flags)) 559 set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags);
637 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING); 560
561 /* Permit __fscache_relinquish_cookie() to proceed */
562 clear_bit_unlock(FSCACHE_COOKIE_CREATING, &cookie->flags);
563 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING);
638 564
639 _leave(""); 565 _leave("");
640} 566}
@@ -643,15 +569,18 @@ EXPORT_SYMBOL(fscache_obtained_object);
643/* 569/*
644 * handle an object that has just become available 570 * handle an object that has just become available
645 */ 571 */
646static void fscache_object_available(struct fscache_object *object) 572static const struct fscache_state *fscache_object_available(struct fscache_object *object,
573 int event)
647{ 574{
648 _enter("{OBJ%x}", object->debug_id); 575 struct fscache_cookie *cookie = object->cookie;
576
577 _enter("{OBJ%x},%d", object->debug_id, event);
578
579 object->oob_table = fscache_osm_run_oob;
649 580
650 spin_lock(&object->lock); 581 spin_lock(&object->lock);
651 582
652 if (object->cookie && 583 ASSERTIF(cookie, !test_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags));
653 test_and_clear_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags))
654 wake_up_bit(&object->cookie->flags, FSCACHE_COOKIE_CREATING);
655 584
656 fscache_done_parent_op(object); 585 fscache_done_parent_op(object);
657 if (object->n_in_progress == 0) { 586 if (object->n_in_progress == 0) {
@@ -667,72 +596,117 @@ static void fscache_object_available(struct fscache_object *object)
667 fscache_stat(&fscache_n_cop_lookup_complete); 596 fscache_stat(&fscache_n_cop_lookup_complete);
668 object->cache->ops->lookup_complete(object); 597 object->cache->ops->lookup_complete(object);
669 fscache_stat_d(&fscache_n_cop_lookup_complete); 598 fscache_stat_d(&fscache_n_cop_lookup_complete);
670 fscache_enqueue_dependents(object);
671 599
672 fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif); 600 fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif);
673 fscache_stat(&fscache_n_object_avail); 601 fscache_stat(&fscache_n_object_avail);
674 602
675 _leave(""); 603 _leave("");
604 return transit_to(JUMPSTART_DEPS);
676} 605}
677 606
678/* 607/*
679 * drop an object's attachments 608 * Wake up this object's dependent objects now that we've become available.
680 */ 609 */
681static void fscache_drop_object(struct fscache_object *object) 610static const struct fscache_state *fscache_jumpstart_dependents(struct fscache_object *object,
611 int event)
682{ 612{
683 struct fscache_object *parent = object->parent; 613 _enter("{OBJ%x},%d", object->debug_id, event);
684 struct fscache_cache *cache = object->cache;
685 614
686 _enter("{OBJ%x,%d}", object->debug_id, object->n_children); 615 if (!fscache_enqueue_dependents(object, FSCACHE_OBJECT_EV_PARENT_READY))
616 return NO_TRANSIT; /* Not finished; requeue */
617 return transit_to(WAIT_FOR_CMD);
618}
687 619
688 ASSERTCMP(object->cookie, ==, NULL); 620/*
689 ASSERT(hlist_unhashed(&object->cookie_link)); 621 * Handle lookup or creation failute.
622 */
623static const struct fscache_state *fscache_lookup_failure(struct fscache_object *object,
624 int event)
625{
626 struct fscache_cookie *cookie;
627 bool wake_looking_up = false;
690 628
691 spin_lock(&cache->object_list_lock); 629 _enter("{OBJ%x},%d", object->debug_id, event);
692 list_del_init(&object->cache_link);
693 spin_unlock(&cache->object_list_lock);
694 630
695 fscache_stat(&fscache_n_cop_drop_object); 631 object->oob_event_mask = 0;
696 cache->ops->drop_object(object);
697 fscache_stat_d(&fscache_n_cop_drop_object);
698 632
699 if (parent) { 633 fscache_stat(&fscache_n_cop_lookup_complete);
700 _debug("release parent OBJ%x {%d}", 634 object->cache->ops->lookup_complete(object);
701 parent->debug_id, parent->n_children); 635 fscache_stat_d(&fscache_n_cop_lookup_complete);
702 636
703 spin_lock(&parent->lock); 637 spin_lock(&object->lock);
704 parent->n_children--; 638 cookie = object->cookie;
705 if (parent->n_children == 0) 639 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
706 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED); 640 if (cookie) {
707 spin_unlock(&parent->lock); 641 if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
708 object->parent = NULL; 642 wake_looking_up = true;
643 clear_bit_unlock(FSCACHE_COOKIE_CREATING, &cookie->flags);
709 } 644 }
645 spin_unlock(&object->lock);
710 646
711 /* this just shifts the object release to the work processor */ 647 if (wake_looking_up)
712 fscache_put_object(object); 648 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
649 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING);
713 650
714 _leave(""); 651 fscache_done_parent_op(object);
652 return transit_to(KILL_OBJECT);
653}
654
655/*
656 * Wait for completion of all active operations on this object and the death of
657 * all child objects of this object.
658 */
659static const struct fscache_state *fscache_kill_object(struct fscache_object *object,
660 int event)
661{
662 _enter("{OBJ%x,%d,%d},%d",
663 object->debug_id, object->n_ops, object->n_children, event);
664
665 object->oob_event_mask = 0;
666
667 spin_lock(&object->lock);
668 clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
669 spin_unlock(&object->lock);
670
671 if (list_empty(&object->dependents) &&
672 object->n_ops == 0 &&
673 object->n_children == 0)
674 return object->cookie ?
675 transit_to(DETACH_FROM_COOKIE) : transit_to(DROP_OBJECT);
676
677 spin_lock(&object->lock);
678 fscache_start_operations(object);
679 spin_unlock(&object->lock);
680
681 if (!list_empty(&object->dependents))
682 return transit_to(KILL_DEPENDENTS);
683
684 return transit_to(WAIT_FOR_CLEARANCE);
715} 685}
716 686
717/* 687/*
718 * release or recycle an object that the netfs has discarded 688 * Kill dependent objects.
719 */ 689 */
720static void fscache_release_object(struct fscache_object *object) 690static const struct fscache_state *fscache_kill_dependents(struct fscache_object *object,
691 int event)
721{ 692{
722 _enter(""); 693 _enter("{OBJ%x},%d", object->debug_id, event);
723 694
724 fscache_drop_object(object); 695 if (!fscache_enqueue_dependents(object, FSCACHE_OBJECT_EV_KILL))
696 return NO_TRANSIT; /* Not finished */
697 return transit_to(WAIT_FOR_CLEARANCE);
725} 698}
726 699
727/* 700/*
728 * withdraw an object from active service 701 * withdraw an object from active service
729 */ 702 */
730static void fscache_withdraw_object(struct fscache_object *object) 703static const struct fscache_state *fscache_detach_from_cookie(struct fscache_object *object,
704 int event)
731{ 705{
732 struct fscache_cookie *cookie; 706 struct fscache_cookie *cookie;
733 bool detached; 707 bool detached = false, awaken = false;
734 708
735 _enter(""); 709 _enter("{OBJ%x},%d", object->debug_id, event);
736 710
737 spin_lock(&object->lock); 711 spin_lock(&object->lock);
738 cookie = object->cookie; 712 cookie = object->cookie;
@@ -742,14 +716,15 @@ static void fscache_withdraw_object(struct fscache_object *object)
742 atomic_inc(&cookie->usage); 716 atomic_inc(&cookie->usage);
743 spin_unlock(&object->lock); 717 spin_unlock(&object->lock);
744 718
745 detached = false;
746 spin_lock(&cookie->lock); 719 spin_lock(&cookie->lock);
747 spin_lock(&object->lock); 720 spin_lock(&object->lock);
748 721
749 if (object->cookie == cookie) { 722 if (object->cookie == cookie) {
750 hlist_del_init(&object->cookie_link); 723 hlist_del_init(&object->cookie_link);
751 object->cookie = NULL; 724 object->cookie = NULL;
752 fscache_invalidation_complete(cookie); 725 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING,
726 &cookie->flags))
727 awaken = true;
753 detached = true; 728 detached = true;
754 } 729 }
755 spin_unlock(&cookie->lock); 730 spin_unlock(&cookie->lock);
@@ -760,37 +735,62 @@ static void fscache_withdraw_object(struct fscache_object *object)
760 735
761 spin_unlock(&object->lock); 736 spin_unlock(&object->lock);
762 737
763 fscache_drop_object(object); 738 if (awaken)
739 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
740
741 fscache_stat(&fscache_n_object_dead);
742 _leave("");
743 return transit_to(DROP_OBJECT);
764} 744}
765 745
766/* 746/*
767 * withdraw an object from active service at the behest of the cache 747 * Drop an object's attachments
768 * - need break the links to a cached object cookie 748 */
769 * - called under two situations: 749static const struct fscache_state *fscache_drop_object(struct fscache_object *object,
770 * (1) recycler decides to reclaim an in-use object 750 int event)
771 * (2) a cache is unmounted
772 * - have to take care as the cookie can be being relinquished by the netfs
773 * simultaneously
774 * - the object is pinned by the caller holding a refcount on it
775 */
776void fscache_withdrawing_object(struct fscache_cache *cache,
777 struct fscache_object *object)
778{ 751{
779 bool enqueue = false; 752 struct fscache_object *parent = object->parent;
753 struct fscache_cache *cache = object->cache;
780 754
781 _enter(",OBJ%x", object->debug_id); 755 _enter("{OBJ%x,%d},%d", object->debug_id, object->n_children, event);
782 756
757 ASSERTCMP(object->cookie, ==, NULL);
758 ASSERT(hlist_unhashed(&object->cookie_link));
759
760 /* Prevent a race with our last child, which has to signal EV_CLEARED
761 * before dropping our spinlock.
762 */
783 spin_lock(&object->lock); 763 spin_lock(&object->lock);
784 if (object->state < FSCACHE_OBJECT_WITHDRAWING) {
785 object->state = FSCACHE_OBJECT_WITHDRAWING;
786 enqueue = true;
787 }
788 spin_unlock(&object->lock); 764 spin_unlock(&object->lock);
789 765
790 if (enqueue) 766 /* Discard from the cache's collection of objects */
791 fscache_enqueue_object(object); 767 spin_lock(&cache->object_list_lock);
768 list_del_init(&object->cache_link);
769 spin_unlock(&cache->object_list_lock);
770
771 fscache_stat(&fscache_n_cop_drop_object);
772 cache->ops->drop_object(object);
773 fscache_stat_d(&fscache_n_cop_drop_object);
774
775 /* The parent object wants to know when all it dependents have gone */
776 if (parent) {
777 _debug("release parent OBJ%x {%d}",
778 parent->debug_id, parent->n_children);
779
780 spin_lock(&parent->lock);
781 parent->n_children--;
782 if (parent->n_children == 0)
783 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED);
784 spin_unlock(&parent->lock);
785 object->parent = NULL;
786 }
787
788 /* this just shifts the object release to the work processor */
789 fscache_put_object(object);
790 fscache_stat(&fscache_n_object_dead);
792 791
793 _leave(""); 792 _leave("");
793 return transit_to(OBJECT_DEAD);
794} 794}
795 795
796/* 796/*
@@ -807,7 +807,7 @@ static int fscache_get_object(struct fscache_object *object)
807} 807}
808 808
809/* 809/*
810 * discard a ref on a work item 810 * Discard a ref on an object
811 */ 811 */
812static void fscache_put_object(struct fscache_object *object) 812static void fscache_put_object(struct fscache_object *object)
813{ 813{
@@ -839,7 +839,7 @@ void fscache_enqueue_object(struct fscache_object *object)
839 839
840/** 840/**
841 * fscache_object_sleep_till_congested - Sleep until object wq is congested 841 * fscache_object_sleep_till_congested - Sleep until object wq is congested
842 * @timoutp: Scheduler sleep timeout 842 * @timeoutp: Scheduler sleep timeout
843 * 843 *
844 * Allow an object handler to sleep until the object workqueue is congested. 844 * Allow an object handler to sleep until the object workqueue is congested.
845 * 845 *
@@ -867,18 +867,21 @@ bool fscache_object_sleep_till_congested(signed long *timeoutp)
867EXPORT_SYMBOL_GPL(fscache_object_sleep_till_congested); 867EXPORT_SYMBOL_GPL(fscache_object_sleep_till_congested);
868 868
869/* 869/*
870 * enqueue the dependents of an object for metadata-type processing 870 * Enqueue the dependents of an object for metadata-type processing.
871 * - the caller must hold the object's lock 871 *
872 * - this may cause an already locked object to wind up being processed again 872 * If we don't manage to finish the list before the scheduler wants to run
873 * again then return false immediately. We return true if the list was
874 * cleared.
873 */ 875 */
874static void fscache_enqueue_dependents(struct fscache_object *object) 876static bool fscache_enqueue_dependents(struct fscache_object *object, int event)
875{ 877{
876 struct fscache_object *dep; 878 struct fscache_object *dep;
879 bool ret = true;
877 880
878 _enter("{OBJ%x}", object->debug_id); 881 _enter("{OBJ%x}", object->debug_id);
879 882
880 if (list_empty(&object->dependents)) 883 if (list_empty(&object->dependents))
881 return; 884 return true;
882 885
883 spin_lock(&object->lock); 886 spin_lock(&object->lock);
884 887
@@ -887,23 +890,23 @@ static void fscache_enqueue_dependents(struct fscache_object *object)
887 struct fscache_object, dep_link); 890 struct fscache_object, dep_link);
888 list_del_init(&dep->dep_link); 891 list_del_init(&dep->dep_link);
889 892
890 893 fscache_raise_event(dep, event);
891 /* sort onto appropriate lists */
892 fscache_enqueue_object(dep);
893 fscache_put_object(dep); 894 fscache_put_object(dep);
894 895
895 if (!list_empty(&object->dependents)) 896 if (!list_empty(&object->dependents) && need_resched()) {
896 cond_resched_lock(&object->lock); 897 ret = false;
898 break;
899 }
897 } 900 }
898 901
899 spin_unlock(&object->lock); 902 spin_unlock(&object->lock);
903 return ret;
900} 904}
901 905
902/* 906/*
903 * remove an object from whatever queue it's waiting on 907 * remove an object from whatever queue it's waiting on
904 * - the caller must hold object->lock
905 */ 908 */
906void fscache_dequeue_object(struct fscache_object *object) 909static void fscache_dequeue_object(struct fscache_object *object)
907{ 910{
908 _enter("{OBJ%x}", object->debug_id); 911 _enter("{OBJ%x}", object->debug_id);
909 912
@@ -963,12 +966,14 @@ EXPORT_SYMBOL(fscache_check_aux);
963/* 966/*
964 * Asynchronously invalidate an object. 967 * Asynchronously invalidate an object.
965 */ 968 */
966static void fscache_invalidate_object(struct fscache_object *object) 969static const struct fscache_state *_fscache_invalidate_object(struct fscache_object *object,
970 int event)
967{ 971{
968 struct fscache_operation *op; 972 struct fscache_operation *op;
969 struct fscache_cookie *cookie = object->cookie; 973 struct fscache_cookie *cookie = object->cookie;
970 974
971 _enter("{OBJ%x}", object->debug_id); 975 _enter("{OBJ%x},%d", object->debug_id, event);
976
972 977
973 /* Reject any new read/write ops and abort any that are pending. */ 978 /* Reject any new read/write ops and abort any that are pending. */
974 fscache_invalidate_writes(cookie); 979 fscache_invalidate_writes(cookie);
@@ -978,9 +983,9 @@ static void fscache_invalidate_object(struct fscache_object *object)
978 /* Now we have to wait for in-progress reads and writes */ 983 /* Now we have to wait for in-progress reads and writes */
979 op = kzalloc(sizeof(*op), GFP_KERNEL); 984 op = kzalloc(sizeof(*op), GFP_KERNEL);
980 if (!op) { 985 if (!op) {
981 fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR); 986 clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
982 _leave(" [ENOMEM]"); 987 _leave(" [ENOMEM]");
983 return; 988 return transit_to(KILL_OBJECT);
984 } 989 }
985 990
986 fscache_operation_init(op, object->cache->ops->invalidate_object, NULL); 991 fscache_operation_init(op, object->cache->ops->invalidate_object, NULL);
@@ -1001,13 +1006,44 @@ static void fscache_invalidate_object(struct fscache_object *object)
1001 /* We can allow read and write requests to come in once again. They'll 1006 /* We can allow read and write requests to come in once again. They'll
1002 * queue up behind our exclusive invalidation operation. 1007 * queue up behind our exclusive invalidation operation.
1003 */ 1008 */
1004 fscache_invalidation_complete(cookie); 1009 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
1005 _leave(""); 1010 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
1006 return; 1011 _leave(" [ok]");
1012 return transit_to(UPDATE_OBJECT);
1007 1013
1008submit_op_failed: 1014submit_op_failed:
1015 clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
1009 spin_unlock(&cookie->lock); 1016 spin_unlock(&cookie->lock);
1010 kfree(op); 1017 kfree(op);
1011 fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR);
1012 _leave(" [EIO]"); 1018 _leave(" [EIO]");
1019 return transit_to(KILL_OBJECT);
1020}
1021
1022static const struct fscache_state *fscache_invalidate_object(struct fscache_object *object,
1023 int event)
1024{
1025 const struct fscache_state *s;
1026
1027 fscache_stat(&fscache_n_invalidates_run);
1028 fscache_stat(&fscache_n_cop_invalidate_object);
1029 s = _fscache_invalidate_object(object, event);
1030 fscache_stat_d(&fscache_n_cop_invalidate_object);
1031 return s;
1032}
1033
1034/*
1035 * Asynchronously update an object.
1036 */
1037static const struct fscache_state *fscache_update_object(struct fscache_object *object,
1038 int event)
1039{
1040 _enter("{OBJ%x},%d", object->debug_id, event);
1041
1042 fscache_stat(&fscache_n_updates_run);
1043 fscache_stat(&fscache_n_cop_update_object);
1044 object->cache->ops->update_object(object);
1045 fscache_stat_d(&fscache_n_cop_update_object);
1046
1047 _leave("");
1048 return transit_to(WAIT_FOR_CMD);
1013} 1049}
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index ccf02194e7a6..4da211b21ddf 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -119,7 +119,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
119 /* need to issue a new write op after this */ 119 /* need to issue a new write op after this */
120 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); 120 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
121 ret = 0; 121 ret = 0;
122 } else if (object->state == FSCACHE_OBJECT_CREATING) { 122 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
123 op->object = object; 123 op->object = object;
124 object->n_ops++; 124 object->n_ops++;
125 object->n_exclusive++; /* reads and writes must wait */ 125 object->n_exclusive++; /* reads and writes must wait */
@@ -144,7 +144,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
144 */ 144 */
145static void fscache_report_unexpected_submission(struct fscache_object *object, 145static void fscache_report_unexpected_submission(struct fscache_object *object,
146 struct fscache_operation *op, 146 struct fscache_operation *op,
147 unsigned long ostate) 147 const struct fscache_state *ostate)
148{ 148{
149 static bool once_only; 149 static bool once_only;
150 struct fscache_operation *p; 150 struct fscache_operation *p;
@@ -155,11 +155,8 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
155 once_only = true; 155 once_only = true;
156 156
157 kdebug("unexpected submission OP%x [OBJ%x %s]", 157 kdebug("unexpected submission OP%x [OBJ%x %s]",
158 op->debug_id, object->debug_id, 158 op->debug_id, object->debug_id, object->state->name);
159 fscache_object_states[object->state]); 159 kdebug("objstate=%s [%s]", object->state->name, ostate->name);
160 kdebug("objstate=%s [%s]",
161 fscache_object_states[object->state],
162 fscache_object_states[ostate]);
163 kdebug("objflags=%lx", object->flags); 160 kdebug("objflags=%lx", object->flags);
164 kdebug("objevent=%lx [%lx]", object->events, object->event_mask); 161 kdebug("objevent=%lx [%lx]", object->events, object->event_mask);
165 kdebug("ops=%u inp=%u exc=%u", 162 kdebug("ops=%u inp=%u exc=%u",
@@ -190,7 +187,7 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
190int fscache_submit_op(struct fscache_object *object, 187int fscache_submit_op(struct fscache_object *object,
191 struct fscache_operation *op) 188 struct fscache_operation *op)
192{ 189{
193 unsigned long ostate; 190 const struct fscache_state *ostate;
194 int ret; 191 int ret;
195 192
196 _enter("{OBJ%x OP%x},{%u}", 193 _enter("{OBJ%x OP%x},{%u}",
@@ -226,16 +223,14 @@ int fscache_submit_op(struct fscache_object *object,
226 fscache_run_op(object, op); 223 fscache_run_op(object, op);
227 } 224 }
228 ret = 0; 225 ret = 0;
229 } else if (object->state == FSCACHE_OBJECT_CREATING) { 226 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
230 op->object = object; 227 op->object = object;
231 object->n_ops++; 228 object->n_ops++;
232 atomic_inc(&op->usage); 229 atomic_inc(&op->usage);
233 list_add_tail(&op->pend_link, &object->pending_ops); 230 list_add_tail(&op->pend_link, &object->pending_ops);
234 fscache_stat(&fscache_n_op_pend); 231 fscache_stat(&fscache_n_op_pend);
235 ret = 0; 232 ret = 0;
236 } else if (object->state == FSCACHE_OBJECT_DYING || 233 } else if (fscache_object_is_dying(object)) {
237 object->state == FSCACHE_OBJECT_LC_DYING ||
238 object->state == FSCACHE_OBJECT_WITHDRAWING) {
239 fscache_stat(&fscache_n_op_rejected); 234 fscache_stat(&fscache_n_op_rejected);
240 op->state = FSCACHE_OP_ST_CANCELLED; 235 op->state = FSCACHE_OP_ST_CANCELLED;
241 ret = -ENOBUFS; 236 ret = -ENOBUFS;
@@ -266,13 +261,14 @@ void fscache_abort_object(struct fscache_object *object)
266 261
267/* 262/*
268 * jump start the operation processing on an object 263 * jump start the operation processing on an object
269 * - caller must hold object->lock
270 */ 264 */
271void fscache_start_operations(struct fscache_object *object) 265void fscache_start_operations(struct fscache_object *object)
272{ 266{
273 struct fscache_operation *op; 267 struct fscache_operation *op;
274 bool stop = false; 268 bool stop = false;
275 269
270 ASSERT(spin_is_locked(&object->lock));
271
276 while (!list_empty(&object->pending_ops) && !stop) { 272 while (!list_empty(&object->pending_ops) && !stop) {
277 op = list_entry(object->pending_ops.next, 273 op = list_entry(object->pending_ops.next,
278 struct fscache_operation, pend_link); 274 struct fscache_operation, pend_link);
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 42f8f2d8a197..b4e4b424160a 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -408,7 +408,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
408 object = hlist_entry(cookie->backing_objects.first, 408 object = hlist_entry(cookie->backing_objects.first,
409 struct fscache_object, cookie_link); 409 struct fscache_object, cookie_link);
410 410
411 ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP); 411 ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags));
412 412
413 atomic_inc(&object->n_reads); 413 atomic_inc(&object->n_reads);
414 __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); 414 __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
@@ -729,8 +729,9 @@ static void fscache_write_op(struct fscache_operation *_op)
729 */ 729 */
730 spin_unlock(&object->lock); 730 spin_unlock(&object->lock);
731 fscache_op_complete(&op->op, false); 731 fscache_op_complete(&op->op, false);
732 _leave(" [cancel] op{f=%lx s=%u} obj{s=%u f=%lx}", 732 _leave(" [cancel] op{f=%lx s=%u} obj{s=%s f=%lx}",
733 _op->flags, _op->state, object->state, object->flags); 733 _op->flags, _op->state, object->state->short_name,
734 object->flags);
734 return; 735 return;
735 } 736 }
736 737
@@ -833,14 +834,12 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie)
833 * (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is 834 * (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is
834 * set) 835 * set)
835 * 836 *
836 * (a) no writes yet (set FSCACHE_COOKIE_PENDING_FILL and queue deferred 837 * (a) no writes yet
837 * fill op)
838 * 838 *
839 * (b) writes deferred till post-creation (mark page for writing and 839 * (b) writes deferred till post-creation (mark page for writing and
840 * return immediately) 840 * return immediately)
841 * 841 *
842 * (2) negative lookup, object created, initial fill being made from netfs 842 * (2) negative lookup, object created, initial fill being made from netfs
843 * (FSCACHE_COOKIE_INITIAL_FILL is set)
844 * 843 *
845 * (a) fill point not yet reached this page (mark page for writing and 844 * (a) fill point not yet reached this page (mark page for writing and
846 * return) 845 * return)