Skip to content
This repository has been archived by the owner on Feb 26, 2020. It is now read-only.

Commit

Permalink
Revert "Taskq locking optimizations"
Browse files Browse the repository at this point in the history
This reverts commit ec2b410.

A race condition was introduced by which a wake_up() call can be lost
after the taskq thread determines there is no pending work items,
leading to deadlock:

1. taksq thread enables interrupts
2. dispatcher thread runs, queues work item, call wake_up()
3. taskq thread runs, adds self to waitq, sleeps

This could easily happen if an interrupt for an IO completion was
outstanding at the point where the taskq thread reenables interrupts,
just before the call to add_wait_queue_exclusive().  The handler would
run immediately within the race window.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #32
  • Loading branch information
nedbass authored and behlendorf committed Jan 19, 2012
1 parent 87d1123 commit 0bb43ca
Showing 1 changed file with 5 additions and 7 deletions.
12 changes: 5 additions & 7 deletions module/spl/spl-taskq.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,10 @@ __taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
ASSERT(!(t->tqent_flags & TQENT_FLAG_PREALLOC));

spin_unlock(&t->tqent_lock);

wake_up(&tq->tq_work_waitq);
out:
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
if (rc > 0)
wake_up(&tq->tq_work_waitq);

SRETURN(rc);
}
EXPORT_SYMBOL(__taskq_dispatch);
Expand All @@ -310,7 +309,6 @@ __taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
/* Taskq being destroyed and all tasks drained */
if (!(tq->tq_flags & TQ_ACTIVE)) {
t->tqent_id = 0;
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
goto out;
}

Expand All @@ -334,10 +332,10 @@ __taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
t->tqent_arg = arg;

spin_unlock(&t->tqent_lock);
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);

wake_up(&tq->tq_work_waitq);
out:
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
SEXIT;
}
EXPORT_SYMBOL(__taskq_dispatch_ent);
Expand Down Expand Up @@ -456,17 +454,17 @@ taskq_thread(void *args)

while (!kthread_should_stop()) {

add_wait_queue(&tq->tq_work_waitq, &wait);
if (list_empty(&tq->tq_pend_list) &&
list_empty(&tq->tq_prio_list)) {
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
add_wait_queue_exclusive(&tq->tq_work_waitq, &wait);
schedule();
remove_wait_queue(&tq->tq_work_waitq, &wait);
spin_lock_irqsave(&tq->tq_lock, tq->tq_lock_flags);
} else {
__set_current_state(TASK_RUNNING);
}

remove_wait_queue(&tq->tq_work_waitq, &wait);

if (!list_empty(&tq->tq_prio_list))
pend_list = &tq->tq_prio_list;
Expand Down

0 comments on commit 0bb43ca

Please sign in to comment.