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 <mahrens@delphix.com>
Reviewed-by: Mark Maybee <mark.maybee@delphix.com>
Reviewed-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Signed-off-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Closes #13939
This commit is contained in:
Serapheim Dimitropoulos 2022-09-29 09:39:48 -07:00 committed by Brian Behlendorf
parent c8d6a91a99
commit 37763ea2a6
1 changed files with 6 additions and 1 deletions

View File

@ -1028,8 +1028,13 @@ dsl_process_sub_livelist(bpobj_t *bpobj, bplist_t *to_free, zthr_t *t,
.t = t .t = t
}; };
int err = bpobj_iterate_nofree(bpobj, dsl_livelist_iterate, &arg, size); 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); avl_destroy(&avl);
return (err); return (err);
} }