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
44174417 int error;
44184418 };
44194419
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+
44204443 static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
44214444 __poll_t mask, task_work_func_t func)
44224445 {
@@ -4440,13 +4463,13 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll, · 17 unmodified lines
44404463 * of executing it. We can't safely execute it anyway, as we may not
44414464 * have the needed state needed for it anyway.
44424465 */
4443− ret = task_work_add(tsk, &req->task_work, true);
4466+ ret = io_req_task_work_add(req, &req->task_work);
44444467 if (unlikely(ret)) {
44454468 WRITE_ONCE(poll->canceled, true);
44464469 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);
44484472 }
4449− wake_up_process(tsk);
44504473 return 1;
44514474 }
44524475
@@ -6486,15 +6509,23 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 2033 unmodified lines
64866509 do {
64876510 prepare_to_wait_exclusive(&ctx->wait, &iowq.wq,
64886511 TASK_INTERRUPTIBLE);
6512+ /* make sure we run task_work before checking for signals */
64896513 if (current->task_works)
64906514 task_work_run();
6491− if (io_should_wake(&iowq, false))
6492− break;
6493− schedule();
64946515 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+ }
64956523 ret = -EINTR;
64966524 break;
64976525 }
6526+ if (io_should_wake(&iowq, false))
6527+ break;
6528+ schedule();
64986529 } while (1);
64996530 finish_wait(&ctx->wait, &iowq.wq);
65006531
include/linux/sched/jobctl.h+3−1
@@ -19,6 +19,7 @@ struct task_struct; · 18 unmodified lines
1919 #define JOBCTL_TRAPPING_BIT 21 /* switching to TRACED */
2020 #define JOBCTL_LISTENING_BIT 22 /* ptracer is listening for events */
2121 #define JOBCTL_TRAP_FREEZE_BIT 23 /* trap for cgroup freezer */
22+#define JOBCTL_TASK_WORK_BIT 24 /* set by TWA_SIGNAL */
2223
2324 #define JOBCTL_STOP_DEQUEUED (1UL << JOBCTL_STOP_DEQUEUED_BIT)
2425 #define JOBCTL_STOP_PENDING (1UL << JOBCTL_STOP_PENDING_BIT)
@@ -28,9 +29,10 @@ struct task_struct; · 3 unmodified lines
2829 #define JOBCTL_TRAPPING (1UL << JOBCTL_TRAPPING_BIT)
2930 #define JOBCTL_LISTENING (1UL << JOBCTL_LISTENING_BIT)
3031 #define JOBCTL_TRAP_FREEZE (1UL << JOBCTL_TRAP_FREEZE_BIT)
32+#define JOBCTL_TASK_WORK (1UL << JOBCTL_TASK_WORK_BIT)
3133
3234 #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)
3436
3537 extern bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask);
3638 extern 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
1313 twork->func = func;
1414 }
1515
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+
1720 struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
1821 void task_work_run(void);
1922
kernel/signal.c+7−3
@@ -2529,9 +2529,6 @@ bool get_signal(struct ksignal *ksig) · 2528 unmodified lines
25292529 struct signal_struct *signal = current->signal;
25302530 int signr;
25312531
2532− if (unlikely(current->task_works))
2533− task_work_run();
2534−
25352532 if (unlikely(uprobe_deny_signal()))
25362533 return false;
25372534
@@ -2544,6 +2541,13 @@ bool get_signal(struct ksignal *ksig) · 6 unmodified lines
25442541
25452542 relock:
25462543 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+
25472551 /*
25482552 * Every stopped thread goes here after wakeup. Check to see if
25492553 * 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
2525 * 0 if succeeds or -ESRCH.
2626 */
2727 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)
2929 {
3030 struct callback_head *head;
31+ unsigned long flags;
3132
3233 do {
3334 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
3637 work->next = head;
3738 } while (cmpxchg(&task->task_works, head, work) != head);
3839
39− if (notify)
40+ switch (notify) {
41+ case TWA_RESUME:
4042 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+
4153 return 0;
4254 }
4355

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