| @@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object · 29 unmodified lines |
| 30 | 30 | static const struct fscache_state *fscache_object_available(struct fscache_object *, int); |
| 31 | 31 | static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); |
| 32 | 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 | 35 | #define __STATE_NAME(n) fscache_osm_##n |
| 35 | 36 | #define STATE(n) (&__STATE_NAME(n)) |
| @@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); · 55 unmodified lines |
| 91 | 92 | static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); |
| 92 | 93 | static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); |
| 93 | 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 | 97 | static WAIT_STATE(WAIT_FOR_INIT, "?INI", |
| 97 | 98 | TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); |
| @@ -229,6 +230,10 @@ execute_work_state: · 131 unmodified lines |
| 229 | 230 | event = -1; |
| 230 | 231 | if (new_state == NO_TRANSIT) { |
| 231 | 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 | 237 | fscache_enqueue_object(object); |
| 233 | 238 | event_mask = object->oob_event_mask; |
| 234 | 239 | goto unmask_events; |
| @@ -239,7 +244,7 @@ execute_work_state: · 4 unmodified lines |
| 239 | 244 | object->state = state = new_state; |
| 240 | 245 | |
| 241 | 246 | if (state->work) { |
| 242 | | − if (unlikely(state->work == ((void *)2UL))) { |
| 247 | + if (unlikely(state == STATE(OBJECT_DEAD))) { |
| 243 | 248 | _leave(" [dead]"); |
| 244 | 249 | return; |
| 245 | 250 | } |
| @@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob · 399 unmodified lines |
| 645 | 650 | fscache_mark_object_dead(object); |
| 646 | 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 | 659 | if (list_empty(&object->dependents) && |
| 649 | 660 | object->n_ops == 0 && |
| 650 | 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 | 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 | +} |