diff --git a/include/sys/taskq.h b/include/sys/taskq.h index 7a0be048ca..0e78ea1233 100644 --- a/include/sys/taskq.h +++ b/include/sys/taskq.h @@ -81,12 +81,18 @@ typedef struct taskq { wait_queue_head_t tq_wait_waitq; /* wait waitq */ } taskq_t; +/* Global system-wide dynamic task queue available for all consumers */ +extern taskq_t *system_taskq; + extern taskqid_t __taskq_dispatch(taskq_t *, task_func_t, void *, uint_t); extern taskq_t *__taskq_create(const char *, int, pri_t, int, int, uint_t); extern void __taskq_destroy(taskq_t *); extern void __taskq_wait(taskq_t *); extern int __taskq_member(taskq_t *, void *); +int spl_taskq_init(void); +void spl_taskq_fini(void); + #define taskq_member(tq, t) __taskq_member(tq, t) #define taskq_wait_id(tq, id) __taskq_wait_id(tq, id) #define taskq_wait(tq) __taskq_wait(tq) diff --git a/modules/spl/spl-generic.c b/modules/spl/spl-generic.c index 58b5951700..d361bff92b 100644 --- a/modules/spl/spl-generic.c +++ b/modules/spl/spl-generic.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -225,26 +226,31 @@ static int __init spl_init(void) if ((rc = spl_mutex_init())) GOTO(out2 , rc); - if ((rc = vn_init())) + if ((rc = spl_taskq_init())) GOTO(out3, rc); - if ((rc = proc_init())) + if ((rc = vn_init())) GOTO(out4, rc); - if ((rc = kstat_init())) + if ((rc = proc_init())) GOTO(out5, rc); + if ((rc = kstat_init())) + GOTO(out6, rc); + if ((rc = set_hostid())) - GOTO(out6, rc = -EADDRNOTAVAIL); + GOTO(out7, rc = -EADDRNOTAVAIL); printk("SPL: Loaded Solaris Porting Layer v%s\n", VERSION); RETURN(rc); -out6: +out7: kstat_fini(); -out5: +out6: proc_fini(); -out4: +out5: vn_fini(); +out4: + spl_taskq_fini(); out3: spl_mutex_fini(); out2: @@ -265,6 +271,7 @@ static void spl_fini(void) kstat_fini(); proc_fini(); vn_fini(); + spl_taskq_fini(); spl_mutex_fini(); spl_kmem_fini(); debug_fini(); diff --git a/modules/spl/spl-taskq.c b/modules/spl/spl-taskq.c index 3c7f43cda5..dc6959db55 100644 --- a/modules/spl/spl-taskq.c +++ b/modules/spl/spl-taskq.c @@ -33,6 +33,10 @@ #define DEBUG_SUBSYSTEM S_TASKQ +/* Global system-wide dynamic task queue available for all consumers */ +taskq_t *system_taskq; +EXPORT_SYMBOL(system_taskq); + typedef struct spl_task { spinlock_t t_lock; struct list_head t_list; @@ -464,3 +468,24 @@ __taskq_destroy(taskq_t *tq) EXIT; } EXPORT_SYMBOL(__taskq_destroy); + +int +spl_taskq_init(void) +{ + ENTRY; + + system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512, + TASKQ_DYNAMIC | TASKQ_PREPOPULATE); + if (system_taskq == NULL) + RETURN(1); + + RETURN(0); +} + +void +spl_taskq_fini(void) +{ + ENTRY; + taskq_destroy(system_taskq); + EXIT; +} diff --git a/modules/splat/splat-taskq.c b/modules/splat/splat-taskq.c index 4d349f0712..3cc09bcb97 100644 --- a/modules/splat/splat-taskq.c +++ b/modules/splat/splat-taskq.c @@ -38,6 +38,10 @@ #define SPLAT_TASKQ_TEST2_NAME "multiple" #define SPLAT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks" +#define SPLAT_TASKQ_TEST3_ID 0x0203 +#define SPLAT_TASKQ_TEST3_NAME "system" +#define SPLAT_TASKQ_TEST3_DESC "System task queue, multiple tasks" + typedef struct splat_taskq_arg { int flag; int id; @@ -49,14 +53,14 @@ typedef struct splat_taskq_arg { * task completes, ensure task ran properly, cleanup taskq, */ static void -splat_taskq_test1_func(void *arg) +splat_taskq_test13_func(void *arg) { splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; ASSERT(tq_arg); splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' function '%s' setting flag\n", - tq_arg->name, sym2str(splat_taskq_test1_func)); + tq_arg->name, sym2str(splat_taskq_test13_func)); tq_arg->flag = 1; } @@ -84,12 +88,12 @@ 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_test1_func)); - if ((id = taskq_dispatch(tq, splat_taskq_test1_func, + tq_arg.name, sym2str(splat_taskq_test13_func)); + if ((id = taskq_dispatch(tq, splat_taskq_test13_func, &tq_arg, TQ_SLEEP)) == 0) { splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' function '%s' dispatch failed\n", - tq_arg.name, sym2str(splat_taskq_test1_func)); + tq_arg.name, sym2str(splat_taskq_test13_func)); taskq_destroy(tq); return -EINVAL; } @@ -230,6 +234,38 @@ splat_taskq_test2(struct file *file, void *arg) { return rc; } +/* Validation Test 3 - Use the global system task queue with a single + * task, * wait until task completes, ensure task ran properly. + */ +static int +splat_taskq_test3(struct file *file, void *arg) +{ + taskqid_t id; + splat_taskq_arg_t tq_arg; + + tq_arg.flag = 0; + tq_arg.id = 0; + tq_arg.file = file; + 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) { + splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, + "Taskq '%s' function '%s' dispatch failed\n", + tq_arg.name, sym2str(splat_taskq_test13_func)); + return -EINVAL; + } + + splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n", + tq_arg.name); + taskq_wait(system_taskq); + + return (tq_arg.flag) ? 0 : -EINVAL; +} + splat_subsystem_t * splat_taskq_init(void) { @@ -251,6 +287,8 @@ splat_taskq_init(void) SPLAT_TASKQ_TEST1_ID, splat_taskq_test1); SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST2_NAME, SPLAT_TASKQ_TEST2_DESC, SPLAT_TASKQ_TEST2_ID, splat_taskq_test2); + SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST3_NAME, SPLAT_TASKQ_TEST3_DESC, + SPLAT_TASKQ_TEST3_ID, splat_taskq_test3); return sub; } @@ -259,6 +297,7 @@ void splat_taskq_fini(splat_subsystem_t *sub) { ASSERT(sub); + SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST3_ID); SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST2_ID); SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST1_ID);