History

Merge branch 'io_uring-5.8' into for-5.9/io_uring

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()

Jens Axboe committed 6 years ago

Commit 58c6a582 parents 8eb06d7 b7db41c5 files · +65 −13Browse files

Unified · Split

5 files
  1. fs/io_uring.c +37 −6
  2. include/linux/sched/jobctl.h +3 −1
  3. include/linux/task_work.h +4 −1
  4. kernel/signal.c +7 −3
  5. kernel/task_work.c +14 −2
fs/io_uring.c+37−6
@@ -4417,6 +4417,29 @@ struct io_poll_table { · 4416 unmodified lines
4417 int error;4417 int error;
4418};4418};
4419 4419
4420static 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
4420static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,4443static 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 not4463 * 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(&current->sighand->siglock);
6518 current->jobctl &= ~JOBCTL_TASK_WORK;
6519 recalc_sigpending();
6520 spin_unlock_irq(&current->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
include/linux/sched/jobctl.h+3−1
@@ -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
35extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask);37extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask);
36extern void task_clear_jobctl_trapping(struct task_struct *task);38extern void task_clear_jobctl_trapping(struct task_struct *task);
include/linux/task_work.h+4−1
@@ -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
16int task_work_add(struct task_struct *task, struct callback_head *twork, bool);16#define TWA_RESUME 1
17#define TWA_SIGNAL 2
18int task_work_add(struct task_struct *task, struct callback_head *twork, int);
19
17struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);20struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
18void task_work_run(void);21void task_work_run(void);
19 22
kernel/signal.c+7−3
@@ -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
2545relock:2542relock:
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 if2552 * Every stopped thread goes here after wakeup. Check to see if
2549 * we should notify the parent, prepare_signal(SIGCONT) encodes2553 * we should notify the parent, prepare_signal(SIGCONT) encodes
kernel/task_work.c+14−2
@@ -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 */
27int27int
28task_work_add(struct task_struct *task, struct callback_head *work, bool notify)28task_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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t