Fix stack traverse_impl()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 26 Aug 2010 17:58:47 +0000 (10:58 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 31 Aug 2010 15:38:49 +0000 (08:38 -0700)
Stack use reduced from 560 bytes to 128 bytes.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
module/zfs/dmu_traverse.c

index 023f90e..fb102c6 100644 (file)
@@ -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);
 }