]> git.proxmox.com Git - mirror_spl.git/commitdiff
Allow spawning a new thread for TQ_NOQUEUE dispatch with dynamic taskq
authorTim Chase <tim@onlight.com>
Mon, 8 Feb 2016 19:20:05 +0000 (13:20 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 17 Mar 2016 16:52:35 +0000 (09:52 -0700)
When a TQ_NOQUEUE dispatch is done on a dynamic taskq, allow another
thread to be spawned.  This will cause TQ_NOQUEUE to behave similarly
as it does with non-dynamic taskqs.

Add support for TQ_NOQUEUE to taskq_dispatch_ent().

Signed-off-by: Tim Chase <tim@onlight.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #530

module/spl/spl-taskq.c

index 56034c89947a17b0e94ad1159cb95970e32a868f..bfcf651af693b0b16eb7c15b5443e946f1db4a2e 100644 (file)
@@ -562,16 +562,22 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
 
        /* Do not queue the task unless there is idle thread for it */
        ASSERT(tq->tq_nactive <= tq->tq_nthreads);
-       if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads))
-               goto out;
+       if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) {
+               /* Dynamic taskq may be able to spawn another thread */
+               if (!(tq->tq_flags & TASKQ_DYNAMIC) || taskq_thread_spawn(tq) == 0)
+                       goto out;
+       }
 
        if ((t = task_alloc(tq, flags, &irqflags)) == NULL)
                goto out;
 
        spin_lock(&t->tqent_lock);
 
+       /* Queue to the front of the list to enforce TQ_NOQUEUE semantics */
+       if (flags & TQ_NOQUEUE)
+               list_add(&t->tqent_list, &tq->tq_prio_list);
        /* Queue to the priority list instead of the pending list */
-       if (flags & TQ_FRONT)
+       else if (flags & TQ_FRONT)
                list_add_tail(&t->tqent_list, &tq->tq_prio_list);
        else
                list_add_tail(&t->tqent_list, &tq->tq_pend_list);
@@ -593,7 +599,7 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
        wake_up(&tq->tq_work_waitq);
 out:
        /* Spawn additional taskq threads if required. */
-       if (tq->tq_nactive == tq->tq_nthreads)
+       if (!(flags & TQ_NOQUEUE) && tq->tq_nactive == tq->tq_nthreads)
                (void) taskq_thread_spawn(tq);
 
        spin_unlock_irqrestore(&tq->tq_lock, irqflags);
@@ -665,6 +671,13 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
                goto out;
        }
 
+       if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) {
+               /* Dynamic taskq may be able to spawn another thread */
+               if (!(tq->tq_flags & TASKQ_DYNAMIC) || taskq_thread_spawn(tq) == 0)
+                       goto out2;
+               flags |= TQ_FRONT;
+       }
+
        spin_lock(&t->tqent_lock);
 
        /*
@@ -693,6 +706,7 @@ out:
        /* Spawn additional taskq threads if required. */
        if (tq->tq_nactive == tq->tq_nthreads)
                (void) taskq_thread_spawn(tq);
+out2:
        spin_unlock_irqrestore(&tq->tq_lock, irqflags);
 }
 EXPORT_SYMBOL(taskq_dispatch_ent);