diff options
| author | David S. Miller <davem@davemloft.net> | 2016-09-23 06:46:57 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-09-23 06:46:57 -0400 |
| commit | d6989d4bbe6c4d1c2a76696833a07f044e85694d (patch) | |
| tree | 2d9a70d0feee4d4a20568be1b39a961fa0d27d81 /kernel/events/ring_buffer.c | |
| parent | 0364a8824c020f12e2d5e9fad963685b58f7574e (diff) | |
| parent | b1f2beb87bb034bb209773807994279f90cace78 (diff) | |
| download | lwn-d6989d4bbe6c4d1c2a76696833a07f044e85694d.tar.gz lwn-d6989d4bbe6c4d1c2a76696833a07f044e85694d.zip | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'kernel/events/ring_buffer.c')
| -rw-r--r-- | kernel/events/ring_buffer.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index ae9b90dc9a5a..257fa460b846 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -330,15 +330,22 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, if (!rb) return NULL; - if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount)) + if (!rb_has_aux(rb)) goto err; /* - * If rb::aux_mmap_count is zero (and rb_has_aux() above went through), - * the aux buffer is in perf_mmap_close(), about to get freed. + * If aux_mmap_count is zero, the aux buffer is in perf_mmap_close(), + * about to get freed, so we leave immediately. + * + * Checking rb::aux_mmap_count and rb::refcount has to be done in + * the same order, see perf_mmap_close. Otherwise we end up freeing + * aux pages in this path, which is a bug, because in_atomic(). */ if (!atomic_read(&rb->aux_mmap_count)) - goto err_put; + goto err; + + if (!atomic_inc_not_zero(&rb->aux_refcount)) + goto err; /* * Nesting is not supported for AUX area, make sure nested |
