From 200366f23f1a16874d78a07936c5a33f2d488022 Mon Sep 17 00:00:00 2001 From: Tim Chase Date: Mon, 19 Oct 2015 07:47:52 -0500 Subject: Provide kstat for taskqs This patch provides 2 new kstats to display task queues: /proc/spl/taskqs-all - Display all task queues /proc/spl/taskqs - Display only "active" task queues A task queue is considered to be "active" if it currently has active (running) threads or if any of its pending, priority, delay or waitq lists are not empty. If the task queue has running threads, displays each thread function's address (symbolically, if possibly) and its argument. If the task queue has a non-empty list of pending, priority or delayed task queue entries (taskq_ent_t), displays each entry's thread function address and arguemnt. If the task queue has any waiters, displays each waiting task's pid. Note: This patch also updates some comments in taskq.h which referred to "taskq_t" when they should have referred to "taskq_ent_t". Signed-off-by: Tim Chase Signed-off-by: Brian Behlendorf Closes #491 --- module/spl/spl-taskq.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'module/spl/spl-taskq.c') diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c index 89d68f33c..db5d8fba1 100644 --- a/module/spl/spl-taskq.c +++ b/module/spl/spl-taskq.c @@ -54,6 +54,10 @@ EXPORT_SYMBOL(system_taskq); static taskq_t *dynamic_taskq; static taskq_thread_t *taskq_thread_create(taskq_t *); +/* List of all taskqs */ +LIST_HEAD(tq_list); +DECLARE_RWSEM(tq_list_sem); + static int task_km_flags(uint_t flags) { @@ -66,6 +70,23 @@ task_km_flags(uint_t flags) return (KM_SLEEP); } +/* + * taskq_find_by_name - Find the largest instance number of a named taskq. + */ +static int +taskq_find_by_name(const char *name) +{ + struct list_head *tql; + taskq_t *tq; + + list_for_each_prev(tql, &tq_list) { + tq = list_entry(tql, taskq_t, tq_taskqs); + if (strcmp(name, tq->tq_name) == 0) + return tq->tq_instance; + } + return (-1); +} + /* * NOTE: Must be called with tq->tq_lock held, returns a list_t which * is not attached to the free, work, or pending taskq lists. @@ -1024,6 +1045,7 @@ taskq_create(const char *name, int nthreads, pri_t pri, init_waitqueue_head(&tq->tq_work_waitq); init_waitqueue_head(&tq->tq_wait_waitq); tq->tq_lock_class = TQ_LOCK_GENERAL; + INIT_LIST_HEAD(&tq->tq_taskqs); if (flags & TASKQ_PREPOPULATE) { spin_lock_irqsave_nested(&tq->tq_lock, irqflags, @@ -1053,6 +1075,11 @@ taskq_create(const char *name, int nthreads, pri_t pri, if (rc) { taskq_destroy(tq); tq = NULL; + } else { + down_write(&tq_list_sem); + tq->tq_instance = taskq_find_by_name(name) + 1; + list_add_tail(&tq->tq_taskqs, &tq_list); + up_write(&tq_list_sem); } return (tq); @@ -1081,6 +1108,11 @@ taskq_destroy(taskq_t *tq) taskq_wait(tq); + /* remove taskq from global list used by the kstats */ + down_write(&tq_list_sem); + list_del(&tq->tq_taskqs); + up_write(&tq_list_sem); + spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class); /* -- cgit v1.2.3