Merge tag 'io_uring-5.8-2020-07-01' of git://git.kernel.dk/linux-block
Pull io_uring fixes from Jens Axboe: "One fix in here, for a regression in 5.7 where a task is waiting in the kernel for a condition, but that condition won't become true until task_work is run. And the task_work can't be run exactly because the task is waiting in the kernel, so we'll never make any progress. One example of that is registering an eventfd and queueing io_uring work, and then the task goes and waits in eventfd read with the expectation that it'll get woken (and read an event) when the io_uring request completes. The io_uring request is finished through task_work, which won't get run while the task is looping in eventfd read" * tag 'io_uring-5.8-2020-07-01' of git://git.kernel.dk/linux-block: io_uring: use signal based task_work running task_work: teach task_work_add() to do signal_wake_up()
This commit is contained in:
@@ -2529,9 +2529,6 @@ bool get_signal(struct ksignal *ksig)
|
||||
struct signal_struct *signal = current->signal;
|
||||
int signr;
|
||||
|
||||
if (unlikely(current->task_works))
|
||||
task_work_run();
|
||||
|
||||
if (unlikely(uprobe_deny_signal()))
|
||||
return false;
|
||||
|
||||
@@ -2544,6 +2541,13 @@ bool get_signal(struct ksignal *ksig)
|
||||
|
||||
relock:
|
||||
spin_lock_irq(&sighand->siglock);
|
||||
current->jobctl &= ~JOBCTL_TASK_WORK;
|
||||
if (unlikely(current->task_works)) {
|
||||
spin_unlock_irq(&sighand->siglock);
|
||||
task_work_run();
|
||||
goto relock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every stopped thread goes here after wakeup. Check to see if
|
||||
* we should notify the parent, prepare_signal(SIGCONT) encodes
|
||||
|
@@ -25,9 +25,10 @@ static struct callback_head work_exited; /* all we need is ->next == NULL */
|
||||
* 0 if succeeds or -ESRCH.
|
||||
*/
|
||||
int
|
||||
task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
|
||||
task_work_add(struct task_struct *task, struct callback_head *work, int notify)
|
||||
{
|
||||
struct callback_head *head;
|
||||
unsigned long flags;
|
||||
|
||||
do {
|
||||
head = READ_ONCE(task->task_works);
|
||||
@@ -36,8 +37,19 @@ task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
|
||||
work->next = head;
|
||||
} while (cmpxchg(&task->task_works, head, work) != head);
|
||||
|
||||
if (notify)
|
||||
switch (notify) {
|
||||
case TWA_RESUME:
|
||||
set_notify_resume(task);
|
||||
break;
|
||||
case TWA_SIGNAL:
|
||||
if (lock_task_sighand(task, &flags)) {
|
||||
task->jobctl |= JOBCTL_TASK_WORK;
|
||||
signal_wake_up(task, 0);
|
||||
unlock_task_sighand(task, &flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user