diff options
-rw-r--r-- | include/linux/perf_event.h | 2 | ||||
-rw-r--r-- | kernel/events/core.c | 109 |
2 files changed, 51 insertions, 60 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 3356abcfff18..3ef6ea12806a 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -402,6 +402,8 @@ struct perf_event { | |||
402 | 402 | ||
403 | struct ring_buffer *rb; | 403 | struct ring_buffer *rb; |
404 | struct list_head rb_entry; | 404 | struct list_head rb_entry; |
405 | unsigned long rcu_batches; | ||
406 | int rcu_pending; | ||
405 | 407 | ||
406 | /* poll related */ | 408 | /* poll related */ |
407 | wait_queue_head_t waitq; | 409 | wait_queue_head_t waitq; |
diff --git a/kernel/events/core.c b/kernel/events/core.c index feb1329ca331..440eefc67397 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -3192,7 +3192,8 @@ static void free_event_rcu(struct rcu_head *head) | |||
3192 | } | 3192 | } |
3193 | 3193 | ||
3194 | static void ring_buffer_put(struct ring_buffer *rb); | 3194 | static void ring_buffer_put(struct ring_buffer *rb); |
3195 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); | 3195 | static void ring_buffer_attach(struct perf_event *event, |
3196 | struct ring_buffer *rb); | ||
3196 | 3197 | ||
3197 | static void unaccount_event_cpu(struct perf_event *event, int cpu) | 3198 | static void unaccount_event_cpu(struct perf_event *event, int cpu) |
3198 | { | 3199 | { |
@@ -3252,8 +3253,6 @@ static void free_event(struct perf_event *event) | |||
3252 | unaccount_event(event); | 3253 | unaccount_event(event); |
3253 | 3254 | ||
3254 | if (event->rb) { | 3255 | if (event->rb) { |
3255 | struct ring_buffer *rb; | ||
3256 | |||
3257 | /* | 3256 | /* |
3258 | * Can happen when we close an event with re-directed output. | 3257 | * Can happen when we close an event with re-directed output. |
3259 | * | 3258 | * |
@@ -3261,12 +3260,7 @@ static void free_event(struct perf_event *event) | |||
3261 | * over us; possibly making our ring_buffer_put() the last. | 3260 | * over us; possibly making our ring_buffer_put() the last. |
3262 | */ | 3261 | */ |
3263 | mutex_lock(&event->mmap_mutex); | 3262 | mutex_lock(&event->mmap_mutex); |
3264 | rb = event->rb; | 3263 | ring_buffer_attach(event, NULL); |
3265 | if (rb) { | ||
3266 | rcu_assign_pointer(event->rb, NULL); | ||
3267 | ring_buffer_detach(event, rb); | ||
3268 | ring_buffer_put(rb); /* could be last */ | ||
3269 | } | ||
3270 | mutex_unlock(&event->mmap_mutex); | 3264 | mutex_unlock(&event->mmap_mutex); |
3271 | } | 3265 | } |
3272 | 3266 | ||
@@ -3850,28 +3844,47 @@ unlock: | |||
3850 | static void ring_buffer_attach(struct perf_event *event, | 3844 | static void ring_buffer_attach(struct perf_event *event, |
3851 | struct ring_buffer *rb) | 3845 | struct ring_buffer *rb) |
3852 | { | 3846 | { |
3847 | struct ring_buffer *old_rb = NULL; | ||
3853 | unsigned long flags; | 3848 | unsigned long flags; |
3854 | 3849 | ||
3855 | if (!list_empty(&event->rb_entry)) | 3850 | if (event->rb) { |
3856 | return; | 3851 | /* |
3852 | * Should be impossible, we set this when removing | ||
3853 | * event->rb_entry and wait/clear when adding event->rb_entry. | ||
3854 | */ | ||
3855 | WARN_ON_ONCE(event->rcu_pending); | ||
3857 | 3856 | ||
3858 | spin_lock_irqsave(&rb->event_lock, flags); | 3857 | old_rb = event->rb; |
3859 | if (list_empty(&event->rb_entry)) | 3858 | event->rcu_batches = get_state_synchronize_rcu(); |
3860 | list_add(&event->rb_entry, &rb->event_list); | 3859 | event->rcu_pending = 1; |
3861 | spin_unlock_irqrestore(&rb->event_lock, flags); | ||
3862 | } | ||
3863 | 3860 | ||
3864 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb) | 3861 | spin_lock_irqsave(&old_rb->event_lock, flags); |
3865 | { | 3862 | list_del_rcu(&event->rb_entry); |
3866 | unsigned long flags; | 3863 | spin_unlock_irqrestore(&old_rb->event_lock, flags); |
3864 | } | ||
3867 | 3865 | ||
3868 | if (list_empty(&event->rb_entry)) | 3866 | if (event->rcu_pending && rb) { |
3869 | return; | 3867 | cond_synchronize_rcu(event->rcu_batches); |
3868 | event->rcu_pending = 0; | ||
3869 | } | ||
3870 | 3870 | ||
3871 | spin_lock_irqsave(&rb->event_lock, flags); | 3871 | if (rb) { |
3872 | list_del_init(&event->rb_entry); | 3872 | spin_lock_irqsave(&rb->event_lock, flags); |
3873 | wake_up_all(&event->waitq); | 3873 | list_add_rcu(&event->rb_entry, &rb->event_list); |
3874 | spin_unlock_irqrestore(&rb->event_lock, flags); | 3874 | spin_unlock_irqrestore(&rb->event_lock, flags); |
3875 | } | ||
3876 | |||
3877 | rcu_assign_pointer(event->rb, rb); | ||
3878 | |||
3879 | if (old_rb) { | ||
3880 | ring_buffer_put(old_rb); | ||
3881 | /* | ||
3882 | * Since we detached before setting the new rb, so that we | ||
3883 | * could attach the new rb, we could have missed a wakeup. | ||
3884 | * Provide it now. | ||
3885 | */ | ||
3886 | wake_up_all(&event->waitq); | ||
3887 | } | ||
3875 | } | 3888 | } |
3876 | 3889 | ||
3877 | static void ring_buffer_wakeup(struct perf_event *event) | 3890 | static void ring_buffer_wakeup(struct perf_event *event) |
@@ -3940,7 +3953,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) | |||
3940 | { | 3953 | { |
3941 | struct perf_event *event = vma->vm_file->private_data; | 3954 | struct perf_event *event = vma->vm_file->private_data; |
3942 | 3955 | ||
3943 | struct ring_buffer *rb = event->rb; | 3956 | struct ring_buffer *rb = ring_buffer_get(event); |
3944 | struct user_struct *mmap_user = rb->mmap_user; | 3957 | struct user_struct *mmap_user = rb->mmap_user; |
3945 | int mmap_locked = rb->mmap_locked; | 3958 | int mmap_locked = rb->mmap_locked; |
3946 | unsigned long size = perf_data_size(rb); | 3959 | unsigned long size = perf_data_size(rb); |
@@ -3948,18 +3961,14 @@ static void perf_mmap_close(struct vm_area_struct *vma) | |||
3948 | atomic_dec(&rb->mmap_count); | 3961 | atomic_dec(&rb->mmap_count); |
3949 | 3962 | ||
3950 | if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) | 3963 | if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) |
3951 | return; | 3964 | goto out_put; |
3952 | 3965 | ||
3953 | /* Detach current event from the buffer. */ | 3966 | ring_buffer_attach(event, NULL); |
3954 | rcu_assign_pointer(event->rb, NULL); | ||
3955 | ring_buffer_detach(event, rb); | ||
3956 | mutex_unlock(&event->mmap_mutex); | 3967 | mutex_unlock(&event->mmap_mutex); |
3957 | 3968 | ||
3958 | /* If there's still other mmap()s of this buffer, we're done. */ | 3969 | /* If there's still other mmap()s of this buffer, we're done. */ |
3959 | if (atomic_read(&rb->mmap_count)) { | 3970 | if (atomic_read(&rb->mmap_count)) |
3960 | ring_buffer_put(rb); /* can't be last */ | 3971 | goto out_put; |
3961 | return; | ||
3962 | } | ||
3963 | 3972 | ||
3964 | /* | 3973 | /* |
3965 | * No other mmap()s, detach from all other events that might redirect | 3974 | * No other mmap()s, detach from all other events that might redirect |
@@ -3989,11 +3998,9 @@ again: | |||
3989 | * still restart the iteration to make sure we're not now | 3998 | * still restart the iteration to make sure we're not now |
3990 | * iterating the wrong list. | 3999 | * iterating the wrong list. |
3991 | */ | 4000 | */ |
3992 | if (event->rb == rb) { | 4001 | if (event->rb == rb) |
3993 | rcu_assign_pointer(event->rb, NULL); | 4002 | ring_buffer_attach(event, NULL); |
3994 | ring_buffer_detach(event, rb); | 4003 | |
3995 | ring_buffer_put(rb); /* can't be last, we still have one */ | ||
3996 | } | ||
3997 | mutex_unlock(&event->mmap_mutex); | 4004 | mutex_unlock(&event->mmap_mutex); |
3998 | put_event(event); | 4005 | put_event(event); |
3999 | 4006 | ||
@@ -4018,6 +4025,7 @@ again: | |||
4018 | vma->vm_mm->pinned_vm -= mmap_locked; | 4025 | vma->vm_mm->pinned_vm -= mmap_locked; |
4019 | free_uid(mmap_user); | 4026 | free_uid(mmap_user); |
4020 | 4027 | ||
4028 | out_put: | ||
4021 | ring_buffer_put(rb); /* could be last */ | 4029 | ring_buffer_put(rb); /* could be last */ |
4022 | } | 4030 | } |
4023 | 4031 | ||
@@ -4135,7 +4143,6 @@ again: | |||
4135 | vma->vm_mm->pinned_vm += extra; | 4143 | vma->vm_mm->pinned_vm += extra; |
4136 | 4144 | ||
4137 | ring_buffer_attach(event, rb); | 4145 | ring_buffer_attach(event, rb); |
4138 | rcu_assign_pointer(event->rb, rb); | ||
4139 | 4146 | ||
4140 | perf_event_init_userpage(event); | 4147 | perf_event_init_userpage(event); |
4141 | perf_event_update_userpage(event); | 4148 | perf_event_update_userpage(event); |
@@ -6934,7 +6941,7 @@ err_size: | |||
6934 | static int | 6941 | static int |
6935 | perf_event_set_output(struct perf_event *event, struct perf_event *output_event) | 6942 | perf_event_set_output(struct perf_event *event, struct perf_event *output_event) |
6936 | { | 6943 | { |
6937 | struct ring_buffer *rb = NULL, *old_rb = NULL; | 6944 | struct ring_buffer *rb = NULL; |
6938 | int ret = -EINVAL; | 6945 | int ret = -EINVAL; |
6939 | 6946 | ||
6940 | if (!output_event) | 6947 | if (!output_event) |
@@ -6962,8 +6969,6 @@ set: | |||
6962 | if (atomic_read(&event->mmap_count)) | 6969 | if (atomic_read(&event->mmap_count)) |
6963 | goto unlock; | 6970 | goto unlock; |
6964 | 6971 | ||
6965 | old_rb = event->rb; | ||
6966 | |||
6967 | if (output_event) { | 6972 | if (output_event) { |
6968 | /* get the rb we want to redirect to */ | 6973 | /* get the rb we want to redirect to */ |
6969 | rb = ring_buffer_get(output_event); | 6974 | rb = ring_buffer_get(output_event); |
@@ -6971,23 +6976,7 @@ set: | |||
6971 | goto unlock; | 6976 | goto unlock; |
6972 | } | 6977 | } |
6973 | 6978 | ||
6974 | if (old_rb) | 6979 | ring_buffer_attach(event, rb); |
6975 | ring_buffer_detach(event, old_rb); | ||
6976 | |||
6977 | if (rb) | ||
6978 | ring_buffer_attach(event, rb); | ||
6979 | |||
6980 | rcu_assign_pointer(event->rb, rb); | ||
6981 | |||
6982 | if (old_rb) { | ||
6983 | ring_buffer_put(old_rb); | ||
6984 | /* | ||
6985 | * Since we detached before setting the new rb, so that we | ||
6986 | * could attach the new rb, we could have missed a wakeup. | ||
6987 | * Provide it now. | ||
6988 | */ | ||
6989 | wake_up_all(&event->waitq); | ||
6990 | } | ||
6991 | 6980 | ||
6992 | ret = 0; | 6981 | ret = 0; |
6993 | unlock: | 6982 | unlock: |