mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Revert "Taskq locking optimizations"
This reverts commit ec2b41049f
.
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
This commit is contained in:
parent
87d1123924
commit
0bb43ca282
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user