| @@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object · 29 unmodified lines |
| 30 | static const struct fscache_state *fscache_object_available(struct fscache_object *, int); | 30 | static const struct fscache_state *fscache_object_available(struct fscache_object *, int); |
| 31 | static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); | 31 | static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); |
| 32 | static const struct fscache_state *fscache_update_object(struct fscache_object *, int); | 32 | static const struct fscache_state *fscache_update_object(struct fscache_object *, int); |
| | 33 | static const struct fscache_state *fscache_object_dead(struct fscache_object *, int); |
| 33 | | 34 | |
| 34 | #define __STATE_NAME(n) fscache_osm_##n | 35 | #define __STATE_NAME(n) fscache_osm_##n |
| 35 | #define STATE(n) (&__STATE_NAME(n)) | 36 | #define STATE(n) (&__STATE_NAME(n)) |
| @@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); · 55 unmodified lines |
| 91 | static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); | 92 | static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); |
| 92 | static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); | 93 | static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); |
| 93 | static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); | 94 | static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); |
| 94 | static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL); | 95 | static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead); |
| 95 | | 96 | |
| 96 | static WAIT_STATE(WAIT_FOR_INIT, "?INI", | 97 | static WAIT_STATE(WAIT_FOR_INIT, "?INI", |
| 97 | TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); | 98 | TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); |
| @@ -229,6 +230,10 @@ execute_work_state: · 131 unmodified lines |
| 229 | event = -1; | 230 | event = -1; |
| 230 | if (new_state == NO_TRANSIT) { | 231 | if (new_state == NO_TRANSIT) { |
| 231 | _debug("{OBJ%x} %s notrans", object->debug_id, state->name); | 232 | _debug("{OBJ%x} %s notrans", object->debug_id, state->name); |
| | 233 | if (unlikely(state == STATE(OBJECT_DEAD))) { |
| | 234 | _leave(" [dead]"); |
| | 235 | return; |
| | 236 | } |
| 232 | fscache_enqueue_object(object); | 237 | fscache_enqueue_object(object); |
| 233 | event_mask = object->oob_event_mask; | 238 | event_mask = object->oob_event_mask; |
| 234 | goto unmask_events; | 239 | goto unmask_events; |
| @@ -239,7 +244,7 @@ execute_work_state: · 4 unmodified lines |
| 239 | object->state = state = new_state; | 244 | object->state = state = new_state; |
| 240 | | 245 | |
| 241 | if (state->work) { | 246 | if (state->work) { |
| 242 | if (unlikely(state->work == ((void *)2UL))) { | 247 | if (unlikely(state == STATE(OBJECT_DEAD))) { |
| 243 | _leave(" [dead]"); | 248 | _leave(" [dead]"); |
| 244 | return; | 249 | return; |
| 245 | } | 250 | } |
| @@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob · 399 unmodified lines |
| 645 | fscache_mark_object_dead(object); | 650 | fscache_mark_object_dead(object); |
| 646 | object->oob_event_mask = 0; | 651 | object->oob_event_mask = 0; |
| 647 | | 652 | |
| | 653 | if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) { |
| | 654 | /* Reject any new read/write ops and abort any that are pending. */ |
| | 655 | clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); |
| | 656 | fscache_cancel_all_ops(object); |
| | 657 | } |
| | 658 | |
| 648 | if (list_empty(&object->dependents) && | 659 | if (list_empty(&object->dependents) && |
| 649 | object->n_ops == 0 && | 660 | object->n_ops == 0 && |
| 650 | object->n_children == 0) | 661 | object->n_children == 0) |
| @@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object, · 426 unmodified lines |
| 1077 | } | 1088 | } |
| 1078 | } | 1089 | } |
| 1079 | EXPORT_SYMBOL(fscache_object_mark_killed); | 1090 | EXPORT_SYMBOL(fscache_object_mark_killed); |
| | 1091 | |
| | 1092 | /* |
| | 1093 | * The object is dead. We can get here if an object gets queued by an event |
| | 1094 | * that would lead to its death (such as EV_KILL) when the dispatcher is |
| | 1095 | * already running (and so can be requeued) but hasn't yet cleared the event |
| | 1096 | * mask. |
| | 1097 | */ |
| | 1098 | static const struct fscache_state *fscache_object_dead(struct fscache_object *object, |
| | 1099 | int event) |
| | 1100 | { |
| | 1101 | if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD, |
| | 1102 | &object->flags)) |
| | 1103 | return NO_TRANSIT; |
| | 1104 | |
| | 1105 | WARN(true, "FS-Cache object redispatched after death"); |
| | 1106 | return NO_TRANSIT; |
| | 1107 | } |