diff options
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/core.c | 142 | ||||
-rw-r--r-- | kernel/events/hw_breakpoint.c | 11 | ||||
-rw-r--r-- | kernel/events/uprobes.c | 8 |
3 files changed, 89 insertions, 72 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 2ba890450d15..dbccf83c134d 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -372,6 +372,8 @@ void perf_cgroup_switch(struct task_struct *task, int mode) | |||
372 | 372 | ||
373 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 373 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
374 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 374 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); |
375 | if (cpuctx->unique_pmu != pmu) | ||
376 | continue; /* ensure we process each cpuctx once */ | ||
375 | 377 | ||
376 | /* | 378 | /* |
377 | * perf_cgroup_events says at least one | 379 | * perf_cgroup_events says at least one |
@@ -395,9 +397,10 @@ void perf_cgroup_switch(struct task_struct *task, int mode) | |||
395 | 397 | ||
396 | if (mode & PERF_CGROUP_SWIN) { | 398 | if (mode & PERF_CGROUP_SWIN) { |
397 | WARN_ON_ONCE(cpuctx->cgrp); | 399 | WARN_ON_ONCE(cpuctx->cgrp); |
398 | /* set cgrp before ctxsw in to | 400 | /* |
399 | * allow event_filter_match() to not | 401 | * set cgrp before ctxsw in to allow |
400 | * have to pass task around | 402 | * event_filter_match() to not have to pass |
403 | * task around | ||
401 | */ | 404 | */ |
402 | cpuctx->cgrp = perf_cgroup_from_task(task); | 405 | cpuctx->cgrp = perf_cgroup_from_task(task); |
403 | cpu_ctx_sched_in(cpuctx, EVENT_ALL, task); | 406 | cpu_ctx_sched_in(cpuctx, EVENT_ALL, task); |
@@ -468,14 +471,13 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event, | |||
468 | { | 471 | { |
469 | struct perf_cgroup *cgrp; | 472 | struct perf_cgroup *cgrp; |
470 | struct cgroup_subsys_state *css; | 473 | struct cgroup_subsys_state *css; |
471 | struct file *file; | 474 | struct fd f = fdget(fd); |
472 | int ret = 0, fput_needed; | 475 | int ret = 0; |
473 | 476 | ||
474 | file = fget_light(fd, &fput_needed); | 477 | if (!f.file) |
475 | if (!file) | ||
476 | return -EBADF; | 478 | return -EBADF; |
477 | 479 | ||
478 | css = cgroup_css_from_dir(file, perf_subsys_id); | 480 | css = cgroup_css_from_dir(f.file, perf_subsys_id); |
479 | if (IS_ERR(css)) { | 481 | if (IS_ERR(css)) { |
480 | ret = PTR_ERR(css); | 482 | ret = PTR_ERR(css); |
481 | goto out; | 483 | goto out; |
@@ -501,7 +503,7 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event, | |||
501 | ret = -EINVAL; | 503 | ret = -EINVAL; |
502 | } | 504 | } |
503 | out: | 505 | out: |
504 | fput_light(file, fput_needed); | 506 | fdput(f); |
505 | return ret; | 507 | return ret; |
506 | } | 508 | } |
507 | 509 | ||
@@ -1254,7 +1256,7 @@ retry: | |||
1254 | /* | 1256 | /* |
1255 | * Cross CPU call to disable a performance event | 1257 | * Cross CPU call to disable a performance event |
1256 | */ | 1258 | */ |
1257 | static int __perf_event_disable(void *info) | 1259 | int __perf_event_disable(void *info) |
1258 | { | 1260 | { |
1259 | struct perf_event *event = info; | 1261 | struct perf_event *event = info; |
1260 | struct perf_event_context *ctx = event->ctx; | 1262 | struct perf_event_context *ctx = event->ctx; |
@@ -2936,12 +2938,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); | |||
2936 | /* | 2938 | /* |
2937 | * Called when the last reference to the file is gone. | 2939 | * Called when the last reference to the file is gone. |
2938 | */ | 2940 | */ |
2939 | static int perf_release(struct inode *inode, struct file *file) | 2941 | static void put_event(struct perf_event *event) |
2940 | { | 2942 | { |
2941 | struct perf_event *event = file->private_data; | ||
2942 | struct task_struct *owner; | 2943 | struct task_struct *owner; |
2943 | 2944 | ||
2944 | file->private_data = NULL; | 2945 | if (!atomic_long_dec_and_test(&event->refcount)) |
2946 | return; | ||
2945 | 2947 | ||
2946 | rcu_read_lock(); | 2948 | rcu_read_lock(); |
2947 | owner = ACCESS_ONCE(event->owner); | 2949 | owner = ACCESS_ONCE(event->owner); |
@@ -2976,7 +2978,13 @@ static int perf_release(struct inode *inode, struct file *file) | |||
2976 | put_task_struct(owner); | 2978 | put_task_struct(owner); |
2977 | } | 2979 | } |
2978 | 2980 | ||
2979 | return perf_event_release_kernel(event); | 2981 | perf_event_release_kernel(event); |
2982 | } | ||
2983 | |||
2984 | static int perf_release(struct inode *inode, struct file *file) | ||
2985 | { | ||
2986 | put_event(file->private_data); | ||
2987 | return 0; | ||
2980 | } | 2988 | } |
2981 | 2989 | ||
2982 | u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) | 2990 | u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) |
@@ -3228,21 +3236,18 @@ unlock: | |||
3228 | 3236 | ||
3229 | static const struct file_operations perf_fops; | 3237 | static const struct file_operations perf_fops; |
3230 | 3238 | ||
3231 | static struct perf_event *perf_fget_light(int fd, int *fput_needed) | 3239 | static inline int perf_fget_light(int fd, struct fd *p) |
3232 | { | 3240 | { |
3233 | struct file *file; | 3241 | struct fd f = fdget(fd); |
3234 | 3242 | if (!f.file) | |
3235 | file = fget_light(fd, fput_needed); | 3243 | return -EBADF; |
3236 | if (!file) | ||
3237 | return ERR_PTR(-EBADF); | ||
3238 | 3244 | ||
3239 | if (file->f_op != &perf_fops) { | 3245 | if (f.file->f_op != &perf_fops) { |
3240 | fput_light(file, *fput_needed); | 3246 | fdput(f); |
3241 | *fput_needed = 0; | 3247 | return -EBADF; |
3242 | return ERR_PTR(-EBADF); | ||
3243 | } | 3248 | } |
3244 | 3249 | *p = f; | |
3245 | return file->private_data; | 3250 | return 0; |
3246 | } | 3251 | } |
3247 | 3252 | ||
3248 | static int perf_event_set_output(struct perf_event *event, | 3253 | static int perf_event_set_output(struct perf_event *event, |
@@ -3274,20 +3279,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3274 | 3279 | ||
3275 | case PERF_EVENT_IOC_SET_OUTPUT: | 3280 | case PERF_EVENT_IOC_SET_OUTPUT: |
3276 | { | 3281 | { |
3277 | struct perf_event *output_event = NULL; | ||
3278 | int fput_needed = 0; | ||
3279 | int ret; | 3282 | int ret; |
3280 | |||
3281 | if (arg != -1) { | 3283 | if (arg != -1) { |
3282 | output_event = perf_fget_light(arg, &fput_needed); | 3284 | struct perf_event *output_event; |
3283 | if (IS_ERR(output_event)) | 3285 | struct fd output; |
3284 | return PTR_ERR(output_event); | 3286 | ret = perf_fget_light(arg, &output); |
3287 | if (ret) | ||
3288 | return ret; | ||
3289 | output_event = output.file->private_data; | ||
3290 | ret = perf_event_set_output(event, output_event); | ||
3291 | fdput(output); | ||
3292 | } else { | ||
3293 | ret = perf_event_set_output(event, NULL); | ||
3285 | } | 3294 | } |
3286 | |||
3287 | ret = perf_event_set_output(event, output_event); | ||
3288 | if (output_event) | ||
3289 | fput_light(output_event->filp, fput_needed); | ||
3290 | |||
3291 | return ret; | 3295 | return ret; |
3292 | } | 3296 | } |
3293 | 3297 | ||
@@ -3670,7 +3674,7 @@ unlock: | |||
3670 | atomic_inc(&event->mmap_count); | 3674 | atomic_inc(&event->mmap_count); |
3671 | mutex_unlock(&event->mmap_mutex); | 3675 | mutex_unlock(&event->mmap_mutex); |
3672 | 3676 | ||
3673 | vma->vm_flags |= VM_RESERVED; | 3677 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; |
3674 | vma->vm_ops = &perf_mmap_vmops; | 3678 | vma->vm_ops = &perf_mmap_vmops; |
3675 | 3679 | ||
3676 | return ret; | 3680 | return ret; |
@@ -4411,7 +4415,7 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
4411 | rcu_read_lock(); | 4415 | rcu_read_lock(); |
4412 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4416 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
4413 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 4417 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
4414 | if (cpuctx->active_pmu != pmu) | 4418 | if (cpuctx->unique_pmu != pmu) |
4415 | goto next; | 4419 | goto next; |
4416 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 4420 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
4417 | 4421 | ||
@@ -4557,7 +4561,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
4557 | rcu_read_lock(); | 4561 | rcu_read_lock(); |
4558 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4562 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
4559 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 4563 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
4560 | if (cpuctx->active_pmu != pmu) | 4564 | if (cpuctx->unique_pmu != pmu) |
4561 | goto next; | 4565 | goto next; |
4562 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 4566 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
4563 | 4567 | ||
@@ -4753,7 +4757,7 @@ got_name: | |||
4753 | rcu_read_lock(); | 4757 | rcu_read_lock(); |
4754 | list_for_each_entry_rcu(pmu, &pmus, entry) { | 4758 | list_for_each_entry_rcu(pmu, &pmus, entry) { |
4755 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); | 4759 | cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); |
4756 | if (cpuctx->active_pmu != pmu) | 4760 | if (cpuctx->unique_pmu != pmu) |
4757 | goto next; | 4761 | goto next; |
4758 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, | 4762 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, |
4759 | vma->vm_flags & VM_EXEC); | 4763 | vma->vm_flags & VM_EXEC); |
@@ -5854,8 +5858,8 @@ static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu) | |||
5854 | 5858 | ||
5855 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); | 5859 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); |
5856 | 5860 | ||
5857 | if (cpuctx->active_pmu == old_pmu) | 5861 | if (cpuctx->unique_pmu == old_pmu) |
5858 | cpuctx->active_pmu = pmu; | 5862 | cpuctx->unique_pmu = pmu; |
5859 | } | 5863 | } |
5860 | } | 5864 | } |
5861 | 5865 | ||
@@ -5990,7 +5994,7 @@ skip_type: | |||
5990 | cpuctx->ctx.pmu = pmu; | 5994 | cpuctx->ctx.pmu = pmu; |
5991 | cpuctx->jiffies_interval = 1; | 5995 | cpuctx->jiffies_interval = 1; |
5992 | INIT_LIST_HEAD(&cpuctx->rotation_list); | 5996 | INIT_LIST_HEAD(&cpuctx->rotation_list); |
5993 | cpuctx->active_pmu = pmu; | 5997 | cpuctx->unique_pmu = pmu; |
5994 | } | 5998 | } |
5995 | 5999 | ||
5996 | got_cpu_context: | 6000 | got_cpu_context: |
@@ -6142,6 +6146,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, | |||
6142 | 6146 | ||
6143 | mutex_init(&event->mmap_mutex); | 6147 | mutex_init(&event->mmap_mutex); |
6144 | 6148 | ||
6149 | atomic_long_set(&event->refcount, 1); | ||
6145 | event->cpu = cpu; | 6150 | event->cpu = cpu; |
6146 | event->attr = *attr; | 6151 | event->attr = *attr; |
6147 | event->group_leader = group_leader; | 6152 | event->group_leader = group_leader; |
@@ -6434,12 +6439,11 @@ SYSCALL_DEFINE5(perf_event_open, | |||
6434 | struct perf_event_attr attr; | 6439 | struct perf_event_attr attr; |
6435 | struct perf_event_context *ctx; | 6440 | struct perf_event_context *ctx; |
6436 | struct file *event_file = NULL; | 6441 | struct file *event_file = NULL; |
6437 | struct file *group_file = NULL; | 6442 | struct fd group = {NULL, 0}; |
6438 | struct task_struct *task = NULL; | 6443 | struct task_struct *task = NULL; |
6439 | struct pmu *pmu; | 6444 | struct pmu *pmu; |
6440 | int event_fd; | 6445 | int event_fd; |
6441 | int move_group = 0; | 6446 | int move_group = 0; |
6442 | int fput_needed = 0; | ||
6443 | int err; | 6447 | int err; |
6444 | 6448 | ||
6445 | /* for future expandability... */ | 6449 | /* for future expandability... */ |
@@ -6469,17 +6473,15 @@ SYSCALL_DEFINE5(perf_event_open, | |||
6469 | if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) | 6473 | if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) |
6470 | return -EINVAL; | 6474 | return -EINVAL; |
6471 | 6475 | ||
6472 | event_fd = get_unused_fd_flags(O_RDWR); | 6476 | event_fd = get_unused_fd(); |
6473 | if (event_fd < 0) | 6477 | if (event_fd < 0) |
6474 | return event_fd; | 6478 | return event_fd; |
6475 | 6479 | ||
6476 | if (group_fd != -1) { | 6480 | if (group_fd != -1) { |
6477 | group_leader = perf_fget_light(group_fd, &fput_needed); | 6481 | err = perf_fget_light(group_fd, &group); |
6478 | if (IS_ERR(group_leader)) { | 6482 | if (err) |
6479 | err = PTR_ERR(group_leader); | ||
6480 | goto err_fd; | 6483 | goto err_fd; |
6481 | } | 6484 | group_leader = group.file->private_data; |
6482 | group_file = group_leader->filp; | ||
6483 | if (flags & PERF_FLAG_FD_OUTPUT) | 6485 | if (flags & PERF_FLAG_FD_OUTPUT) |
6484 | output_event = group_leader; | 6486 | output_event = group_leader; |
6485 | if (flags & PERF_FLAG_FD_NO_GROUP) | 6487 | if (flags & PERF_FLAG_FD_NO_GROUP) |
@@ -6616,7 +6618,6 @@ SYSCALL_DEFINE5(perf_event_open, | |||
6616 | put_ctx(gctx); | 6618 | put_ctx(gctx); |
6617 | } | 6619 | } |
6618 | 6620 | ||
6619 | event->filp = event_file; | ||
6620 | WARN_ON_ONCE(ctx->parent_ctx); | 6621 | WARN_ON_ONCE(ctx->parent_ctx); |
6621 | mutex_lock(&ctx->mutex); | 6622 | mutex_lock(&ctx->mutex); |
6622 | 6623 | ||
@@ -6656,7 +6657,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
6656 | * of the group leader will find the pointer to itself in | 6657 | * of the group leader will find the pointer to itself in |
6657 | * perf_group_detach(). | 6658 | * perf_group_detach(). |
6658 | */ | 6659 | */ |
6659 | fput_light(group_file, fput_needed); | 6660 | fdput(group); |
6660 | fd_install(event_fd, event_file); | 6661 | fd_install(event_fd, event_file); |
6661 | return event_fd; | 6662 | return event_fd; |
6662 | 6663 | ||
@@ -6670,7 +6671,7 @@ err_task: | |||
6670 | if (task) | 6671 | if (task) |
6671 | put_task_struct(task); | 6672 | put_task_struct(task); |
6672 | err_group_fd: | 6673 | err_group_fd: |
6673 | fput_light(group_file, fput_needed); | 6674 | fdput(group); |
6674 | err_fd: | 6675 | err_fd: |
6675 | put_unused_fd(event_fd); | 6676 | put_unused_fd(event_fd); |
6676 | return err; | 6677 | return err; |
@@ -6710,7 +6711,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | |||
6710 | goto err_free; | 6711 | goto err_free; |
6711 | } | 6712 | } |
6712 | 6713 | ||
6713 | event->filp = NULL; | ||
6714 | WARN_ON_ONCE(ctx->parent_ctx); | 6714 | WARN_ON_ONCE(ctx->parent_ctx); |
6715 | mutex_lock(&ctx->mutex); | 6715 | mutex_lock(&ctx->mutex); |
6716 | perf_install_in_context(ctx, event, cpu); | 6716 | perf_install_in_context(ctx, event, cpu); |
@@ -6792,7 +6792,7 @@ static void sync_child_event(struct perf_event *child_event, | |||
6792 | * Release the parent event, if this was the last | 6792 | * Release the parent event, if this was the last |
6793 | * reference to it. | 6793 | * reference to it. |
6794 | */ | 6794 | */ |
6795 | fput(parent_event->filp); | 6795 | put_event(parent_event); |
6796 | } | 6796 | } |
6797 | 6797 | ||
6798 | static void | 6798 | static void |
@@ -6868,9 +6868,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) | |||
6868 | * | 6868 | * |
6869 | * __perf_event_exit_task() | 6869 | * __perf_event_exit_task() |
6870 | * sync_child_event() | 6870 | * sync_child_event() |
6871 | * fput(parent_event->filp) | 6871 | * put_event() |
6872 | * perf_release() | 6872 | * mutex_lock(&ctx->mutex) |
6873 | * mutex_lock(&ctx->mutex) | ||
6874 | * | 6873 | * |
6875 | * But since its the parent context it won't be the same instance. | 6874 | * But since its the parent context it won't be the same instance. |
6876 | */ | 6875 | */ |
@@ -6938,7 +6937,7 @@ static void perf_free_event(struct perf_event *event, | |||
6938 | list_del_init(&event->child_list); | 6937 | list_del_init(&event->child_list); |
6939 | mutex_unlock(&parent->child_mutex); | 6938 | mutex_unlock(&parent->child_mutex); |
6940 | 6939 | ||
6941 | fput(parent->filp); | 6940 | put_event(parent); |
6942 | 6941 | ||
6943 | perf_group_detach(event); | 6942 | perf_group_detach(event); |
6944 | list_del_event(event, ctx); | 6943 | list_del_event(event, ctx); |
@@ -7018,6 +7017,12 @@ inherit_event(struct perf_event *parent_event, | |||
7018 | NULL, NULL); | 7017 | NULL, NULL); |
7019 | if (IS_ERR(child_event)) | 7018 | if (IS_ERR(child_event)) |
7020 | return child_event; | 7019 | return child_event; |
7020 | |||
7021 | if (!atomic_long_inc_not_zero(&parent_event->refcount)) { | ||
7022 | free_event(child_event); | ||
7023 | return NULL; | ||
7024 | } | ||
7025 | |||
7021 | get_ctx(child_ctx); | 7026 | get_ctx(child_ctx); |
7022 | 7027 | ||
7023 | /* | 7028 | /* |
@@ -7059,14 +7064,6 @@ inherit_event(struct perf_event *parent_event, | |||
7059 | raw_spin_unlock_irqrestore(&child_ctx->lock, flags); | 7064 | raw_spin_unlock_irqrestore(&child_ctx->lock, flags); |
7060 | 7065 | ||
7061 | /* | 7066 | /* |
7062 | * Get a reference to the parent filp - we will fput it | ||
7063 | * when the child event exits. This is safe to do because | ||
7064 | * we are in the parent and we know that the filp still | ||
7065 | * exists and has a nonzero count: | ||
7066 | */ | ||
7067 | atomic_long_inc(&parent_event->filp->f_count); | ||
7068 | |||
7069 | /* | ||
7070 | * Link this into the parent event's child list | 7067 | * Link this into the parent event's child list |
7071 | */ | 7068 | */ |
7072 | WARN_ON_ONCE(parent_event->ctx->parent_ctx); | 7069 | WARN_ON_ONCE(parent_event->ctx->parent_ctx); |
@@ -7499,5 +7496,12 @@ struct cgroup_subsys perf_subsys = { | |||
7499 | .destroy = perf_cgroup_destroy, | 7496 | .destroy = perf_cgroup_destroy, |
7500 | .exit = perf_cgroup_exit, | 7497 | .exit = perf_cgroup_exit, |
7501 | .attach = perf_cgroup_attach, | 7498 | .attach = perf_cgroup_attach, |
7499 | |||
7500 | /* | ||
7501 | * perf_event cgroup doesn't handle nesting correctly. | ||
7502 | * ctx->nr_cgroups adjustments should be propagated through the | ||
7503 | * cgroup hierarchy. Fix it and remove the following. | ||
7504 | */ | ||
7505 | .broken_hierarchy = true, | ||
7502 | }; | 7506 | }; |
7503 | #endif /* CONFIG_CGROUP_PERF */ | 7507 | #endif /* CONFIG_CGROUP_PERF */ |
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index bb38c4d3ee12..9a7b487c6fe2 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c | |||
@@ -453,7 +453,16 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att | |||
453 | int old_type = bp->attr.bp_type; | 453 | int old_type = bp->attr.bp_type; |
454 | int err = 0; | 454 | int err = 0; |
455 | 455 | ||
456 | perf_event_disable(bp); | 456 | /* |
457 | * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it | ||
458 | * will not be possible to raise IPIs that invoke __perf_event_disable. | ||
459 | * So call the function directly after making sure we are targeting the | ||
460 | * current task. | ||
461 | */ | ||
462 | if (irqs_disabled() && bp->ctx && bp->ctx->task == current) | ||
463 | __perf_event_disable(bp); | ||
464 | else | ||
465 | perf_event_disable(bp); | ||
457 | 466 | ||
458 | bp->attr.bp_addr = attr->bp_addr; | 467 | bp->attr.bp_addr = attr->bp_addr; |
459 | bp->attr.bp_type = attr->bp_type; | 468 | bp->attr.bp_type = attr->bp_type; |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index c92651d619ca..5cc4e7e42e68 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -144,10 +144,14 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
144 | spinlock_t *ptl; | 144 | spinlock_t *ptl; |
145 | pte_t *ptep; | 145 | pte_t *ptep; |
146 | int err; | 146 | int err; |
147 | /* For mmu_notifiers */ | ||
148 | const unsigned long mmun_start = addr; | ||
149 | const unsigned long mmun_end = addr + PAGE_SIZE; | ||
147 | 150 | ||
148 | /* For try_to_free_swap() and munlock_vma_page() below */ | 151 | /* For try_to_free_swap() and munlock_vma_page() below */ |
149 | lock_page(page); | 152 | lock_page(page); |
150 | 153 | ||
154 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
151 | err = -EAGAIN; | 155 | err = -EAGAIN; |
152 | ptep = page_check_address(page, mm, addr, &ptl, 0); | 156 | ptep = page_check_address(page, mm, addr, &ptl, 0); |
153 | if (!ptep) | 157 | if (!ptep) |
@@ -176,6 +180,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
176 | 180 | ||
177 | err = 0; | 181 | err = 0; |
178 | unlock: | 182 | unlock: |
183 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
179 | unlock_page(page); | 184 | unlock_page(page); |
180 | return err; | 185 | return err; |
181 | } | 186 | } |
@@ -690,7 +695,6 @@ static struct map_info * | |||
690 | build_map_info(struct address_space *mapping, loff_t offset, bool is_register) | 695 | build_map_info(struct address_space *mapping, loff_t offset, bool is_register) |
691 | { | 696 | { |
692 | unsigned long pgoff = offset >> PAGE_SHIFT; | 697 | unsigned long pgoff = offset >> PAGE_SHIFT; |
693 | struct prio_tree_iter iter; | ||
694 | struct vm_area_struct *vma; | 698 | struct vm_area_struct *vma; |
695 | struct map_info *curr = NULL; | 699 | struct map_info *curr = NULL; |
696 | struct map_info *prev = NULL; | 700 | struct map_info *prev = NULL; |
@@ -699,7 +703,7 @@ build_map_info(struct address_space *mapping, loff_t offset, bool is_register) | |||
699 | 703 | ||
700 | again: | 704 | again: |
701 | mutex_lock(&mapping->i_mmap_mutex); | 705 | mutex_lock(&mapping->i_mmap_mutex); |
702 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 706 | vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { |
703 | if (!valid_vma(vma, is_register)) | 707 | if (!valid_vma(vma, is_register)) |
704 | continue; | 708 | continue; |
705 | 709 | ||