This reverts commit 80e846398c695dc3d0d2eac6da91772ff2aade65.

Let's see what CI says about reverting this 4 ~ 5 years old commit. We
shouldn't be in the business of changing perf/core in our "for CI" drm
branch.

Signed-off-by: Lucas De Marchi <[email protected]>
---
 kernel/events/core.c | 49 ++++++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index bf5b8fc8979e..ac5e7c683526 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5729,16 +5729,20 @@ static int __perf_read_group_add(struct perf_event 
*leader,
 }
 
 static int perf_read_group(struct perf_event *event,
-                          u64 read_format, char __user *buf,
-                          u64 *values)
+                                  u64 read_format, char __user *buf)
 {
        struct perf_event *leader = event->group_leader, *child;
        struct perf_event_context *ctx = leader->ctx;
        int ret;
+       u64 *values;
 
        lockdep_assert_held(&ctx->mutex);
 
-       *values = 1 + leader->nr_siblings;
+       values = kzalloc(event->read_size, GFP_KERNEL);
+       if (!values)
+               return -ENOMEM;
+
+       values[0] = 1 + leader->nr_siblings;
 
        mutex_lock(&leader->child_mutex);
 
@@ -5752,17 +5756,25 @@ static int perf_read_group(struct perf_event *event,
                        goto unlock;
        }
 
+       mutex_unlock(&leader->child_mutex);
+
        ret = event->read_size;
+       if (copy_to_user(buf, values, event->read_size))
+               ret = -EFAULT;
+       goto out;
+
 unlock:
        mutex_unlock(&leader->child_mutex);
+out:
+       kfree(values);
        return ret;
 }
 
 static int perf_read_one(struct perf_event *event,
-                        u64 read_format, char __user *buf,
-                        u64 *values)
+                                u64 read_format, char __user *buf)
 {
        u64 enabled, running;
+       u64 values[5];
        int n = 0;
 
        values[n++] = __perf_event_read_value(event, &enabled, &running);
@@ -5775,6 +5787,9 @@ static int perf_read_one(struct perf_event *event,
        if (read_format & PERF_FORMAT_LOST)
                values[n++] = atomic64_read(&event->lost_samples);
 
+       if (copy_to_user(buf, values, n * sizeof(u64)))
+               return -EFAULT;
+
        return n * sizeof(u64);
 }
 
@@ -5795,8 +5810,7 @@ static bool is_event_hup(struct perf_event *event)
  * Read the performance event - simple non blocking version for now
  */
 static ssize_t
-__perf_read(struct perf_event *event, char __user *buf,
-           size_t count, u64 *values)
+__perf_read(struct perf_event *event, char __user *buf, size_t count)
 {
        u64 read_format = event->attr.read_format;
        int ret;
@@ -5814,9 +5828,9 @@ __perf_read(struct perf_event *event, char __user *buf,
 
        WARN_ON_ONCE(event->ctx->parent_ctx);
        if (read_format & PERF_FORMAT_GROUP)
-               ret = perf_read_group(event, read_format, buf, values);
+               ret = perf_read_group(event, read_format, buf);
        else
-               ret = perf_read_one(event, read_format, buf, values);
+               ret = perf_read_one(event, read_format, buf);
 
        return ret;
 }
@@ -5826,31 +5840,16 @@ perf_read(struct file *file, char __user *buf, size_t 
count, loff_t *ppos)
 {
        struct perf_event *event = file->private_data;
        struct perf_event_context *ctx;
-       u64 stack_values[8];
-       u64 *values;
        int ret;
 
        ret = security_perf_event_read(event);
        if (ret)
                return ret;
 
-       if (event->read_size <= sizeof(stack_values))
-               values = memset(stack_values, 0, event->read_size);
-       else
-               values = kzalloc(event->read_size, GFP_KERNEL);
-       if (!values)
-               return -ENOMEM;
-
        ctx = perf_event_ctx_lock(event);
-       ret = __perf_read(event, buf, count, values);
+       ret = __perf_read(event, buf, count);
        perf_event_ctx_unlock(event, ctx);
 
-       if (ret > 0 && copy_to_user(buf, values, ret))
-               ret = -EFAULT;
-
-       if (values != stack_values)
-               kfree(values);
-
        return ret;
 }
 
-- 
2.47.0

Reply via email to