From 37763ea2a67871ffce452df225b5b71733b8e2a1 Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Thu, 29 Sep 2022 09:39:48 -0700 Subject: [PATCH] Fix panic in dsl_process_sub_livelist for EINTR = Issue Recently we hit an assertion panic in `dsl_process_sub_livelist` while exporting the spa and interrupting `bpobj_iterate_nofree`. In that case `bpobj_iterate_nofree` stops mid-way returning an EINTR without clearing the intermediate AVL tree that keeps track of the livelist entries it has encountered so far. At that point the code has a VERIFY for the number of elements of the AVL expecting it to be zero (which is not the case for EINTR). = Fix Cleanup any intermediate state before destroying the AVL when encountering EINTR. Also added a comment documenting the scenario where the EINTR comes up. There is no need to do anything else for the calles of `dsl_process_sub_livelist` as they already handle the EINTR case. Reviewed-by: Matthew Ahrens Reviewed-by: Mark Maybee Reviewed-by: Richard Yao Signed-off-by: Serapheim Dimitropoulos Closes #13939 --- module/zfs/dsl_deadlist.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/zfs/dsl_deadlist.c b/module/zfs/dsl_deadlist.c index a77e381520..7681b735ec 100644 --- a/module/zfs/dsl_deadlist.c +++ b/module/zfs/dsl_deadlist.c @@ -1028,8 +1028,13 @@ dsl_process_sub_livelist(bpobj_t *bpobj, bplist_t *to_free, zthr_t *t, .t = t }; int err = bpobj_iterate_nofree(bpobj, dsl_livelist_iterate, &arg, size); + VERIFY(err != 0 || avl_numnodes(&avl) == 0); - VERIFY0(avl_numnodes(&avl)); + void *cookie = NULL; + livelist_entry_t *le = NULL; + while ((le = avl_destroy_nodes(&avl, &cookie)) != NULL) { + kmem_free(le, sizeof (livelist_entry_t)); + } avl_destroy(&avl); return (err); }