hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
--------------------------------
When initialising an object in fscache_initialise_object(), it will just drop the object due to [no parent]/[bad parent]/[grab failed], however the current object may already have children added in fscache_attach_object(), so the assertion may fail in fscache_put_object() because n_children != 0.
========================================================= kernel BUG at fs/cachefiles/interface.c:372! CPU: 2 PID: 153 Comm: kworker/u8:7 5.10.0-00001-g24c450967e57-dirty RIP: 0010:cachefiles_put_object.cold+0x3b3/0x434 Call Trace: fscache_put_object+0x77/0xc0 fscache_object_work_func+0x4d/0x60 process_one_work+0x40e/0x810 worker_thread+0x96/0x700 kthread+0x1f4/0x250 ret_from_fork+0x1f/0x30 =========================================================
As follows, mounting OBJ1 and OBJ4 successively can trigger the above assertion failure:
OBJ0->OBJ3->OBJ2->OBJ1 | --->OBJ5->OBJ4
fscache_look_up_object(OBJ3) cachefiles_lookup_object cachefiles_walk_to_object fscache_object_lookup_negative fscache_lookup_failure(OBJ3) __fscache_acquire_cookie fscache_acquire_non_index_cookie fscache_alloc_object(OBJ4) fscache_alloc_object(OBJ5) fscache_attach_object(OBJ5) cookie->parent->backing_objects fscache_object_is_dying(OBJ3) OBJ3->n_children++ fscache_kill_object(OBJ3) fscache_mark_object_dead(OBJ3) clear_bit(FSCACHE_OBJECT_IS_LIVE, &OBJ3->flags); fscache_kill_dependents(OBJ3) list_del_init(&dep->dep_link); // WAIT_FOR_CLEARANCE fscache_attach_object(OBJ4) OBJ4->parent = OBJ5 OBJ5->n_children++ fscache_raise_event(OBJ4, OBJECT_NEW_CHILD) fscache_initialise_object(OBJ4) fscache_raise_event(OBJ5, OBJECT_NEW_CHILD) fscache_initialise_object(OBJ5) if (fscache_object_is_dying(OBJ3)) fscache_drop_object(OBJ5) cachefiles_drop_object(OBJ5) OBJ3->n_children-- fscache_put_object(OBJ5) cachefiles_put_object(OBJ5) OBJ5->usage == 0 OBJ5)->fscache.n_children != 0 // ASSERTCMP FAIL
To fix this, replace DROP_OBJECT in fscache_initialise_object() with KILL_OBJECT so that it waits for n_children to become 0 when there are child objects.
Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/fscache/object.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 9ce3041a5d71..0375f448afc4 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -382,14 +382,14 @@ static const struct fscache_state *fscache_initialise_object(struct fscache_obje parent = object->parent; if (!parent) { _leave(" [no parent]"); - return transit_to(DROP_OBJECT); + return transit_to(KILL_OBJECT); }
_debug("parent: %s of:%lx", parent->state->name, parent->flags);
if (fscache_object_is_dying(parent)) { _leave(" [bad parent]"); - return transit_to(DROP_OBJECT); + return transit_to(KILL_OBJECT); }
if (fscache_object_is_available(parent)) { @@ -411,7 +411,7 @@ static const struct fscache_state *fscache_initialise_object(struct fscache_obje spin_unlock(&parent->lock); if (!success) { _leave(" [grab failed]"); - return transit_to(DROP_OBJECT); + return transit_to(KILL_OBJECT); }
/* fscache_acquire_non_index_cookie() uses this