perf: Fix wakeup storm for RO mmap()s
[profile/ivi/kernel-x86-ivi.git] / kernel / perf_event.c
index 3f2cc31..1531e0b 100644 (file)
@@ -3056,8 +3056,8 @@ int perf_output_begin(struct perf_output_handle *handle,
        handle->offset  = offset;
        handle->head    = head;
 
-       if (head - tail > data->watermark)
-               local_inc(&data->wakeup);
+       if (head - local_read(&data->wakeup) > data->watermark)
+               local_add(data->watermark, &data->wakeup);
 
        if (have_lost) {
                lost_event.header.type = PERF_RECORD_LOST;
@@ -4920,6 +4920,13 @@ static int perf_event_set_output(struct perf_event *event, int output_fd)
        int fput_needed = 0;
        int ret = -EINVAL;
 
+       /*
+        * Don't allow output of inherited per-task events. This would
+        * create performance issues due to cross cpu access.
+        */
+       if (event->cpu == -1 && event->attr.inherit)
+               return -EINVAL;
+
        if (!output_fd)
                goto set;
 
@@ -4940,6 +4947,18 @@ static int perf_event_set_output(struct perf_event *event, int output_fd)
        if (event->data)
                goto out;
 
+       /*
+        * Don't allow cross-cpu buffers
+        */
+       if (output_event->cpu != event->cpu)
+               goto out;
+
+       /*
+        * If its not a per-cpu buffer, it must be the same task.
+        */
+       if (output_event->cpu == -1 && output_event->ctx != event->ctx)
+               goto out;
+
        atomic_long_inc(&output_file->f_count);
 
 set: