After basic initialization of an fscache object, the oob_table is set to fscache_osm_init_oob. Eventually though, we'll wait on the parent to be ready and at that point, fscache_osm_init_oob is not sufficient to unwind the current state of the object. Fix this by having fscache_parent_ready set the oob_table to a new state that properly releases the parent and then transitions to the ABORT_INIT state to finish the cleanup. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/fscache/object.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/fscache/object.c b/fs/fscache/object.c index a42b206c0659..51f2991fed3f 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -15,6 +15,7 @@ #include "internal.h" static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *, int); +static const struct fscache_state *fscache_abort_parent(struct fscache_object *, int); static const struct fscache_state *fscache_kill_dependents(struct fscache_object *, int); static const struct fscache_state *fscache_drop_object(struct fscache_object *, int); static const struct fscache_state *fscache_initialise_object(struct fscache_object *, int); @@ -75,6 +76,7 @@ static const struct fscache_state *fscache_object_dead(struct fscache_object *, */ static WORK_STATE(INIT_OBJECT, "INIT", fscache_initialise_object); static WORK_STATE(PARENT_READY, "PRDY", fscache_parent_ready); +static WORK_STATE(ABORT_PARENT, "ABTP", fscache_abort_parent); static WORK_STATE(ABORT_INIT, "ABRT", fscache_abort_initialisation); static WORK_STATE(LOOK_UP_OBJECT, "LOOK", fscache_look_up_object); static WORK_STATE(CREATE_OBJECT, "CRTO", fscache_look_up_object); @@ -120,6 +122,13 @@ static const struct fscache_transition fscache_osm_init_oob[] = { { 0, NULL } }; +static const struct fscache_transition fscache_osm_parent_oob[] = { + TRANSIT_TO(ABORT_PARENT, + (1 << FSCACHE_OBJECT_EV_ERROR) | + (1 << FSCACHE_OBJECT_EV_KILL)), + { 0, NULL } +}; + static const struct fscache_transition fscache_osm_lookup_oob[] = { TRANSIT_TO(LOOKUP_FAILURE, (1 << FSCACHE_OBJECT_EV_ERROR) | @@ -350,9 +359,7 @@ static inline void fscache_mark_object_dead(struct fscache_object *object) spin_unlock(&object->lock); } -/* - * Abort object initialisation before we start it. - */ +/* Abort object initialisation before we start it. */ static const struct fscache_state *fscache_abort_initialisation(struct fscache_object *object, int event) { @@ -363,6 +370,15 @@ static const struct fscache_state *fscache_abort_initialisation(struct fscache_o return transit_to(KILL_OBJECT); } +/* Abort object init after the parent is ready. */ +static const struct fscache_state *fscache_abort_parent(struct fscache_object *object, + int event) +{ + _enter("{OBJ%x},%d", object->debug_id, event); + fscache_done_parent_op(object); + return transit_to(ABORT_INIT); +} + /* * initialise an object * - check the specified object's parent to see if we can make use of it @@ -434,6 +450,8 @@ static const struct fscache_state *fscache_parent_ready(struct fscache_object *o ASSERT(parent != NULL); + object->oob_table = fscache_osm_parent_oob; + spin_lock(&parent->lock); parent->n_ops++; parent->n_obj_ops++; -- 2.21.0 -- Linux-cachefs mailing list Linux-cachefs@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/linux-cachefs