diff options
author | Brian Atkinson <batkinson@lanl.gov> | 2021-01-29 00:54:12 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-29 00:54:12 +0000 |
commit | 2993698eb3dfc0b462d216b2ea8bbe7bdb06f841 (patch) | |
tree | 0615002850e09323f866cf0387098bda689508bc | |
parent | 9f8c7e6a76a147cacc26dd0661d1a00da42bf405 (diff) | |
download | src-2993698eb3dfc0b462d216b2ea8bbe7bdb06f841.tar.gz src-2993698eb3dfc0b462d216b2ea8bbe7bdb06f841.zip |
Fixing gang ABD when adding another gang
I originally applied a fix in #11539 to fix a parent's child references
when a gang ABD is free'd. However, I did not take into account
abd_gang_add_gang(). We still need to make sure to update the child
references in this function as well. In order to resolve this I removed
decreasing the gang ABD's size in abd_free_gang() as well as moved back
the original placeent of zfs_refcount_remove_many() in abd_free().
Reviewed-by: Mark Maybee <mark.maybee@delphix.com>
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Brian Atkinson <batkinson@lanl.gov>
Closes #11542
-rw-r--r-- | module/zfs/abd.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/module/zfs/abd.c b/module/zfs/abd.c index 34bf9100bd50..0d48b39c04ce 100644 --- a/module/zfs/abd.c +++ b/module/zfs/abd.c @@ -257,11 +257,9 @@ abd_free_gang(abd_t *abd) ASSERT(list_link_active(&cabd->abd_gang_link)); list_remove(&ABD_GANG(abd).abd_gang_chain, cabd); mutex_exit(&cabd->abd_mtx); - abd->abd_size -= cabd->abd_size; if (cabd->abd_flags & ABD_FLAG_GANG_FREE) abd_free(cabd); } - ASSERT0(abd->abd_size); list_destroy(&ABD_GANG(abd).abd_gang_chain); } @@ -292,11 +290,6 @@ abd_free(abd_t *abd) abd_verify(abd); IMPLY(abd->abd_flags & ABD_FLAG_OWNER, abd->abd_parent == NULL); - if (abd->abd_parent != NULL) { - (void) zfs_refcount_remove_many(&abd->abd_parent->abd_children, - abd->abd_size, abd); - } - if (abd_is_gang(abd)) { abd_free_gang(abd); } else if (abd_is_linear(abd)) { @@ -307,6 +300,11 @@ abd_free(abd_t *abd) abd_free_scatter(abd); } + if (abd->abd_parent != NULL) { + (void) zfs_refcount_remove_many(&abd->abd_parent->abd_children, + abd->abd_size, abd); + } + abd_fini_struct(abd); if (abd->abd_flags & ABD_FLAG_ALLOCD) abd_free_struct_impl(abd); @@ -366,7 +364,7 @@ abd_gang_add_gang(abd_t *pabd, abd_t *cabd, boolean_t free_on_free) &ABD_GANG(cabd).abd_gang_chain); ASSERT(list_is_empty(&ABD_GANG(cabd).abd_gang_chain)); abd_verify(pabd); - abd_free_struct(cabd); + abd_free(cabd); } else { for (abd_t *child = list_head(&ABD_GANG(cabd).abd_gang_chain); child != NULL; |