diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/auditfilter.c | 3 | ||||
| -rw-r--r-- | kernel/cpu/idle.c | 2 | ||||
| -rw-r--r-- | kernel/events/core.c | 240 | ||||
| -rw-r--r-- | kernel/kmod.c | 5 | ||||
| -rw-r--r-- | kernel/module.c | 21 | ||||
| -rw-r--r-- | kernel/rcutree_plugin.h | 4 | ||||
| -rw-r--r-- | kernel/time/Kconfig | 5 | ||||
| -rw-r--r-- | kernel/time/tick-broadcast.c | 10 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 3 | ||||
| -rw-r--r-- | kernel/timer.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_events.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 53 | ||||
| -rw-r--r-- | kernel/workqueue.c | 19 |
14 files changed, 172 insertions, 203 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 83a2970295d1..6bd4a90d1991 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -1021,9 +1021,6 @@ static void audit_log_rule_change(char *action, struct audit_krule *rule, int re | |||
| 1021 | * @seq: netlink audit message sequence (serial) number | 1021 | * @seq: netlink audit message sequence (serial) number |
| 1022 | * @data: payload data | 1022 | * @data: payload data |
| 1023 | * @datasz: size of payload data | 1023 | * @datasz: size of payload data |
| 1024 | * @loginuid: loginuid of sender | ||
| 1025 | * @sessionid: sessionid for netlink audit message | ||
| 1026 | * @sid: SE Linux Security ID of sender | ||
| 1027 | */ | 1024 | */ |
| 1028 | int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) | 1025 | int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) |
| 1029 | { | 1026 | { |
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index 8b86c0c68edf..d5585f5e038e 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c | |||
| @@ -40,11 +40,13 @@ __setup("hlt", cpu_idle_nopoll_setup); | |||
| 40 | 40 | ||
| 41 | static inline int cpu_idle_poll(void) | 41 | static inline int cpu_idle_poll(void) |
| 42 | { | 42 | { |
| 43 | rcu_idle_enter(); | ||
| 43 | trace_cpu_idle_rcuidle(0, smp_processor_id()); | 44 | trace_cpu_idle_rcuidle(0, smp_processor_id()); |
| 44 | local_irq_enable(); | 45 | local_irq_enable(); |
| 45 | while (!need_resched()) | 46 | while (!need_resched()) |
| 46 | cpu_relax(); | 47 | cpu_relax(); |
| 47 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | 48 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); |
| 49 | rcu_idle_exit(); | ||
| 48 | return 1; | 50 | return 1; |
| 49 | } | 51 | } |
| 50 | 52 | ||
diff --git a/kernel/events/core.c b/kernel/events/core.c index 6b41c1899a8b..9dc297faf7c0 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -4394,6 +4394,64 @@ perf_event_read_event(struct perf_event *event, | |||
| 4394 | perf_output_end(&handle); | 4394 | perf_output_end(&handle); |
| 4395 | } | 4395 | } |
| 4396 | 4396 | ||
| 4397 | typedef int (perf_event_aux_match_cb)(struct perf_event *event, void *data); | ||
| 4398 | typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data); | ||
| 4399 | |||
| 4400 | static void | ||
| 4401 | perf_event_aux_ctx(struct perf_event_context *ctx, | ||
| 4402 | perf_event_aux_match_cb match, | ||
| 4403 | perf_event_aux_output_cb output, | ||
| 4404 | void *data) | ||
| 4405 | { | ||
| 4406 | struct perf_event *event; | ||
| 4407 | |||
| 4408 | list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { | ||
| 4409 | if (event->state < PERF_EVENT_STATE_INACTIVE) | ||
| 4410 | continue; | ||
| 4411 | if (!event_filter_match(event)) | ||
| 4412 | continue; | ||
| 4413 | if (match(event, data)) | ||
| 4414 | output(event, data); | ||
| 4415 | } | ||
| 4416 | } | ||
| 4417 | |||
| 4418 | static void | ||
| 4419 | perf_event_aux(perf_event_aux_match_cb match, | ||
| 4420 | perf_event_aux_output_cb output, | ||
| 4421 | void *data, | ||
| 4422 | struct perf_event_context *task_ctx) | ||
| 4423 | { | ||
| 4424 | struct perf_cpu_context *cpuctx; | ||
| 4425 | struct perf_event_context *ctx; | ||
| 4426 | struct pmu *pmu; | ||
| 4427 | int ctxn; | ||
| 4428 | |||
| 4429 | rcu_read_lock(); | ||
| 4430 | list_for_each_entry_rcu(pmu, &pmus, entry) { | ||
| 4431 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4432 | if (cpuctx->unique_pmu != pmu) | ||
| 4433 | goto next; | ||
| 4434 | perf_event_aux_ctx(&cpuctx->ctx, match, output, data); | ||
| 4435 | if (task_ctx) | ||
| 4436 | goto next; | ||
| 4437 | ctxn = pmu->task_ctx_nr; | ||
| 4438 | if (ctxn < 0) | ||
| 4439 | goto next; | ||
| 4440 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | ||
| 4441 | if (ctx) | ||
| 4442 | perf_event_aux_ctx(ctx, match, output, data); | ||
| 4443 | next: | ||
| 4444 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4445 | } | ||
| 4446 | |||
| 4447 | if (task_ctx) { | ||
| 4448 | preempt_disable(); | ||
| 4449 | perf_event_aux_ctx(task_ctx, match, output, data); | ||
| 4450 | preempt_enable(); | ||
| 4451 | } | ||
| 4452 | rcu_read_unlock(); | ||
| 4453 | } | ||
| 4454 | |||
| 4397 | /* | 4455 | /* |
| 4398 | * task tracking -- fork/exit | 4456 | * task tracking -- fork/exit |
| 4399 | * | 4457 | * |
| @@ -4416,8 +4474,9 @@ struct perf_task_event { | |||
| 4416 | }; | 4474 | }; |
| 4417 | 4475 | ||
| 4418 | static void perf_event_task_output(struct perf_event *event, | 4476 | static void perf_event_task_output(struct perf_event *event, |
| 4419 | struct perf_task_event *task_event) | 4477 | void *data) |
| 4420 | { | 4478 | { |
| 4479 | struct perf_task_event *task_event = data; | ||
| 4421 | struct perf_output_handle handle; | 4480 | struct perf_output_handle handle; |
| 4422 | struct perf_sample_data sample; | 4481 | struct perf_sample_data sample; |
| 4423 | struct task_struct *task = task_event->task; | 4482 | struct task_struct *task = task_event->task; |
| @@ -4445,62 +4504,11 @@ out: | |||
| 4445 | task_event->event_id.header.size = size; | 4504 | task_event->event_id.header.size = size; |
| 4446 | } | 4505 | } |
| 4447 | 4506 | ||
| 4448 | static int perf_event_task_match(struct perf_event *event) | 4507 | static int perf_event_task_match(struct perf_event *event, |
| 4449 | { | 4508 | void *data __maybe_unused) |
| 4450 | if (event->state < PERF_EVENT_STATE_INACTIVE) | ||
| 4451 | return 0; | ||
| 4452 | |||
| 4453 | if (!event_filter_match(event)) | ||
| 4454 | return 0; | ||
| 4455 | |||
| 4456 | if (event->attr.comm || event->attr.mmap || | ||
| 4457 | event->attr.mmap_data || event->attr.task) | ||
| 4458 | return 1; | ||
| 4459 | |||
| 4460 | return 0; | ||
| 4461 | } | ||
| 4462 | |||
| 4463 | static void perf_event_task_ctx(struct perf_event_context *ctx, | ||
| 4464 | struct perf_task_event *task_event) | ||
| 4465 | { | 4509 | { |
| 4466 | struct perf_event *event; | 4510 | return event->attr.comm || event->attr.mmap || |
| 4467 | 4511 | event->attr.mmap_data || event->attr.task; | |
| 4468 | list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { | ||
| 4469 | if (perf_event_task_match(event)) | ||
| 4470 | perf_event_task_output(event, task_event); | ||
| 4471 | } | ||
| 4472 | } | ||
| 4473 | |||
| 4474 | static void perf_event_task_event(struct perf_task_event *task_event) | ||
| 4475 | { | ||
| 4476 | struct perf_cpu_context *cpuctx; | ||
| 4477 | struct perf_event_context *ctx; | ||
| 4478 | struct pmu *pmu; | ||
| 4479 | int ctxn; | ||
| 4480 | |||
| 4481 | rcu_read_lock(); | ||
| 4482 | list_for_each_entry_rcu(pmu, &pmus, entry) { | ||
| 4483 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4484 | if (cpuctx->unique_pmu != pmu) | ||
| 4485 | goto next; | ||
| 4486 | perf_event_task_ctx(&cpuctx->ctx, task_event); | ||
| 4487 | |||
| 4488 | ctx = task_event->task_ctx; | ||
| 4489 | if (!ctx) { | ||
| 4490 | ctxn = pmu->task_ctx_nr; | ||
| 4491 | if (ctxn < 0) | ||
| 4492 | goto next; | ||
| 4493 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | ||
| 4494 | if (ctx) | ||
| 4495 | perf_event_task_ctx(ctx, task_event); | ||
| 4496 | } | ||
| 4497 | next: | ||
| 4498 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4499 | } | ||
| 4500 | if (task_event->task_ctx) | ||
| 4501 | perf_event_task_ctx(task_event->task_ctx, task_event); | ||
| 4502 | |||
| 4503 | rcu_read_unlock(); | ||
| 4504 | } | 4512 | } |
| 4505 | 4513 | ||
| 4506 | static void perf_event_task(struct task_struct *task, | 4514 | static void perf_event_task(struct task_struct *task, |
| @@ -4531,7 +4539,10 @@ static void perf_event_task(struct task_struct *task, | |||
| 4531 | }, | 4539 | }, |
| 4532 | }; | 4540 | }; |
| 4533 | 4541 | ||
| 4534 | perf_event_task_event(&task_event); | 4542 | perf_event_aux(perf_event_task_match, |
| 4543 | perf_event_task_output, | ||
| 4544 | &task_event, | ||
| 4545 | task_ctx); | ||
| 4535 | } | 4546 | } |
| 4536 | 4547 | ||
| 4537 | void perf_event_fork(struct task_struct *task) | 4548 | void perf_event_fork(struct task_struct *task) |
| @@ -4557,8 +4568,9 @@ struct perf_comm_event { | |||
| 4557 | }; | 4568 | }; |
| 4558 | 4569 | ||
| 4559 | static void perf_event_comm_output(struct perf_event *event, | 4570 | static void perf_event_comm_output(struct perf_event *event, |
| 4560 | struct perf_comm_event *comm_event) | 4571 | void *data) |
| 4561 | { | 4572 | { |
| 4573 | struct perf_comm_event *comm_event = data; | ||
| 4562 | struct perf_output_handle handle; | 4574 | struct perf_output_handle handle; |
| 4563 | struct perf_sample_data sample; | 4575 | struct perf_sample_data sample; |
| 4564 | int size = comm_event->event_id.header.size; | 4576 | int size = comm_event->event_id.header.size; |
| @@ -4585,39 +4597,16 @@ out: | |||
| 4585 | comm_event->event_id.header.size = size; | 4597 | comm_event->event_id.header.size = size; |
| 4586 | } | 4598 | } |
| 4587 | 4599 | ||
| 4588 | static int perf_event_comm_match(struct perf_event *event) | 4600 | static int perf_event_comm_match(struct perf_event *event, |
| 4589 | { | 4601 | void *data __maybe_unused) |
| 4590 | if (event->state < PERF_EVENT_STATE_INACTIVE) | ||
| 4591 | return 0; | ||
| 4592 | |||
| 4593 | if (!event_filter_match(event)) | ||
| 4594 | return 0; | ||
| 4595 | |||
| 4596 | if (event->attr.comm) | ||
| 4597 | return 1; | ||
| 4598 | |||
| 4599 | return 0; | ||
| 4600 | } | ||
| 4601 | |||
| 4602 | static void perf_event_comm_ctx(struct perf_event_context *ctx, | ||
| 4603 | struct perf_comm_event *comm_event) | ||
| 4604 | { | 4602 | { |
| 4605 | struct perf_event *event; | 4603 | return event->attr.comm; |
| 4606 | |||
| 4607 | list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { | ||
| 4608 | if (perf_event_comm_match(event)) | ||
| 4609 | perf_event_comm_output(event, comm_event); | ||
| 4610 | } | ||
| 4611 | } | 4604 | } |
| 4612 | 4605 | ||
| 4613 | static void perf_event_comm_event(struct perf_comm_event *comm_event) | 4606 | static void perf_event_comm_event(struct perf_comm_event *comm_event) |
| 4614 | { | 4607 | { |
| 4615 | struct perf_cpu_context *cpuctx; | ||
| 4616 | struct perf_event_context *ctx; | ||
| 4617 | char comm[TASK_COMM_LEN]; | 4608 | char comm[TASK_COMM_LEN]; |
| 4618 | unsigned int size; | 4609 | unsigned int size; |
| 4619 | struct pmu *pmu; | ||
| 4620 | int ctxn; | ||
| 4621 | 4610 | ||
| 4622 | memset(comm, 0, sizeof(comm)); | 4611 | memset(comm, 0, sizeof(comm)); |
| 4623 | strlcpy(comm, comm_event->task->comm, sizeof(comm)); | 4612 | strlcpy(comm, comm_event->task->comm, sizeof(comm)); |
| @@ -4627,24 +4616,11 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
| 4627 | comm_event->comm_size = size; | 4616 | comm_event->comm_size = size; |
| 4628 | 4617 | ||
| 4629 | comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; | 4618 | comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; |
| 4630 | rcu_read_lock(); | ||
| 4631 | list_for_each_entry_rcu(pmu, &pmus, entry) { | ||
| 4632 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4633 | if (cpuctx->unique_pmu != pmu) | ||
| 4634 | goto next; | ||
| 4635 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | ||
| 4636 | 4619 | ||
| 4637 | ctxn = pmu->task_ctx_nr; | 4620 | perf_event_aux(perf_event_comm_match, |
| 4638 | if (ctxn < 0) | 4621 | perf_event_comm_output, |
| 4639 | goto next; | 4622 | comm_event, |
| 4640 | 4623 | NULL); | |
| 4641 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | ||
| 4642 | if (ctx) | ||
| 4643 | perf_event_comm_ctx(ctx, comm_event); | ||
| 4644 | next: | ||
| 4645 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4646 | } | ||
| 4647 | rcu_read_unlock(); | ||
| 4648 | } | 4624 | } |
| 4649 | 4625 | ||
| 4650 | void perf_event_comm(struct task_struct *task) | 4626 | void perf_event_comm(struct task_struct *task) |
| @@ -4706,8 +4682,9 @@ struct perf_mmap_event { | |||
| 4706 | }; | 4682 | }; |
| 4707 | 4683 | ||
| 4708 | static void perf_event_mmap_output(struct perf_event *event, | 4684 | static void perf_event_mmap_output(struct perf_event *event, |
| 4709 | struct perf_mmap_event *mmap_event) | 4685 | void *data) |
| 4710 | { | 4686 | { |
| 4687 | struct perf_mmap_event *mmap_event = data; | ||
| 4711 | struct perf_output_handle handle; | 4688 | struct perf_output_handle handle; |
| 4712 | struct perf_sample_data sample; | 4689 | struct perf_sample_data sample; |
| 4713 | int size = mmap_event->event_id.header.size; | 4690 | int size = mmap_event->event_id.header.size; |
| @@ -4734,46 +4711,24 @@ out: | |||
| 4734 | } | 4711 | } |
| 4735 | 4712 | ||
| 4736 | static int perf_event_mmap_match(struct perf_event *event, | 4713 | static int perf_event_mmap_match(struct perf_event *event, |
| 4737 | struct perf_mmap_event *mmap_event, | 4714 | void *data) |
| 4738 | int executable) | ||
| 4739 | { | ||
| 4740 | if (event->state < PERF_EVENT_STATE_INACTIVE) | ||
| 4741 | return 0; | ||
| 4742 | |||
| 4743 | if (!event_filter_match(event)) | ||
| 4744 | return 0; | ||
| 4745 | |||
| 4746 | if ((!executable && event->attr.mmap_data) || | ||
| 4747 | (executable && event->attr.mmap)) | ||
| 4748 | return 1; | ||
| 4749 | |||
| 4750 | return 0; | ||
| 4751 | } | ||
| 4752 | |||
| 4753 | static void perf_event_mmap_ctx(struct perf_event_context *ctx, | ||
| 4754 | struct perf_mmap_event *mmap_event, | ||
| 4755 | int executable) | ||
| 4756 | { | 4715 | { |
| 4757 | struct perf_event *event; | 4716 | struct perf_mmap_event *mmap_event = data; |
| 4717 | struct vm_area_struct *vma = mmap_event->vma; | ||
| 4718 | int executable = vma->vm_flags & VM_EXEC; | ||
| 4758 | 4719 | ||
| 4759 | list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { | 4720 | return (!executable && event->attr.mmap_data) || |
| 4760 | if (perf_event_mmap_match(event, mmap_event, executable)) | 4721 | (executable && event->attr.mmap); |
| 4761 | perf_event_mmap_output(event, mmap_event); | ||
| 4762 | } | ||
| 4763 | } | 4722 | } |
| 4764 | 4723 | ||
| 4765 | static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) | 4724 | static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) |
| 4766 | { | 4725 | { |
| 4767 | struct perf_cpu_context *cpuctx; | ||
| 4768 | struct perf_event_context *ctx; | ||
| 4769 | struct vm_area_struct *vma = mmap_event->vma; | 4726 | struct vm_area_struct *vma = mmap_event->vma; |
| 4770 | struct file *file = vma->vm_file; | 4727 | struct file *file = vma->vm_file; |
| 4771 | unsigned int size; | 4728 | unsigned int size; |
| 4772 | char tmp[16]; | 4729 | char tmp[16]; |
| 4773 | char *buf = NULL; | 4730 | char *buf = NULL; |
| 4774 | const char *name; | 4731 | const char *name; |
| 4775 | struct pmu *pmu; | ||
| 4776 | int ctxn; | ||
| 4777 | 4732 | ||
| 4778 | memset(tmp, 0, sizeof(tmp)); | 4733 | memset(tmp, 0, sizeof(tmp)); |
| 4779 | 4734 | ||
| @@ -4829,27 +4784,10 @@ got_name: | |||
| 4829 | 4784 | ||
| 4830 | mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; | 4785 | mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; |
| 4831 | 4786 | ||
| 4832 | rcu_read_lock(); | 4787 | perf_event_aux(perf_event_mmap_match, |
| 4833 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4788 | perf_event_mmap_output, |
| 4834 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 4789 | mmap_event, |
| 4835 | if (cpuctx->unique_pmu != pmu) | 4790 | NULL); |
| 4836 | goto next; | ||
| 4837 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, | ||
| 4838 | vma->vm_flags & VM_EXEC); | ||
| 4839 | |||
| 4840 | ctxn = pmu->task_ctx_nr; | ||
| 4841 | if (ctxn < 0) | ||
| 4842 | goto next; | ||
| 4843 | |||
| 4844 | ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); | ||
| 4845 | if (ctx) { | ||
| 4846 | perf_event_mmap_ctx(ctx, mmap_event, | ||
| 4847 | vma->vm_flags & VM_EXEC); | ||
| 4848 | } | ||
| 4849 | next: | ||
| 4850 | put_cpu_ptr(pmu->pmu_cpu_context); | ||
| 4851 | } | ||
| 4852 | rcu_read_unlock(); | ||
| 4853 | 4791 | ||
| 4854 | kfree(buf); | 4792 | kfree(buf); |
| 4855 | } | 4793 | } |
diff --git a/kernel/kmod.c b/kernel/kmod.c index 1296e72e4161..8241906c4b61 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
| @@ -569,6 +569,11 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) | |||
| 569 | int retval = 0; | 569 | int retval = 0; |
| 570 | 570 | ||
| 571 | helper_lock(); | 571 | helper_lock(); |
| 572 | if (!sub_info->path) { | ||
| 573 | retval = -EINVAL; | ||
| 574 | goto out; | ||
| 575 | } | ||
| 576 | |||
| 572 | if (sub_info->path[0] == '\0') | 577 | if (sub_info->path[0] == '\0') |
| 573 | goto out; | 578 | goto out; |
| 574 | 579 | ||
diff --git a/kernel/module.c b/kernel/module.c index b049939177f6..cab4bce49c23 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -2431,10 +2431,10 @@ static void kmemleak_load_module(const struct module *mod, | |||
| 2431 | kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); | 2431 | kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); |
| 2432 | 2432 | ||
| 2433 | for (i = 1; i < info->hdr->e_shnum; i++) { | 2433 | for (i = 1; i < info->hdr->e_shnum; i++) { |
| 2434 | const char *name = info->secstrings + info->sechdrs[i].sh_name; | 2434 | /* Scan all writable sections that's not executable */ |
| 2435 | if (!(info->sechdrs[i].sh_flags & SHF_ALLOC)) | 2435 | if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) || |
| 2436 | continue; | 2436 | !(info->sechdrs[i].sh_flags & SHF_WRITE) || |
| 2437 | if (!strstarts(name, ".data") && !strstarts(name, ".bss")) | 2437 | (info->sechdrs[i].sh_flags & SHF_EXECINSTR)) |
| 2438 | continue; | 2438 | continue; |
| 2439 | 2439 | ||
| 2440 | kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, | 2440 | kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, |
| @@ -2769,24 +2769,11 @@ static void find_module_sections(struct module *mod, struct load_info *info) | |||
| 2769 | mod->trace_events = section_objs(info, "_ftrace_events", | 2769 | mod->trace_events = section_objs(info, "_ftrace_events", |
| 2770 | sizeof(*mod->trace_events), | 2770 | sizeof(*mod->trace_events), |
| 2771 | &mod->num_trace_events); | 2771 | &mod->num_trace_events); |
| 2772 | /* | ||
| 2773 | * This section contains pointers to allocated objects in the trace | ||
| 2774 | * code and not scanning it leads to false positives. | ||
| 2775 | */ | ||
| 2776 | kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) * | ||
| 2777 | mod->num_trace_events, GFP_KERNEL); | ||
| 2778 | #endif | 2772 | #endif |
| 2779 | #ifdef CONFIG_TRACING | 2773 | #ifdef CONFIG_TRACING |
| 2780 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", | 2774 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", |
| 2781 | sizeof(*mod->trace_bprintk_fmt_start), | 2775 | sizeof(*mod->trace_bprintk_fmt_start), |
| 2782 | &mod->num_trace_bprintk_fmt); | 2776 | &mod->num_trace_bprintk_fmt); |
| 2783 | /* | ||
| 2784 | * This section contains pointers to allocated objects in the trace | ||
| 2785 | * code and not scanning it leads to false positives. | ||
| 2786 | */ | ||
| 2787 | kmemleak_scan_area(mod->trace_bprintk_fmt_start, | ||
| 2788 | sizeof(*mod->trace_bprintk_fmt_start) * | ||
| 2789 | mod->num_trace_bprintk_fmt, GFP_KERNEL); | ||
| 2790 | #endif | 2777 | #endif |
| 2791 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD | 2778 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD |
| 2792 | /* sechdrs[0].sh_size is always zero */ | 2779 | /* sechdrs[0].sh_size is always zero */ |
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 170814dc418f..3db5a375d8dd 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
| @@ -88,7 +88,7 @@ static void __init rcu_bootup_announce_oddness(void) | |||
| 88 | #ifdef CONFIG_RCU_NOCB_CPU | 88 | #ifdef CONFIG_RCU_NOCB_CPU |
| 89 | #ifndef CONFIG_RCU_NOCB_CPU_NONE | 89 | #ifndef CONFIG_RCU_NOCB_CPU_NONE |
| 90 | if (!have_rcu_nocb_mask) { | 90 | if (!have_rcu_nocb_mask) { |
| 91 | alloc_bootmem_cpumask_var(&rcu_nocb_mask); | 91 | zalloc_cpumask_var(&rcu_nocb_mask, GFP_KERNEL); |
| 92 | have_rcu_nocb_mask = true; | 92 | have_rcu_nocb_mask = true; |
| 93 | } | 93 | } |
| 94 | #ifdef CONFIG_RCU_NOCB_CPU_ZERO | 94 | #ifdef CONFIG_RCU_NOCB_CPU_ZERO |
| @@ -1667,7 +1667,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj) | |||
| 1667 | rdtp->last_accelerate = jiffies; | 1667 | rdtp->last_accelerate = jiffies; |
| 1668 | 1668 | ||
| 1669 | /* Request timer delay depending on laziness, and round. */ | 1669 | /* Request timer delay depending on laziness, and round. */ |
| 1670 | if (rdtp->all_lazy) { | 1670 | if (!rdtp->all_lazy) { |
| 1671 | *dj = round_up(rcu_idle_gp_delay + jiffies, | 1671 | *dj = round_up(rcu_idle_gp_delay + jiffies, |
| 1672 | rcu_idle_gp_delay) - jiffies; | 1672 | rcu_idle_gp_delay) - jiffies; |
| 1673 | } else { | 1673 | } else { |
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index e4c07b0692bb..70f27e89012b 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig | |||
| @@ -12,11 +12,6 @@ config CLOCKSOURCE_WATCHDOG | |||
| 12 | config ARCH_CLOCKSOURCE_DATA | 12 | config ARCH_CLOCKSOURCE_DATA |
| 13 | bool | 13 | bool |
| 14 | 14 | ||
| 15 | # Platforms has a persistent clock | ||
| 16 | config ALWAYS_USE_PERSISTENT_CLOCK | ||
| 17 | bool | ||
| 18 | default n | ||
| 19 | |||
| 20 | # Timekeeping vsyscall support | 15 | # Timekeeping vsyscall support |
| 21 | config GENERIC_TIME_VSYSCALL | 16 | config GENERIC_TIME_VSYSCALL |
| 22 | bool | 17 | bool |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 206bbfb34e09..24938d577669 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
| @@ -786,11 +786,11 @@ bool tick_broadcast_oneshot_available(void) | |||
| 786 | 786 | ||
| 787 | void __init tick_broadcast_init(void) | 787 | void __init tick_broadcast_init(void) |
| 788 | { | 788 | { |
| 789 | alloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT); | 789 | zalloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT); |
| 790 | alloc_cpumask_var(&tmpmask, GFP_NOWAIT); | 790 | zalloc_cpumask_var(&tmpmask, GFP_NOWAIT); |
| 791 | #ifdef CONFIG_TICK_ONESHOT | 791 | #ifdef CONFIG_TICK_ONESHOT |
| 792 | alloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT); | 792 | zalloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT); |
| 793 | alloc_cpumask_var(&tick_broadcast_pending_mask, GFP_NOWAIT); | 793 | zalloc_cpumask_var(&tick_broadcast_pending_mask, GFP_NOWAIT); |
| 794 | alloc_cpumask_var(&tick_broadcast_force_mask, GFP_NOWAIT); | 794 | zalloc_cpumask_var(&tick_broadcast_force_mask, GFP_NOWAIT); |
| 795 | #endif | 795 | #endif |
| 796 | } | 796 | } |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index bc67d4245e1d..f4208138fbf4 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -717,6 +717,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts) | |||
| 717 | if (unlikely(!cpu_online(cpu))) { | 717 | if (unlikely(!cpu_online(cpu))) { |
| 718 | if (cpu == tick_do_timer_cpu) | 718 | if (cpu == tick_do_timer_cpu) |
| 719 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; | 719 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; |
| 720 | return false; | ||
| 720 | } | 721 | } |
| 721 | 722 | ||
| 722 | if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) | 723 | if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) |
| @@ -1168,7 +1169,7 @@ void tick_cancel_sched_timer(int cpu) | |||
| 1168 | hrtimer_cancel(&ts->sched_timer); | 1169 | hrtimer_cancel(&ts->sched_timer); |
| 1169 | # endif | 1170 | # endif |
| 1170 | 1171 | ||
| 1171 | ts->nohz_mode = NOHZ_MODE_INACTIVE; | 1172 | memset(ts, 0, sizeof(*ts)); |
| 1172 | } | 1173 | } |
| 1173 | #endif | 1174 | #endif |
| 1174 | 1175 | ||
diff --git a/kernel/timer.c b/kernel/timer.c index a860bba34412..15ffdb3f1948 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -1539,12 +1539,12 @@ static int __cpuinit init_timers_cpu(int cpu) | |||
| 1539 | boot_done = 1; | 1539 | boot_done = 1; |
| 1540 | base = &boot_tvec_bases; | 1540 | base = &boot_tvec_bases; |
| 1541 | } | 1541 | } |
| 1542 | spin_lock_init(&base->lock); | ||
| 1542 | tvec_base_done[cpu] = 1; | 1543 | tvec_base_done[cpu] = 1; |
| 1543 | } else { | 1544 | } else { |
| 1544 | base = per_cpu(tvec_bases, cpu); | 1545 | base = per_cpu(tvec_bases, cpu); |
| 1545 | } | 1546 | } |
| 1546 | 1547 | ||
| 1547 | spin_lock_init(&base->lock); | ||
| 1548 | 1548 | ||
| 1549 | for (j = 0; j < TVN_SIZE; j++) { | 1549 | for (j = 0; j < TVN_SIZE; j++) { |
| 1550 | INIT_LIST_HEAD(base->tv5.vec + j); | 1550 | INIT_LIST_HEAD(base->tv5.vec + j); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 7a0cf68027cc..27963e2bf4bf 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -2072,8 +2072,10 @@ event_enable_func(struct ftrace_hash *hash, | |||
| 2072 | out_reg: | 2072 | out_reg: |
| 2073 | /* Don't let event modules unload while probe registered */ | 2073 | /* Don't let event modules unload while probe registered */ |
| 2074 | ret = try_module_get(file->event_call->mod); | 2074 | ret = try_module_get(file->event_call->mod); |
| 2075 | if (!ret) | 2075 | if (!ret) { |
| 2076 | ret = -EBUSY; | ||
| 2076 | goto out_free; | 2077 | goto out_free; |
| 2078 | } | ||
| 2077 | 2079 | ||
| 2078 | ret = __ftrace_event_enable_disable(file, 1, 1); | 2080 | ret = __ftrace_event_enable_disable(file, 1, 1); |
| 2079 | if (ret < 0) | 2081 | if (ret < 0) |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index a6361178de5a..e1b653f7e1ca 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
| @@ -750,7 +750,11 @@ static int filter_set_pred(struct event_filter *filter, | |||
| 750 | 750 | ||
| 751 | static void __free_preds(struct event_filter *filter) | 751 | static void __free_preds(struct event_filter *filter) |
| 752 | { | 752 | { |
| 753 | int i; | ||
| 754 | |||
| 753 | if (filter->preds) { | 755 | if (filter->preds) { |
| 756 | for (i = 0; i < filter->n_preds; i++) | ||
| 757 | kfree(filter->preds[i].ops); | ||
| 754 | kfree(filter->preds); | 758 | kfree(filter->preds); |
| 755 | filter->preds = NULL; | 759 | filter->preds = NULL; |
| 756 | } | 760 | } |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 636d45fe69b3..9f46e98ba8f2 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -35,7 +35,7 @@ struct trace_probe { | |||
| 35 | const char *symbol; /* symbol name */ | 35 | const char *symbol; /* symbol name */ |
| 36 | struct ftrace_event_class class; | 36 | struct ftrace_event_class class; |
| 37 | struct ftrace_event_call call; | 37 | struct ftrace_event_call call; |
| 38 | struct ftrace_event_file **files; | 38 | struct ftrace_event_file * __rcu *files; |
| 39 | ssize_t size; /* trace entry size */ | 39 | ssize_t size; /* trace entry size */ |
| 40 | unsigned int nr_args; | 40 | unsigned int nr_args; |
| 41 | struct probe_arg args[]; | 41 | struct probe_arg args[]; |
| @@ -185,9 +185,14 @@ static struct trace_probe *find_trace_probe(const char *event, | |||
| 185 | 185 | ||
| 186 | static int trace_probe_nr_files(struct trace_probe *tp) | 186 | static int trace_probe_nr_files(struct trace_probe *tp) |
| 187 | { | 187 | { |
| 188 | struct ftrace_event_file **file = tp->files; | 188 | struct ftrace_event_file **file; |
| 189 | int ret = 0; | 189 | int ret = 0; |
| 190 | 190 | ||
| 191 | /* | ||
| 192 | * Since all tp->files updater is protected by probe_enable_lock, | ||
| 193 | * we don't need to lock an rcu_read_lock. | ||
| 194 | */ | ||
| 195 | file = rcu_dereference_raw(tp->files); | ||
| 191 | if (file) | 196 | if (file) |
| 192 | while (*(file++)) | 197 | while (*(file++)) |
| 193 | ret++; | 198 | ret++; |
| @@ -209,9 +214,10 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 209 | mutex_lock(&probe_enable_lock); | 214 | mutex_lock(&probe_enable_lock); |
| 210 | 215 | ||
| 211 | if (file) { | 216 | if (file) { |
| 212 | struct ftrace_event_file **new, **old = tp->files; | 217 | struct ftrace_event_file **new, **old; |
| 213 | int n = trace_probe_nr_files(tp); | 218 | int n = trace_probe_nr_files(tp); |
| 214 | 219 | ||
| 220 | old = rcu_dereference_raw(tp->files); | ||
| 215 | /* 1 is for new one and 1 is for stopper */ | 221 | /* 1 is for new one and 1 is for stopper */ |
| 216 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), | 222 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), |
| 217 | GFP_KERNEL); | 223 | GFP_KERNEL); |
| @@ -251,11 +257,17 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 251 | static int | 257 | static int |
| 252 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) | 258 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) |
| 253 | { | 259 | { |
| 260 | struct ftrace_event_file **files; | ||
| 254 | int i; | 261 | int i; |
| 255 | 262 | ||
| 256 | if (tp->files) { | 263 | /* |
| 257 | for (i = 0; tp->files[i]; i++) | 264 | * Since all tp->files updater is protected by probe_enable_lock, |
| 258 | if (tp->files[i] == file) | 265 | * we don't need to lock an rcu_read_lock. |
| 266 | */ | ||
| 267 | files = rcu_dereference_raw(tp->files); | ||
| 268 | if (files) { | ||
| 269 | for (i = 0; files[i]; i++) | ||
| 270 | if (files[i] == file) | ||
| 259 | return i; | 271 | return i; |
| 260 | } | 272 | } |
| 261 | 273 | ||
| @@ -274,10 +286,11 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 274 | mutex_lock(&probe_enable_lock); | 286 | mutex_lock(&probe_enable_lock); |
| 275 | 287 | ||
| 276 | if (file) { | 288 | if (file) { |
| 277 | struct ftrace_event_file **new, **old = tp->files; | 289 | struct ftrace_event_file **new, **old; |
| 278 | int n = trace_probe_nr_files(tp); | 290 | int n = trace_probe_nr_files(tp); |
| 279 | int i, j; | 291 | int i, j; |
| 280 | 292 | ||
| 293 | old = rcu_dereference_raw(tp->files); | ||
| 281 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { | 294 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { |
| 282 | ret = -EINVAL; | 295 | ret = -EINVAL; |
| 283 | goto out_unlock; | 296 | goto out_unlock; |
| @@ -872,9 +885,16 @@ __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, | |||
| 872 | static __kprobes void | 885 | static __kprobes void |
| 873 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) | 886 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) |
| 874 | { | 887 | { |
| 875 | struct ftrace_event_file **file = tp->files; | 888 | /* |
| 889 | * Note: preempt is already disabled around the kprobe handler. | ||
| 890 | * However, we still need an smp_read_barrier_depends() corresponding | ||
| 891 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
| 892 | */ | ||
| 893 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
| 894 | |||
| 895 | if (unlikely(!file)) | ||
| 896 | return; | ||
| 876 | 897 | ||
| 877 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 878 | while (*file) { | 898 | while (*file) { |
| 879 | __kprobe_trace_func(tp, regs, *file); | 899 | __kprobe_trace_func(tp, regs, *file); |
| 880 | file++; | 900 | file++; |
| @@ -925,9 +945,16 @@ static __kprobes void | |||
| 925 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | 945 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 926 | struct pt_regs *regs) | 946 | struct pt_regs *regs) |
| 927 | { | 947 | { |
| 928 | struct ftrace_event_file **file = tp->files; | 948 | /* |
| 949 | * Note: preempt is already disabled around the kprobe handler. | ||
| 950 | * However, we still need an smp_read_barrier_depends() corresponding | ||
| 951 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
| 952 | */ | ||
| 953 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
| 954 | |||
| 955 | if (unlikely(!file)) | ||
| 956 | return; | ||
| 929 | 957 | ||
| 930 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 931 | while (*file) { | 958 | while (*file) { |
| 932 | __kretprobe_trace_func(tp, ri, regs, *file); | 959 | __kretprobe_trace_func(tp, ri, regs, *file); |
| 933 | file++; | 960 | file++; |
| @@ -935,7 +962,7 @@ kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | |||
| 935 | } | 962 | } |
| 936 | 963 | ||
| 937 | /* Event entry printers */ | 964 | /* Event entry printers */ |
| 938 | enum print_line_t | 965 | static enum print_line_t |
| 939 | print_kprobe_event(struct trace_iterator *iter, int flags, | 966 | print_kprobe_event(struct trace_iterator *iter, int flags, |
| 940 | struct trace_event *event) | 967 | struct trace_event *event) |
| 941 | { | 968 | { |
| @@ -971,7 +998,7 @@ partial: | |||
| 971 | return TRACE_TYPE_PARTIAL_LINE; | 998 | return TRACE_TYPE_PARTIAL_LINE; |
| 972 | } | 999 | } |
| 973 | 1000 | ||
| 974 | enum print_line_t | 1001 | static enum print_line_t |
| 975 | print_kretprobe_event(struct trace_iterator *iter, int flags, | 1002 | print_kretprobe_event(struct trace_iterator *iter, int flags, |
| 976 | struct trace_event *event) | 1003 | struct trace_event *event) |
| 977 | { | 1004 | { |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4aa9f5bc6b2d..ee8e29a2320c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -296,7 +296,7 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER); | |||
| 296 | static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS]; | 296 | static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS]; |
| 297 | 297 | ||
| 298 | struct workqueue_struct *system_wq __read_mostly; | 298 | struct workqueue_struct *system_wq __read_mostly; |
| 299 | EXPORT_SYMBOL_GPL(system_wq); | 299 | EXPORT_SYMBOL(system_wq); |
| 300 | struct workqueue_struct *system_highpri_wq __read_mostly; | 300 | struct workqueue_struct *system_highpri_wq __read_mostly; |
| 301 | EXPORT_SYMBOL_GPL(system_highpri_wq); | 301 | EXPORT_SYMBOL_GPL(system_highpri_wq); |
| 302 | struct workqueue_struct *system_long_wq __read_mostly; | 302 | struct workqueue_struct *system_long_wq __read_mostly; |
| @@ -1411,7 +1411,7 @@ bool queue_work_on(int cpu, struct workqueue_struct *wq, | |||
| 1411 | local_irq_restore(flags); | 1411 | local_irq_restore(flags); |
| 1412 | return ret; | 1412 | return ret; |
| 1413 | } | 1413 | } |
| 1414 | EXPORT_SYMBOL_GPL(queue_work_on); | 1414 | EXPORT_SYMBOL(queue_work_on); |
| 1415 | 1415 | ||
| 1416 | void delayed_work_timer_fn(unsigned long __data) | 1416 | void delayed_work_timer_fn(unsigned long __data) |
| 1417 | { | 1417 | { |
| @@ -1485,7 +1485,7 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq, | |||
| 1485 | local_irq_restore(flags); | 1485 | local_irq_restore(flags); |
| 1486 | return ret; | 1486 | return ret; |
| 1487 | } | 1487 | } |
| 1488 | EXPORT_SYMBOL_GPL(queue_delayed_work_on); | 1488 | EXPORT_SYMBOL(queue_delayed_work_on); |
| 1489 | 1489 | ||
| 1490 | /** | 1490 | /** |
| 1491 | * mod_delayed_work_on - modify delay of or queue a delayed work on specific CPU | 1491 | * mod_delayed_work_on - modify delay of or queue a delayed work on specific CPU |
| @@ -2059,6 +2059,7 @@ static bool manage_workers(struct worker *worker) | |||
| 2059 | if (unlikely(!mutex_trylock(&pool->manager_mutex))) { | 2059 | if (unlikely(!mutex_trylock(&pool->manager_mutex))) { |
| 2060 | spin_unlock_irq(&pool->lock); | 2060 | spin_unlock_irq(&pool->lock); |
| 2061 | mutex_lock(&pool->manager_mutex); | 2061 | mutex_lock(&pool->manager_mutex); |
| 2062 | spin_lock_irq(&pool->lock); | ||
| 2062 | ret = true; | 2063 | ret = true; |
| 2063 | } | 2064 | } |
| 2064 | 2065 | ||
| @@ -4311,6 +4312,12 @@ bool current_is_workqueue_rescuer(void) | |||
| 4311 | * no synchronization around this function and the test result is | 4312 | * no synchronization around this function and the test result is |
| 4312 | * unreliable and only useful as advisory hints or for debugging. | 4313 | * unreliable and only useful as advisory hints or for debugging. |
| 4313 | * | 4314 | * |
| 4315 | * If @cpu is WORK_CPU_UNBOUND, the test is performed on the local CPU. | ||
| 4316 | * Note that both per-cpu and unbound workqueues may be associated with | ||
| 4317 | * multiple pool_workqueues which have separate congested states. A | ||
| 4318 | * workqueue being congested on one CPU doesn't mean the workqueue is also | ||
| 4319 | * contested on other CPUs / NUMA nodes. | ||
| 4320 | * | ||
| 4314 | * RETURNS: | 4321 | * RETURNS: |
| 4315 | * %true if congested, %false otherwise. | 4322 | * %true if congested, %false otherwise. |
| 4316 | */ | 4323 | */ |
| @@ -4321,6 +4328,9 @@ bool workqueue_congested(int cpu, struct workqueue_struct *wq) | |||
| 4321 | 4328 | ||
| 4322 | rcu_read_lock_sched(); | 4329 | rcu_read_lock_sched(); |
| 4323 | 4330 | ||
| 4331 | if (cpu == WORK_CPU_UNBOUND) | ||
| 4332 | cpu = smp_processor_id(); | ||
| 4333 | |||
| 4324 | if (!(wq->flags & WQ_UNBOUND)) | 4334 | if (!(wq->flags & WQ_UNBOUND)) |
| 4325 | pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); | 4335 | pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); |
| 4326 | else | 4336 | else |
| @@ -4895,7 +4905,8 @@ static void __init wq_numa_init(void) | |||
| 4895 | BUG_ON(!tbl); | 4905 | BUG_ON(!tbl); |
| 4896 | 4906 | ||
| 4897 | for_each_node(node) | 4907 | for_each_node(node) |
| 4898 | BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL, node)); | 4908 | BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL, |
| 4909 | node_online(node) ? node : NUMA_NO_NODE)); | ||
| 4899 | 4910 | ||
| 4900 | for_each_possible_cpu(cpu) { | 4911 | for_each_possible_cpu(cpu) { |
| 4901 | node = cpu_to_node(cpu); | 4912 | node = cpu_to_node(cpu); |
