void zvol_remove_minors(spa_t *spa, const char *name, boolean_t async) { zvol_task_t *task; taskqid_t id; task = zvol_task_alloc(ZVOL_ASYNC_REMOVE_MINORS, name, NULL, ~0ULL); if (task == NULL) return; id = taskq_dispatch(spa->spa_zvol_taskq, zvol_task_cb, task, TQ_SLEEP); if ((async == B_FALSE) && (id != 0)) taskq_wait_id(spa->spa_zvol_taskq, id); }
static int splat_taskq_test7_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskq_ent_t tqe; splat_taskq_arg_t tq_arg; splat_vprint(file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST7_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST7_NAME, 1, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST7_NAME); return -EINVAL; } tq_arg.depth = 0; tq_arg.flag = 0; tq_arg.id = 0; tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST7_NAME; tq_arg.tq = tq; if (prealloc) { taskq_init_ent(&tqe); tq_arg.tqe = &tqe; } else { tq_arg.tqe = NULL; } splat_taskq_test7_func(&tq_arg); if (tq_arg.flag == 0) { splat_vprint(file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' waiting\n", tq_arg.name); taskq_wait_id(tq, SPLAT_TASKQ_DEPTH_MAX); } splat_vprint(file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return tq_arg.depth == SPLAT_TASKQ_DEPTH_MAX ? 0 : -EINVAL; }
static int splat_rwlock_test4_type(taskq_t *tq, rw_priv_t *rwp, int expected_rc, krw_t holder_type, krw_t try_type) { int id, rc = 0; /* Schedule a task function which will try and acquire the rwlock * using type try_type while the rwlock is being held as holder_type. * The result must match expected_rc for the test to pass */ rwp->rw_rc = -EINVAL; rwp->rw_type = try_type; if (holder_type == RW_WRITER || holder_type == RW_READER) rw_enter(&rwp->rw_rwlock, holder_type); id = taskq_dispatch(tq, splat_rwlock_test4_func, rwp, TQ_SLEEP); if (id == 0) { splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME, "%s", "taskq_dispatch() failed\n"); rc = -EINVAL; goto out; } taskq_wait_id(tq, id); if (rwp->rw_rc != expected_rc) rc = -EINVAL; splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME, "%srw_tryenter(%s) returned %d (expected %d) when %s\n", rc ? "Fail " : "", splat_rwlock_test4_name(try_type), rwp->rw_rc, expected_rc, splat_rwlock_test4_name(holder_type)); out: if (holder_type == RW_WRITER || holder_type == RW_READER) rw_exit(&rwp->rw_rwlock); return rc; }
static int splat_taskq_test6_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX]; splat_taskq_arg_t tq_arg; int order[SPLAT_TASKQ_ORDER_MAX] = { 1,2,3,6,7,8,4,5 }; taskq_ent_t tqes[SPLAT_TASKQ_ORDER_MAX]; int i, rc = 0; uint_t tflags; splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST6_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST6_NAME, 3, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST6_NAME); return -EINVAL; } tq_arg.flag = 0; memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX); spin_lock_init(&tq_arg.lock); tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST6_NAME; for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) { taskq_init_ent(&tqes[i]); tq_id[i].id = i + 1; tq_id[i].arg = &tq_arg; tflags = TQ_SLEEP; if (i > 4) tflags |= TQ_FRONT; if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test6_func, &tq_id[i], tflags, &tqes[i]); id = tqes[i].tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test6_func, &tq_id[i], tflags); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test6_func)); rc = -EINVAL; goto out; } if (tq_id[i].id != id) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' expected taskqid %d got %d\n", tq_arg.name, (int)tq_id[i].id, (int)id); rc = -EINVAL; goto out; } /* Sleep to let tasks 1-3 start executing. */ if ( i == 2 ) msleep(100); } splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, SPLAT_TASKQ_ORDER_MAX); taskq_wait_id(tq, SPLAT_TASKQ_ORDER_MAX); rc = splat_taskq_test_order(&tq_arg, order); out: splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return rc; }
static int splat_taskq_test5_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX]; splat_taskq_arg_t tq_arg; int order1[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,0,0,0 }; int order2[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,8,6,7 }; taskq_ent_t tqes[SPLAT_TASKQ_ORDER_MAX]; int i, rc = 0; splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST5_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST5_NAME, 3, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST5_NAME); return -EINVAL; } tq_arg.flag = 0; memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX); spin_lock_init(&tq_arg.lock); tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST5_NAME; for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) { taskq_init_ent(&tqes[i]); tq_id[i].id = i + 1; tq_id[i].arg = &tq_arg; if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test5_func, &tq_id[i], TQ_SLEEP, &tqes[i]); id = tqes[i].tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test5_func, &tq_id[i], TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test5_func)); rc = -EINVAL; goto out; } if (tq_id[i].id != id) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' expected taskqid %d got %d\n", tq_arg.name, (int)tq_id[i].id, (int)id); rc = -EINVAL; goto out; } } splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, 3); taskq_wait_id(tq, 3); if ((rc = splat_taskq_test_order(&tq_arg, order1))) goto out; splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, 8); taskq_wait_id(tq, 8); rc = splat_taskq_test_order(&tq_arg, order2); out: splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return rc; }
static int splat_mutex_test1(struct file *file, void *arg) { mutex_priv_t *mp; taskq_t *tq; int id, rc = 0; mp = (mutex_priv_t *)kmalloc(sizeof(*mp), GFP_KERNEL); if (mp == NULL) return -ENOMEM; tq = taskq_create(SPLAT_MUTEX_TEST_TASKQ, 1, defclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE); if (tq == NULL) { rc = -ENOMEM; goto out2; } mp->mp_magic = SPLAT_MUTEX_TEST_MAGIC; mp->mp_file = file; mutex_init(&mp->mp_mtx, SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL); mutex_enter(&mp->mp_mtx); /* * Schedule a task function which will try and acquire the mutex via * mutex_tryenter() while it's held. This should fail and the task * function will indicate this status in the passed private data. */ mp->mp_rc = -EINVAL; id = taskq_dispatch(tq, splat_mutex_test1_func, mp, TQ_SLEEP); if (id == 0) { mutex_exit(&mp->mp_mtx); splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s", "taskq_dispatch() failed\n"); rc = -EINVAL; goto out; } taskq_wait_id(tq, id); mutex_exit(&mp->mp_mtx); /* Task function successfully acquired mutex, very bad! */ if (mp->mp_rc != -EBUSY) { splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "mutex_trylock() incorrectly succeeded when " "the mutex was held, %d/%d\n", id, mp->mp_rc); rc = -EINVAL; goto out; } else { splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s", "mutex_trylock() correctly failed when " "the mutex was held\n"); } /* * Schedule a task function which will try and acquire the mutex via * mutex_tryenter() while it is not held. This should succeed and * can be verified by checking the private data. */ mp->mp_rc = -EINVAL; id = taskq_dispatch(tq, splat_mutex_test1_func, mp, TQ_SLEEP); if (id == 0) { splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s", "taskq_dispatch() failed\n"); rc = -EINVAL; goto out; } taskq_wait_id(tq, id); /* Task function failed to acquire mutex, very bad! */ if (mp->mp_rc != 0) { splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "mutex_trylock() incorrectly failed when " "the mutex was not held, %d/%d\n", id, mp->mp_rc); rc = -EINVAL; } else { splat_vprint(file, SPLAT_MUTEX_TEST1_NAME, "%s", "mutex_trylock() correctly succeeded " "when the mutex was not held\n"); } out: taskq_destroy(tq); mutex_destroy(&(mp->mp_mtx)); out2: kfree(mp); return rc; }