diff options
-rw-r--r-- | module/zfs/dmu_traverse.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/module/zfs/dmu_traverse.c b/module/zfs/dmu_traverse.c index 023f90e12..fb102c6ca 100644 --- a/module/zfs/dmu_traverse.c +++ b/module/zfs/dmu_traverse.c @@ -356,24 +356,28 @@ static int traverse_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *rootbp, uint64_t txg_start, int flags, blkptr_cb_t func, void *arg) { - traverse_data_t td; - prefetch_data_t pd = { 0 }; - zbookmark_t czb; + traverse_data_t *td; + prefetch_data_t *pd; + zbookmark_t *czb; int err; - td.td_spa = spa; - td.td_objset = ds ? ds->ds_object : 0; - td.td_rootbp = rootbp; - td.td_min_txg = txg_start; - td.td_func = func; - td.td_arg = arg; - td.td_pfd = &pd; - td.td_flags = flags; + td = kmem_alloc(sizeof(traverse_data_t), KM_SLEEP); + pd = kmem_zalloc(sizeof(prefetch_data_t), KM_SLEEP); + czb = kmem_alloc(sizeof(zbookmark_t), KM_SLEEP); + + td->td_spa = spa; + td->td_objset = ds ? ds->ds_object : 0; + td->td_rootbp = rootbp; + td->td_min_txg = txg_start; + td->td_func = func; + td->td_arg = arg; + td->td_pfd = pd; + td->td_flags = flags; - pd.pd_blks_max = zfs_pd_blks_max; - pd.pd_flags = flags; - mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL); - cv_init(&pd.pd_cv, NULL, CV_DEFAULT, NULL); + pd->pd_blks_max = zfs_pd_blks_max; + pd->pd_flags = flags; + mutex_init(&pd->pd_mtx, NULL, MUTEX_DEFAULT, NULL); + cv_init(&pd->pd_cv, NULL, CV_DEFAULT, NULL); /* See comment on ZIL traversal in dsl_scan_visitds. */ if (ds != NULL && !dsl_dataset_is_snapshot(ds)) { @@ -383,27 +387,31 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *rootbp, if (err) return (err); - traverse_zil(&td, &os->os_zil_header); + traverse_zil(td, &os->os_zil_header); } if (!(flags & TRAVERSE_PREFETCH) || 0 == taskq_dispatch(system_taskq, traverse_prefetch_thread, - &td, TQ_NOQUEUE)) - pd.pd_exited = B_TRUE; + td, TQ_NOQUEUE)) + pd->pd_exited = B_TRUE; - SET_BOOKMARK(&czb, td.td_objset, + SET_BOOKMARK(czb, td->td_objset, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); - err = traverse_visitbp(&td, NULL, NULL, rootbp, &czb); + err = traverse_visitbp(td, NULL, NULL, rootbp, czb); + + mutex_enter(&pd->pd_mtx); + pd->pd_cancel = B_TRUE; + cv_broadcast(&pd->pd_cv); + while (!pd->pd_exited) + cv_wait(&pd->pd_cv, &pd->pd_mtx); + mutex_exit(&pd->pd_mtx); - mutex_enter(&pd.pd_mtx); - pd.pd_cancel = B_TRUE; - cv_broadcast(&pd.pd_cv); - while (!pd.pd_exited) - cv_wait(&pd.pd_cv, &pd.pd_mtx); - mutex_exit(&pd.pd_mtx); + mutex_destroy(&pd->pd_mtx); + cv_destroy(&pd->pd_cv); - mutex_destroy(&pd.pd_mtx); - cv_destroy(&pd.pd_cv); + kmem_free(czb, sizeof(zbookmark_t)); + kmem_free(pd, sizeof(struct prefetch_data)); + kmem_free(td, sizeof(struct traverse_data)); return (err); } |