diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 83ca0df838..db28120e9e 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -4930,21 +4930,12 @@ ztest_resume_thread(void *arg) return (NULL); } -static void * -ztest_deadman_thread(void *arg) +#define GRACE 300 + +static void +ztest_deadman_alarm(int sig) { - ztest_shared_t *zs = arg; - int grace = 300; - hrtime_t delta; - - delta = (zs->zs_thread_stop - zs->zs_thread_start) / NANOSEC + grace; - - (void) poll(NULL, 0, (int)(1000 * delta)); - - fatal(0, "failed to complete within %d seconds of deadline", grace); - thread_exit(); - - return (NULL); + fatal(0, "failed to complete within %d seconds of deadline", GRACE); } static void @@ -5134,7 +5125,7 @@ ztest_dataset_close(ztest_shared_t *zs, int d) static void ztest_run(ztest_shared_t *zs) { - kthread_t **tid; + kt_did_t *tid; spa_t *spa; kthread_t *resume_thread; uint64_t object; @@ -5187,10 +5178,10 @@ ztest_run(ztest_shared_t *zs) spa, TS_RUN, NULL, 0, 0)), !=, NULL); /* - * Create a deadman thread to abort() if we hang. + * Set a deadman alarm to abort() if we hang. */ - VERIFY3P(thread_create(NULL, 0, ztest_deadman_thread, zs, - TS_RUN, NULL, 0, 0), !=, NULL); + signal(SIGALRM, ztest_deadman_alarm); + alarm((zs->zs_thread_stop - zs->zs_thread_start) / NANOSEC + GRACE); /* * Verify that we can safely inquire about about any object, @@ -5216,7 +5207,7 @@ ztest_run(ztest_shared_t *zs) } zs->zs_enospc_count = 0; - tid = umem_zalloc(zopt_threads * sizeof (kthread_t *), UMEM_NOFAIL); + tid = umem_zalloc(zopt_threads * sizeof (kt_did_t), UMEM_NOFAIL); if (zopt_verbose >= 4) (void) printf("starting main threads...\n"); @@ -5225,11 +5216,14 @@ ztest_run(ztest_shared_t *zs) * Kick off all the tests that run in parallel. */ for (t = 0; t < zopt_threads; t++) { + kthread_t *thread; + if (t < zopt_datasets && ztest_dataset_open(zs, t) != 0) return; - VERIFY3P(tid[t] = thread_create(NULL, 0, ztest_thread, + VERIFY3P(thread = thread_create(NULL, 0, ztest_thread, (void *)(uintptr_t)t, TS_RUN, NULL, 0, 0), !=, NULL); + tid[t] = thread->t_tid; } /* @@ -5237,7 +5231,7 @@ ztest_run(ztest_shared_t *zs) * so we don't close datasets while threads are still using them. */ for (t = zopt_threads - 1; t >= 0; t--) { - thread_join(tid[t]->t_tid); + thread_join(tid[t]); if (t < zopt_datasets) ztest_dataset_close(zs, t); } @@ -5247,7 +5241,7 @@ ztest_run(ztest_shared_t *zs) zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa)); zs->zs_space = metaslab_class_get_space(spa_normal_class(spa)); - umem_free(tid, zopt_threads * sizeof (kthread_t *)); + umem_free(tid, zopt_threads * sizeof (kt_did_t)); /* Kill the resume thread */ ztest_exiting = B_TRUE; diff --git a/lib/libzpool/include/sys/zfs_context.h b/lib/libzpool/include/sys/zfs_context.h index afca6364db..c104f6d3a1 100644 --- a/lib/libzpool/include/sys/zfs_context.h +++ b/lib/libzpool/include/sys/zfs_context.h @@ -203,7 +203,8 @@ _NOTE(CONSTCOND) } while (0) /* * Threads */ -#define TS_RUN 0x00000002 +#define TS_MAGIC 0x72f158ab4261e538ull +#define TS_RUN 0x00000002 #ifdef _linux_ #define STACK_SIZE 8192 /* Linux x86 and amd64 */ #else @@ -227,7 +228,6 @@ typedef struct kthread { void * t_arg; } kthread_t; -/* XXX tsd_create()/tsd_destroy() missing */ #define tsd_get(key) pthread_getspecific(key) #define tsd_set(key, val) pthread_setspecific(key, val) #define curthread zk_thread_current() diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index f9488177e3..a4252c6310 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -191,13 +191,16 @@ zk_thread_exit(void) pthread_mutex_unlock(&kthread_lock); pthread_cond_broadcast(&kthread_cond); - pthread_exit(NULL); + pthread_exit((void *)TS_MAGIC); } void zk_thread_join(kt_did_t tid) { - pthread_join((pthread_t)tid, NULL); + void *ret; + + pthread_join((pthread_t)tid, &ret); + VERIFY3P(ret, ==, (void *)TS_MAGIC); } /* @@ -507,10 +510,12 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) int fd; vnode_t *vp; int old_umask; - char realpath[MAXPATHLEN]; + char *realpath; struct stat64 st; int err; + realpath = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); + /* * If we're accessing a real disk from userland, we need to use * the character interface to avoid caching. This is particularly @@ -524,11 +529,16 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) if (strncmp(path, "/dev/", 5) == 0) { char *dsk; fd = open64(path, O_RDONLY); - if (fd == -1) - return (errno); + if (fd == -1) { + err = errno; + free(realpath); + return (err); + } if (fstat64(fd, &st) == -1) { + err = errno; close(fd); - return (errno); + free(realpath); + return (err); } close(fd); (void) sprintf(realpath, "%s", path); @@ -538,8 +548,11 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) dsk + 1); } else { (void) sprintf(realpath, "%s", path); - if (!(flags & FCREAT) && stat64(realpath, &st) == -1) - return (errno); + if (!(flags & FCREAT) && stat64(realpath, &st) == -1) { + err = errno; + free(realpath); + return (err); + } } if (flags & FCREAT) @@ -550,6 +563,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. */ fd = open64(realpath, flags - FREAD, mode); + free(realpath); if (flags & FCREAT) (void) umask(old_umask); diff --git a/module/zfs/dmu_traverse.c b/module/zfs/dmu_traverse.c index 3350c08bc1..85b5f59cd6 100644 --- a/module/zfs/dmu_traverse.c +++ b/module/zfs/dmu_traverse.c @@ -356,46 +356,54 @@ static int traverse_impl(spa_t *spa, uint64_t objset, blkptr_t *rootbp, uint64_t txg_start, int flags, blkptr_cb_t func, void *arg) { - struct traverse_data td; - struct prefetch_data pd; - zbookmark_t czb; + struct traverse_data *td; + struct prefetch_data *pd; + zbookmark_t *czb; int err; - td.td_spa = spa; - td.td_objset = objset; - 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(struct traverse_data), KM_SLEEP); + pd = kmem_alloc(sizeof(struct prefetch_data), KM_SLEEP); + czb = kmem_alloc(sizeof(zbookmark_t), KM_SLEEP); - pd.pd_blks_max = 100; - pd.pd_blks_fetched = 0; - pd.pd_flags = flags; - pd.pd_cancel = B_FALSE; - pd.pd_exited = B_FALSE; - mutex_init(&pd.pd_mtx, NULL, MUTEX_DEFAULT, NULL); - cv_init(&pd.pd_cv, NULL, CV_DEFAULT, NULL); + td->td_spa = spa; + td->td_objset = objset; + 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 = 100; + pd->pd_blks_fetched = 0; + pd->pd_flags = flags; + pd->pd_cancel = B_FALSE; + pd->pd_exited = B_FALSE; + mutex_init(&pd->pd_mtx, NULL, MUTEX_DEFAULT, NULL); + cv_init(&pd->pd_cv, NULL, CV_DEFAULT, NULL); 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, objset, + SET_BOOKMARK(czb, 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); } diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index b5935d127e..7b17e6fcef 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -1038,7 +1038,7 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) dsl_dir_t *dd; uint64_t obj; struct dsl_ds_destroyarg dsda = { 0 }; - dsl_dataset_t dummy_ds = { 0 }; + dsl_dataset_t *dummy_ds; dsda.ds = ds; @@ -1058,8 +1058,9 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) } dd = ds->ds_dir; - dummy_ds.ds_dir = dd; - dummy_ds.ds_object = ds->ds_object; + dummy_ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP); + dummy_ds->ds_dir = dd; + dummy_ds->ds_object = ds->ds_object; /* * Check for errors and mark this ds as inconsistent, in @@ -1068,11 +1069,11 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) err = dsl_sync_task_do(dd->dd_pool, dsl_dataset_destroy_begin_check, dsl_dataset_destroy_begin_sync, ds, NULL, 0); if (err) - goto out; + goto out_free; err = dmu_objset_from_ds(ds, &os); if (err) - goto out; + goto out_free; /* * remove the objects in open context, so that we won't @@ -1108,14 +1109,14 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) } if (err != ESRCH) - goto out; + goto out_free; rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); err = dsl_dir_open_obj(dd->dd_pool, dd->dd_object, NULL, FTAG, &dd); rw_exit(&dd->dd_pool->dp_config_rwlock); if (err) - goto out; + goto out_free; /* * Blow away the dsl_dir + head dataset. @@ -1131,7 +1132,7 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) err = dsl_dataset_origin_rm_prep(&dsda, tag); if (err) { dsl_dir_close(dd, FTAG); - goto out; + goto out_free; } } @@ -1139,7 +1140,7 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) dsl_sync_task_create(dstg, dsl_dataset_destroy_check, dsl_dataset_destroy_sync, &dsda, tag, 0); dsl_sync_task_create(dstg, dsl_dir_destroy_check, - dsl_dir_destroy_sync, &dummy_ds, FTAG, 0); + dsl_dir_destroy_sync, dummy_ds, FTAG, 0); err = dsl_sync_task_group_wait(dstg); dsl_sync_task_group_destroy(dstg); @@ -1162,6 +1163,9 @@ dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer) /* if it is successful, dsl_dir_destroy_sync will close the dd */ if (err) dsl_dir_close(dd, FTAG); + +out_free: + kmem_free(dummy_ds, sizeof (dsl_dataset_t)); out: dsl_dataset_disown(ds, tag); return (err);