aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/perf_event.c52
1 files changed, 21 insertions, 31 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 68fbf4ff6888..9a18ff28ea5b 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -1784,30 +1784,15 @@ u64 perf_event_read_value(struct perf_event *event)
1784} 1784}
1785EXPORT_SYMBOL_GPL(perf_event_read_value); 1785EXPORT_SYMBOL_GPL(perf_event_read_value);
1786 1786
1787static int perf_event_read_entry(struct perf_event *event,
1788 u64 read_format, char __user *buf)
1789{
1790 int n = 0, count = 0;
1791 u64 values[2];
1792
1793 values[n++] = perf_event_read_value(event);
1794 if (read_format & PERF_FORMAT_ID)
1795 values[n++] = primary_event_id(event);
1796
1797 count = n * sizeof(u64);
1798
1799 if (copy_to_user(buf, values, count))
1800 return -EFAULT;
1801
1802 return count;
1803}
1804
1805static int perf_event_read_group(struct perf_event *event, 1787static int perf_event_read_group(struct perf_event *event,
1806 u64 read_format, char __user *buf) 1788 u64 read_format, char __user *buf)
1807{ 1789{
1808 struct perf_event *leader = event->group_leader, *sub; 1790 struct perf_event *leader = event->group_leader, *sub;
1809 int n = 0, size = 0, err = -EFAULT; 1791 int n = 0, size = 0, ret = 0;
1810 u64 values[3]; 1792 u64 values[5];
1793 u64 count;
1794
1795 count = perf_event_read_value(leader);
1811 1796
1812 values[n++] = 1 + leader->nr_siblings; 1797 values[n++] = 1 + leader->nr_siblings;
1813 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1798 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
@@ -1818,28 +1803,33 @@ static int perf_event_read_group(struct perf_event *event,
1818 values[n++] = leader->total_time_running + 1803 values[n++] = leader->total_time_running +
1819 atomic64_read(&leader->child_total_time_running); 1804 atomic64_read(&leader->child_total_time_running);
1820 } 1805 }
1806 values[n++] = count;
1807 if (read_format & PERF_FORMAT_ID)
1808 values[n++] = primary_event_id(leader);
1821 1809
1822 size = n * sizeof(u64); 1810 size = n * sizeof(u64);
1823 1811
1824 if (copy_to_user(buf, values, size)) 1812 if (copy_to_user(buf, values, size))
1825 return -EFAULT; 1813 return -EFAULT;
1826 1814
1827 err = perf_event_read_entry(leader, read_format, buf + size); 1815 ret += size;
1828 if (err < 0)
1829 return err;
1830
1831 size += err;
1832 1816
1833 list_for_each_entry(sub, &leader->sibling_list, group_entry) { 1817 list_for_each_entry(sub, &leader->sibling_list, group_entry) {
1834 err = perf_event_read_entry(sub, read_format, 1818 n = 0;
1835 buf + size);
1836 if (err < 0)
1837 return err;
1838 1819
1839 size += err; 1820 values[n++] = perf_event_read_value(sub);
1821 if (read_format & PERF_FORMAT_ID)
1822 values[n++] = primary_event_id(sub);
1823
1824 size = n * sizeof(u64);
1825
1826 if (copy_to_user(buf + size, values, size))
1827 return -EFAULT;
1828
1829 ret += size;
1840 } 1830 }
1841 1831
1842 return size; 1832 return ret;
1843} 1833}
1844 1834
1845static int perf_event_read_one(struct perf_event *event, 1835static int perf_event_read_one(struct perf_event *event,