Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / kernel / events / core.c
index 9fcb0944f0718597fab6f6723e70e701be55b075..3820e3cefbaea869541fcdabadb909174f83a42f 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/mm_types.h>
+#include <linux/cgroup.h>
 
 #include "internal.h"
 
@@ -233,6 +234,20 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
 
 #ifdef CONFIG_CGROUP_PERF
 
+/*
+ * perf_cgroup_info keeps track of time_enabled for a cgroup.
+ * This is a per-cpu dynamically allocated data structure.
+ */
+struct perf_cgroup_info {
+       u64                             time;
+       u64                             timestamp;
+};
+
+struct perf_cgroup {
+       struct cgroup_subsys_state      css;
+       struct perf_cgroup_info __percpu *info;
+};
+
 /*
  * Must ensure cgroup is pinned (css_get) before calling
  * this function. In other words, we cannot call this function
@@ -251,7 +266,22 @@ perf_cgroup_match(struct perf_event *event)
        struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
-       return !event->cgrp || event->cgrp == cpuctx->cgrp;
+       /* @event doesn't care about cgroup */
+       if (!event->cgrp)
+               return true;
+
+       /* wants specific cgroup scope but @cpuctx isn't associated with any */
+       if (!cpuctx->cgrp)
+               return false;
+
+       /*
+        * Cgroup scoping is recursive.  An event enabled for a cgroup is
+        * also enabled for all its descendant cgroups.  If @cpuctx's
+        * cgroup is a descendant of @event's (the test covers identity
+        * case), it's a match.
+        */
+       return cgroup_is_descendant(cpuctx->cgrp->css.cgroup,
+                                   event->cgrp->css.cgroup);
 }
 
 static inline bool perf_tryget_cgroup(struct perf_event *event)
@@ -961,9 +991,15 @@ static void perf_event__header_size(struct perf_event *event)
        if (sample_type & PERF_SAMPLE_PERIOD)
                size += sizeof(data->period);
 
+       if (sample_type & PERF_SAMPLE_WEIGHT)
+               size += sizeof(data->weight);
+
        if (sample_type & PERF_SAMPLE_READ)
                size += event->read_size;
 
+       if (sample_type & PERF_SAMPLE_DATA_SRC)
+               size += sizeof(data->data_src.val);
+
        event->header_size = size;
 }
 
@@ -4178,6 +4214,12 @@ void perf_output_sample(struct perf_output_handle *handle,
                perf_output_sample_ustack(handle,
                                          data->stack_user_size,
                                          data->regs_user.regs);
+
+       if (sample_type & PERF_SAMPLE_WEIGHT)
+               perf_output_put(handle, data->weight);
+
+       if (sample_type & PERF_SAMPLE_DATA_SRC)
+               perf_output_put(handle, data->data_src.val);
 }
 
 void perf_prepare_sample(struct perf_event_header *header,
@@ -4767,6 +4809,9 @@ got_name:
        mmap_event->file_name = name;
        mmap_event->file_size = size;
 
+       if (!(vma->vm_flags & VM_EXEC))
+               mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
+
        mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
 
        rcu_read_lock();
@@ -7517,12 +7562,5 @@ struct cgroup_subsys perf_subsys = {
        .css_free       = perf_cgroup_css_free,
        .exit           = perf_cgroup_exit,
        .attach         = perf_cgroup_attach,
-
-       /*
-        * perf_event cgroup doesn't handle nesting correctly.
-        * ctx->nr_cgroups adjustments should be propagated through the
-        * cgroup hierarchy.  Fix it and remove the following.
-        */
-       .broken_hierarchy = true,
 };
 #endif /* CONFIG_CGROUP_PERF */