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 <jlay...@kernel.org>
---
 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@redhat.com
https://www.redhat.com/mailman/listinfo/linux-cachefs

Reply via email to