Pull in task_work changes from the 5.8 series, as we'll need to apply the same kind of changes to other parts in the 5.9 branch. * io_uring-5.8: io_uring: fix regression with always ignoring signals in io_cqring_wait() io_uring: use signal based task_work running task_work: teach task_work_add() to do signal_wake_up()
Unified · Split
| @@ -4417,6 +4417,29 @@ struct io_poll_table { · 4416 unmodified lines | |||
| 4417 | int error; | 4417 | int error; |
| 4418 | }; | 4418 | }; |
| 4419 | 4419 | ||
| 4420 | static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb) | ||
| 4421 | { | ||
| 4422 | struct task_struct *tsk = req->task; | ||
| 4423 | struct io_ring_ctx *ctx = req->ctx; | ||
| 4424 | int ret, notify = TWA_RESUME; | ||
| 4425 | |||
| 4426 | /* | ||
| 4427 | * SQPOLL kernel thread doesn't need notification, just a wakeup. | ||
| 4428 | * If we're not using an eventfd, then TWA_RESUME is always fine, | ||
| 4429 | * as we won't have dependencies between request completions for | ||
| 4430 | * other kernel wait conditions. | ||
| 4431 | */ | ||
| 4432 | if (ctx->flags & IORING_SETUP_SQPOLL) | ||
| 4433 | notify = 0; | ||
| 4434 | else if (ctx->cq_ev_fd) | ||
| 4435 | notify = TWA_SIGNAL; | ||
| 4436 | |||
| 4437 | ret = task_work_add(tsk, cb, notify); | ||
| 4438 | if (!ret) | ||
| 4439 | wake_up_process(tsk); | ||
| 4440 | return ret; | ||
| 4441 | } | ||
| 4442 | |||
| 4420 | static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll, | 4443 | static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll, |
| 4421 | __poll_t mask, task_work_func_t func) | 4444 | __poll_t mask, task_work_func_t func) |
| 4422 | { | 4445 | { |
| @@ -4440,13 +4463,13 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll, · 17 unmodified lines | |||
| 4440 | * of executing it. We can't safely execute it anyway, as we may not | 4463 | * of executing it. We can't safely execute it anyway, as we may not |
| 4441 | * have the needed state needed for it anyway. | 4464 | * have the needed state needed for it anyway. |
| 4442 | */ | 4465 | */ |
| 4443 | ret = task_work_add(tsk, &req->task_work, true); | 4466 | ret = io_req_task_work_add(req, &req->task_work); |
| 4444 | if (unlikely(ret)) { | 4467 | if (unlikely(ret)) { |
| 4445 | WRITE_ONCE(poll->canceled, true); | 4468 | WRITE_ONCE(poll->canceled, true); |
| 4446 | tsk = io_wq_get_task(req->ctx->io_wq); | 4469 | tsk = io_wq_get_task(req->ctx->io_wq); |
| 4447 | task_work_add(tsk, &req->task_work, true); | 4470 | task_work_add(tsk, &req->task_work, 0); |
| 4471 | wake_up_process(tsk); | ||
| 4448 | } | 4472 | } |
| 4449 | wake_up_process(tsk); | ||
| 4450 | return 1; | 4473 | return 1; |
| 4451 | } | 4474 | } |
| 4452 | 4475 | ||
| @@ -6486,15 +6509,23 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 2033 unmodified lines | |||
| 6486 | do { | 6509 | do { |
| 6487 | prepare_to_wait_exclusive(&ctx->wait, &iowq.wq, | 6510 | prepare_to_wait_exclusive(&ctx->wait, &iowq.wq, |
| 6488 | TASK_INTERRUPTIBLE); | 6511 | TASK_INTERRUPTIBLE); |
| 6512 | /* make sure we run task_work before checking for signals */ | ||
| 6489 | if (current->task_works) | 6513 | if (current->task_works) |
| 6490 | task_work_run(); | 6514 | task_work_run(); |
| 6491 | if (io_should_wake(&iowq, false)) | ||
| 6492 | break; | ||
| 6493 | schedule(); | ||
| 6494 | if (signal_pending(current)) { | 6515 | if (signal_pending(current)) { |
| 6516 | if (current->jobctl & JOBCTL_TASK_WORK) { | ||
| 6517 | spin_lock_irq(¤t->sighand->siglock); | ||
| 6518 | current->jobctl &= ~JOBCTL_TASK_WORK; | ||
| 6519 | recalc_sigpending(); | ||
| 6520 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 6521 | continue; | ||
| 6522 | } | ||
| 6495 | ret = -EINTR; | 6523 | ret = -EINTR; |
| 6496 | break; | 6524 | break; |
| 6497 | } | 6525 | } |
| 6526 | if (io_should_wake(&iowq, false)) | ||
| 6527 | break; | ||
| 6528 | schedule(); | ||
| 6498 | } while (1); | 6529 | } while (1); |
| 6499 | finish_wait(&ctx->wait, &iowq.wq); | 6530 | finish_wait(&ctx->wait, &iowq.wq); |
| 6500 | 6531 | ||
| @@ -19,6 +19,7 @@ struct task_struct; · 18 unmodified lines | |||
| 19 | #define JOBCTL_TRAPPING_BIT 21 /* switching to TRACED */ | 19 | #define JOBCTL_TRAPPING_BIT 21 /* switching to TRACED */ |
| 20 | #define JOBCTL_LISTENING_BIT 22 /* ptracer is listening for events */ | 20 | #define JOBCTL_LISTENING_BIT 22 /* ptracer is listening for events */ |
| 21 | #define JOBCTL_TRAP_FREEZE_BIT 23 /* trap for cgroup freezer */ | 21 | #define JOBCTL_TRAP_FREEZE_BIT 23 /* trap for cgroup freezer */ |
| 22 | #define JOBCTL_TASK_WORK_BIT 24 /* set by TWA_SIGNAL */ | ||
| 22 | 23 | ||
| 23 | #define JOBCTL_STOP_DEQUEUED (1UL << JOBCTL_STOP_DEQUEUED_BIT) | 24 | #define JOBCTL_STOP_DEQUEUED (1UL << JOBCTL_STOP_DEQUEUED_BIT) |
| 24 | #define JOBCTL_STOP_PENDING (1UL << JOBCTL_STOP_PENDING_BIT) | 25 | #define JOBCTL_STOP_PENDING (1UL << JOBCTL_STOP_PENDING_BIT) |
| @@ -28,9 +29,10 @@ struct task_struct; · 3 unmodified lines | |||
| 28 | #define JOBCTL_TRAPPING (1UL << JOBCTL_TRAPPING_BIT) | 29 | #define JOBCTL_TRAPPING (1UL << JOBCTL_TRAPPING_BIT) |
| 29 | #define JOBCTL_LISTENING (1UL << JOBCTL_LISTENING_BIT) | 30 | #define JOBCTL_LISTENING (1UL << JOBCTL_LISTENING_BIT) |
| 30 | #define JOBCTL_TRAP_FREEZE (1UL << JOBCTL_TRAP_FREEZE_BIT) | 31 | #define JOBCTL_TRAP_FREEZE (1UL << JOBCTL_TRAP_FREEZE_BIT) |
| 32 | #define JOBCTL_TASK_WORK (1UL << JOBCTL_TASK_WORK_BIT) | ||
| 31 | 33 | ||
| 32 | #define JOBCTL_TRAP_MASK (JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY) | 34 | #define JOBCTL_TRAP_MASK (JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY) |
| 33 | #define JOBCTL_PENDING_MASK (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK) | 35 | #define JOBCTL_PENDING_MASK (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK | JOBCTL_TASK_WORK) |
| 34 | 36 | ||
| 35 | extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask); | 37 | extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask); |
| 36 | extern void task_clear_jobctl_trapping(struct task_struct *task); | 38 | extern void task_clear_jobctl_trapping(struct task_struct *task); |
| @@ -13,7 +13,10 @@ init_task_work(struct callback_head *twork, task_work_func_t func) · 12 unmodified lines | |||
| 13 | twork->func = func; | 13 | twork->func = func; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | int task_work_add(struct task_struct *task, struct callback_head *twork, bool); | 16 | #define TWA_RESUME 1 |
| 17 | #define TWA_SIGNAL 2 | ||
| 18 | int task_work_add(struct task_struct *task, struct callback_head *twork, int); | ||
| 19 | |||
| 17 | struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t); | 20 | struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t); |
| 18 | void task_work_run(void); | 21 | void task_work_run(void); |
| 19 | 22 | ||
| @@ -2529,9 +2529,6 @@ bool get_signal(struct ksignal *ksig) · 2528 unmodified lines | |||
| 2529 | struct signal_struct *signal = current->signal; | 2529 | struct signal_struct *signal = current->signal; |
| 2530 | int signr; | 2530 | int signr; |
| 2531 | 2531 | ||
| 2532 | if (unlikely(current->task_works)) | ||
| 2533 | task_work_run(); | ||
| 2534 | |||
| 2535 | if (unlikely(uprobe_deny_signal())) | 2532 | if (unlikely(uprobe_deny_signal())) |
| 2536 | return false; | 2533 | return false; |
| 2537 | 2534 | ||
| @@ -2544,6 +2541,13 @@ bool get_signal(struct ksignal *ksig) · 6 unmodified lines | |||
| 2544 | 2541 | ||
| 2545 | relock: | 2542 | relock: |
| 2546 | spin_lock_irq(&sighand->siglock); | 2543 | spin_lock_irq(&sighand->siglock); |
| 2544 | current->jobctl &= ~JOBCTL_TASK_WORK; | ||
| 2545 | if (unlikely(current->task_works)) { | ||
| 2546 | spin_unlock_irq(&sighand->siglock); | ||
| 2547 | task_work_run(); | ||
| 2548 | goto relock; | ||
| 2549 | } | ||
| 2550 | |||
| 2547 | /* | 2551 | /* |
| 2548 | * Every stopped thread goes here after wakeup. Check to see if | 2552 | * Every stopped thread goes here after wakeup. Check to see if |
| 2549 | * we should notify the parent, prepare_signal(SIGCONT) encodes | 2553 | * 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 */ · 24 unmodified lines | |||
| 25 | * 0 if succeeds or -ESRCH. | 25 | * 0 if succeeds or -ESRCH. |
| 26 | */ | 26 | */ |
| 27 | int | 27 | int |
| 28 | task_work_add(struct task_struct *task, struct callback_head *work, bool notify) | 28 | task_work_add(struct task_struct *task, struct callback_head *work, int notify) |
| 29 | { | 29 | { |
| 30 | struct callback_head *head; | 30 | struct callback_head *head; |
| 31 | unsigned long flags; | ||
| 31 | 32 | ||
| 32 | do { | 33 | do { |
| 33 | head = READ_ONCE(task->task_works); | 34 | head = READ_ONCE(task->task_works); |
| @@ -36,8 +37,19 @@ task_work_add(struct task_struct *task, struct callback_head *work, bool notify) · 2 unmodified lines | |||
| 36 | work->next = head; | 37 | work->next = head; |
| 37 | } while (cmpxchg(&task->task_works, head, work) != head); | 38 | } while (cmpxchg(&task->task_works, head, work) != head); |
| 38 | 39 | ||
| 39 | if (notify) | 40 | switch (notify) { |
| 41 | case TWA_RESUME: | ||
| 40 | set_notify_resume(task); | 42 | set_notify_resume(task); |
| 43 | break; | ||
| 44 | case TWA_SIGNAL: | ||
| 45 | if (lock_task_sighand(task, &flags)) { | ||
| 46 | task->jobctl |= JOBCTL_TASK_WORK; | ||
| 47 | signal_wake_up(task, 0); | ||
| 48 | unlock_task_sighand(task, &flags); | ||
| 49 | } | ||
| 50 | break; | ||
| 51 | } | ||
| 52 | |||
| 41 | return 0; | 53 | return 0; |
| 42 | } | 54 | } |
| 43 | 55 | ||