Exercise new taskq interface in splat-taskq tests

The splat-taskq test functions were slightly modified to exercise
the new taskq interface in addition to the old interface.  If the
old interface passes each of its tests, the new interface is
exercised.  Both sub tests (old interface and new interface) must
pass for each test as a whole to pass.

Signed-off-by: Prakash Surya <surya1@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #65
This commit is contained in:
Prakash Surya 2011-12-06 10:11:36 -08:00 committed by Brian Behlendorf
parent 44217f7aad
commit 699d5ee8a9

View File

@ -67,6 +67,7 @@ typedef struct splat_taskq_arg {
int order[SPLAT_TASKQ_ORDER_MAX];
unsigned int depth;
taskq_t *tq;
taskq_ent_t *tqe;
spinlock_t lock;
struct file *file;
const char *name;
@ -94,14 +95,19 @@ splat_taskq_test13_func(void *arg)
}
static int
splat_taskq_test1(struct file *file, void *arg)
splat_taskq_test1_impl(struct file *file, void *arg, boolean_t prealloc)
{
taskq_t *tq;
taskqid_t id;
splat_taskq_arg_t tq_arg;
taskq_ent_t tqe;
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' creating\n",
SPLAT_TASKQ_TEST1_NAME);
taskq_init_ent(&tqe);
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' creating (%s dispatch)\n",
SPLAT_TASKQ_TEST1_NAME,
prealloc ? "prealloc" : "dynamic");
if ((tq = taskq_create(SPLAT_TASKQ_TEST1_NAME, 1, maxclsyspri,
50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) {
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
@ -118,11 +124,19 @@ splat_taskq_test1(struct file *file, void *arg)
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' function '%s' dispatching\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
if ((id = taskq_dispatch(tq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP)) == 0) {
if (prealloc) {
taskq_dispatch_ent(tq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP, &tqe);
id = tqe.tqent_id;
} else {
id = taskq_dispatch(tq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP);
}
if (id == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME,
"Taskq '%s' function '%s' dispatch failed\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
"Taskq '%s' function '%s' dispatch failed\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
taskq_destroy(tq);
return -EINVAL;
}
@ -132,11 +146,26 @@ splat_taskq_test1(struct file *file, void *arg)
taskq_wait(tq);
splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' destroying\n",
tq_arg.name);
taskq_destroy(tq);
return (tq_arg.flag) ? 0 : -EINVAL;
}
static int
splat_taskq_test1(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test1_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test1_impl(file, arg, B_TRUE);
return rc;
}
/*
* Create multiple taskq's, each with multiple tasks, wait until
* all tasks complete, ensure all tasks ran properly and in the
@ -175,16 +204,34 @@ splat_taskq_test2_func2(void *arg)
#define TEST2_THREADS_PER_TASKQ 1
static int
splat_taskq_test2(struct file *file, void *arg) {
splat_taskq_test2_impl(struct file *file, void *arg, boolean_t prealloc) {
taskq_t *tq[TEST2_TASKQS] = { NULL };
taskqid_t id;
splat_taskq_arg_t tq_args[TEST2_TASKQS];
taskq_ent_t *func1_tqes = NULL;
taskq_ent_t *func2_tqes = NULL;
int i, rc = 0;
for (i = 0; i < TEST2_TASKQS; i++) {
func1_tqes = kmalloc(sizeof(*func1_tqes) * TEST2_TASKQS, GFP_KERNEL);
if (func1_tqes == NULL) {
rc = -ENOMEM;
goto out;
}
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' "
"creating\n", SPLAT_TASKQ_TEST2_NAME, i);
func2_tqes = kmalloc(sizeof(*func2_tqes) * TEST2_TASKQS, GFP_KERNEL);
if (func2_tqes == NULL) {
rc = -ENOMEM;
goto out;
}
for (i = 0; i < TEST2_TASKQS; i++) {
taskq_init_ent(&func1_tqes[i]);
taskq_init_ent(&func2_tqes[i]);
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
"Taskq '%s/%d' creating (%s dispatch)\n",
SPLAT_TASKQ_TEST2_NAME, i,
prealloc ? "prealloc" : "dynamic");
if ((tq[i] = taskq_create(SPLAT_TASKQ_TEST2_NAME,
TEST2_THREADS_PER_TASKQ,
maxclsyspri, 50, INT_MAX,
@ -205,9 +252,16 @@ splat_taskq_test2(struct file *file, void *arg) {
"Taskq '%s/%d' function '%s' dispatching\n",
tq_args[i].name, tq_args[i].id,
sym2str(splat_taskq_test2_func1));
if ((id = taskq_dispatch(
tq[i], splat_taskq_test2_func1,
&tq_args[i], TQ_SLEEP)) == 0) {
if (prealloc) {
taskq_dispatch_ent(tq[i], splat_taskq_test2_func1,
&tq_args[i], TQ_SLEEP, &func1_tqes[i]);
id = func1_tqes[i].tqent_id;
} else {
id = taskq_dispatch(tq[i], splat_taskq_test2_func1,
&tq_args[i], TQ_SLEEP);
}
if (id == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
"Taskq '%s/%d' function '%s' dispatch "
"failed\n", tq_args[i].name, tq_args[i].id,
@ -220,13 +274,20 @@ splat_taskq_test2(struct file *file, void *arg) {
"Taskq '%s/%d' function '%s' dispatching\n",
tq_args[i].name, tq_args[i].id,
sym2str(splat_taskq_test2_func2));
if ((id = taskq_dispatch(
tq[i], splat_taskq_test2_func2,
&tq_args[i], TQ_SLEEP)) == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
"Taskq '%s/%d' function '%s' dispatch failed\n",
tq_args[i].name, tq_args[i].id,
sym2str(splat_taskq_test2_func2));
if (prealloc) {
taskq_dispatch_ent(tq[i], splat_taskq_test2_func2,
&tq_args[i], TQ_SLEEP, &func2_tqes[i]);
id = func2_tqes[i].tqent_id;
} else {
id = taskq_dispatch(tq[i], splat_taskq_test2_func2,
&tq_args[i], TQ_SLEEP);
}
if (id == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq "
"'%s/%d' function '%s' dispatch failed\n",
tq_args[i].name, tq_args[i].id,
sym2str(splat_taskq_test2_func2));
rc = -EINVAL;
break;
}
@ -243,6 +304,7 @@ splat_taskq_test2(struct file *file, void *arg) {
splat_vprint(file, SPLAT_TASKQ_TEST2_NAME,
"Taskq '%s/%d; destroying\n",
tq_args[i].name, tq_args[i].id);
taskq_destroy(tq[i]);
if (!rc && tq_args[i].flag != ((i * 2) + 1)) {
@ -261,6 +323,25 @@ splat_taskq_test2(struct file *file, void *arg) {
}
}
}
out:
if (func1_tqes)
kfree(func1_tqes);
if (func2_tqes)
kfree(func2_tqes);
return rc;
}
static int
splat_taskq_test2(struct file *file, void *arg) {
int rc;
rc = splat_taskq_test2_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test2_impl(file, arg, B_TRUE);
return rc;
}
@ -270,10 +351,13 @@ splat_taskq_test2(struct file *file, void *arg) {
* completes, ensure task ran properly.
*/
static int
splat_taskq_test3(struct file *file, void *arg)
splat_taskq_test3_impl(struct file *file, void *arg, boolean_t prealloc)
{
taskqid_t id;
splat_taskq_arg_t tq_arg;
taskq_ent_t tqe;
taskq_init_ent(&tqe);
tq_arg.flag = 0;
tq_arg.id = 0;
@ -281,10 +365,19 @@ splat_taskq_test3(struct file *file, void *arg)
tq_arg.name = SPLAT_TASKQ_TEST3_NAME;
splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
"Taskq '%s' function '%s' dispatching\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
if ((id = taskq_dispatch(system_taskq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP)) == 0) {
"Taskq '%s' function '%s' %s dispatch\n",
tq_arg.name, sym2str(splat_taskq_test13_func),
prealloc ? "prealloc" : "dynamic");
if (prealloc) {
taskq_dispatch_ent(system_taskq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP, &tqe);
id = tqe.tqent_id;
} else {
id = taskq_dispatch(system_taskq, splat_taskq_test13_func,
&tq_arg, TQ_SLEEP);
}
if (id == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST3_NAME,
"Taskq '%s' function '%s' dispatch failed\n",
tq_arg.name, sym2str(splat_taskq_test13_func));
@ -298,6 +391,20 @@ splat_taskq_test3(struct file *file, void *arg)
return (tq_arg.flag) ? 0 : -EINVAL;
}
static int
splat_taskq_test3(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test3_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test3_impl(file, arg, B_TRUE);
return rc;
}
/*
* Create a taskq and dispatch a large number of tasks to the queue.
* Then use taskq_wait() to block until all the tasks complete, then
@ -319,21 +426,30 @@ splat_taskq_test4_func(void *arg)
static int
splat_taskq_test4_common(struct file *file, void *arg, int minalloc,
int maxalloc, int nr_tasks)
int maxalloc, int nr_tasks, boolean_t prealloc)
{
taskq_t *tq;
taskqid_t id;
splat_taskq_arg_t tq_arg;
taskq_ent_t *tqes;
int i, j, rc = 0;
splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' creating "
"(%d/%d/%d)\n", SPLAT_TASKQ_TEST4_NAME, minalloc, maxalloc,
nr_tasks);
tqes = kmalloc(sizeof(*tqes) * nr_tasks, GFP_KERNEL);
if (tqes == NULL)
return -ENOMEM;
splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
"Taskq '%s' creating (%s dispatch) (%d/%d/%d)\n",
SPLAT_TASKQ_TEST4_NAME,
prealloc ? "prealloc" : "dynamic",
minalloc, maxalloc, nr_tasks);
if ((tq = taskq_create(SPLAT_TASKQ_TEST4_NAME, 1, maxclsyspri,
minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) {
splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
"Taskq '%s' create failed\n",
SPLAT_TASKQ_TEST4_NAME);
return -EINVAL;
rc = -EINVAL;
goto out_free;
}
tq_arg.file = file;
@ -346,8 +462,18 @@ splat_taskq_test4_common(struct file *file, void *arg, int minalloc,
tq_arg.name, sym2str(splat_taskq_test4_func), i);
for (j = 0; j < i; j++) {
if ((taskq_dispatch(tq, splat_taskq_test4_func,
&tq_arg, TQ_SLEEP)) == 0) {
taskq_init_ent(&tqes[j]);
if (prealloc) {
taskq_dispatch_ent(tq, splat_taskq_test4_func,
&tq_arg, TQ_SLEEP, &tqes[j]);
id = tqes[j].tqent_id;
} else {
id = taskq_dispatch(tq, splat_taskq_test4_func,
&tq_arg, TQ_SLEEP);
}
if (id == 0) {
splat_vprint(file, SPLAT_TASKQ_TEST4_NAME,
"Taskq '%s' function '%s' dispatch "
"%d failed\n", tq_arg.name,
@ -374,18 +500,36 @@ out:
tq_arg.name);
taskq_destroy(tq);
out_free:
kfree(tqes);
return rc;
}
static int splat_taskq_test4(struct file *file, void *arg)
static int
splat_taskq_test4_impl(struct file *file, void *arg, boolean_t prealloc)
{
int rc;
rc = splat_taskq_test4_common(file, arg, 50, INT_MAX, 1024);
rc = splat_taskq_test4_common(file, arg, 50, INT_MAX, 1024, prealloc);
if (rc)
return rc;
rc = splat_taskq_test4_common(file, arg, 1, 1, 32);
rc = splat_taskq_test4_common(file, arg, 1, 1, 32, prealloc);
return rc;
}
static int
splat_taskq_test4(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test4_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test4_impl(file, arg, B_TRUE);
return rc;
}
@ -498,7 +642,7 @@ splat_taskq_test_order(splat_taskq_arg_t *tq_arg, int *order)
}
static int
splat_taskq_test5(struct file *file, void *arg)
splat_taskq_test5_impl(struct file *file, void *arg, boolean_t prealloc)
{
taskq_t *tq;
taskqid_t id;
@ -506,10 +650,13 @@ splat_taskq_test5(struct file *file, void *arg)
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\n",
SPLAT_TASKQ_TEST5_NAME);
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,
@ -525,11 +672,21 @@ splat_taskq_test5(struct file *file, void *arg)
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 ((id = taskq_dispatch(tq, splat_taskq_test5_func,
&tq_id[i], TQ_SLEEP)) == 0) {
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));
@ -565,6 +722,20 @@ out:
return rc;
}
static int
splat_taskq_test5(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test5_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test5_impl(file, arg, B_TRUE);
return rc;
}
/*
* Create a single task queue with three threads. Dispatch 8 tasks,
* setting TQ_FRONT on only the last three. Sleep after
@ -624,18 +795,21 @@ splat_taskq_test6_func(void *arg)
}
static int
splat_taskq_test6(struct file *file, void *arg)
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\n",
SPLAT_TASKQ_TEST6_NAME);
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,
@ -651,14 +825,24 @@ splat_taskq_test6(struct file *file, void *arg)
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 ((id = taskq_dispatch(tq, splat_taskq_test6_func,
&tq_id[i], tflags)) == 0) {
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));
@ -692,6 +876,20 @@ out:
return rc;
}
static int
splat_taskq_test6(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test6_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test6_impl(file, arg, B_TRUE);
return rc;
}
static void
splat_taskq_test7_func(void *arg)
{
@ -710,8 +908,17 @@ splat_taskq_test7_func(void *arg)
tq_arg->name, sym2str(splat_taskq_test7_func),
tq_arg->depth);
if ((id = taskq_dispatch(tq_arg->tq, splat_taskq_test7_func,
tq_arg, TQ_SLEEP)) == 0) {
if (tq_arg->tqe) {
VERIFY(taskq_empty_ent(tq_arg->tqe));
taskq_dispatch_ent(tq_arg->tq, splat_taskq_test7_func,
tq_arg, TQ_SLEEP, tq_arg->tqe);
id = tq_arg->tqe->tqent_id;
} else {
id = taskq_dispatch(tq_arg->tq, splat_taskq_test7_func,
tq_arg, TQ_SLEEP);
}
if (id == 0) {
splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST7_NAME,
"Taskq '%s' function '%s' dispatch failed "
"(depth = %u)\n", tq_arg->name,
@ -722,13 +929,16 @@ splat_taskq_test7_func(void *arg)
}
static int
splat_taskq_test7(struct file *file, void *arg)
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\n", 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,
@ -744,6 +954,13 @@ splat_taskq_test7(struct file *file, void *arg)
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) {
@ -759,6 +976,20 @@ splat_taskq_test7(struct file *file, void *arg)
return tq_arg.depth == SPLAT_TASKQ_DEPTH_MAX ? 0 : -EINVAL;
}
static int
splat_taskq_test7(struct file *file, void *arg)
{
int rc;
rc = splat_taskq_test7_impl(file, arg, B_FALSE);
if (rc)
return rc;
rc = splat_taskq_test7_impl(file, arg, B_TRUE);
return rc;
}
splat_subsystem_t *
splat_taskq_init(void)
{