Skip to content

Instantly share code, notes, and snippets.

@sdimitro
Created February 22, 2019 23:43
Show Gist options
  • Save sdimitro/87f3a672ba9ae92fb7fa3140f9930d00 to your computer and use it in GitHub Desktop.
Save sdimitro/87f3a672ba9ae92fb7fa3140f9930d00 to your computer and use it in GitHub Desktop.
static int
bpobj_iterate_impl(bpobj_t *initial_bpo, bpobj_itor_t func, void *arg,
dmu_tx_t *tx, boolean_t free)
{
int err = 0;
list_t stack;
list_create(&stack, sizeof (bpobj_info_t),
offsetof(bpobj_info_t, bpi_node));
list_insert_head(&stack, bpi_alloc(initial_bpo, NULL, 0, 0));
for (bpobj_info_t *bpi = list_head(&stack);
bpi != NULL; bpi = list_head(&stack)) {
bpobj_t *bpo = bpi->bpi_bpo;
mutex_enter(&bpo->bpo_lock);
ASSERT(bpobj_is_open(bpo));
if (free)
dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
if (bpi->bpi_visited == B_FALSE) {
err = bpobj_iterate_blkptrs(bpi, func, arg, tx, free);
bpi->bpi_visited = B_TRUE;
if (err != 0)
goto out;
// XXX: chec has_subobjs etc.. set bpi_unprocessed_subobjs here
bpi->bpi_unprocessed_subobjs = bpo->bpo_phys->bpo_num_subobjs;
} else if (bpi->bpi_visited && bpi->bpi_unprocessed_subobjs == 0) {
/*
* If there are no entries, there should
* be no bytes.
*/
if (bpobj_is_empty(bpo)) {
ASSERT0(bpo->bpo_phys->bpo_bytes);
ASSERT0(bpo->bpo_phys->bpo_comp);
ASSERT0(bpo->bpo_phys->bpo_uncomp);
}
if (free && (bpi->bpi_parent != NULL)) {
bpobj_t *p = bpi->bpi_parent->bpi_bpo;
ASSERT0(bpo->bpo_phys->bpo_num_blkptrs);
ASSERT3U(p->bpo_phys->bpo_num_subobjs, >, 0);
ASSERT3U(bpi->bpi_index, ==,
p->bpo_phys->bpo_num_subobjs - 1);
VERIFY0(dmu_free_range(p->bpo_os,
p->bpo_phys->bpo_subobjs,
bpi->bpi_index * sizeof (uint64_t),
sizeof (uint64_t), tx));
/* eliminate the empty subobj */
if (bpo->bpo_havesubobj &&
bpo->bpo_phys->bpo_subobjs != 0) {
ASSERT0(bpo->bpo_phys->bpo_num_subobjs);
err = dmu_object_free(bpo->bpo_os,
bpo->bpo_phys->bpo_subobjs, tx);
if (err)
break;
dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
bpo->bpo_phys->bpo_subobjs = 0;
}
err = dmu_object_free(p->bpo_os,
bpi->bpi_object, tx);
if (err)
break;
}
mutex_exit(&bpo->bpo_lock);
if (bpi->bpi_parent != NULL) {
bpobj_close(bpo);
}
list_remove(&stack, bpi);
kmem_free(bpi, sizeof (bpobj_info_t));
} else {
ASSERT(bpo->bpo_havecomp);
/* Add the last subobj to stack. */
int64_t i = bpi->bpi_unprocessed_subobjs - 1;
uint64_t offset = i * sizeof (uint64_t);
uint64_t obj_from_sublist;
err = dmu_read(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs,
offset, sizeof (uint64_t), &obj_from_sublist,
DMU_READ_PREFETCH);
bpobj_t *sublist = kmem_alloc(sizeof (bpobj_t),
KM_SLEEP);
err = bpobj_open(sublist, bpo->bpo_os, obj_from_sublist);
if (err)
break;
if (free)
dmu_buf_will_dirty(sublist->bpo_dbuf, tx);
list_insert_head(&stack, bpi_alloc(sublist, bpi,
obj_from_sublist, i));
bpi->bpi_unprocessed_subobjs--;
}
}
out:
if (err != 0)
bpobj_iterate_cleanup(&stack);
ASSERT(list_is_empty(&stack));
list_destroy(&stack);
return (err);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment