diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 69086a34a2..5706055216 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -4904,21 +4904,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 @@ -5106,7 +5097,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; @@ -5158,10 +5149,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, @@ -5187,7 +5178,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"); @@ -5196,11 +5187,14 @@ ztest_run(ztest_shared_t *zs) * Kick off all the tests that run in parallel. */ for (int 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; } /* @@ -5208,7 +5202,7 @@ ztest_run(ztest_shared_t *zs) * so we don't close datasets while threads are still using them. */ for (int 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); } @@ -5218,7 +5212,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 27a99cc26c..ebc979dc8c 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); } /* diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index a36a2a62e9..8a342e29aa 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -1034,7 +1034,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; @@ -1054,8 +1054,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 @@ -1064,11 +1065,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 @@ -1105,14 +1106,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. @@ -1128,7 +1129,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; } } @@ -1136,7 +1137,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); @@ -1159,6 +1160,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);