Skip to content

Commit d5b76be

Browse files
committed
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "A kernel crash fix plus three tooling fixes" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/core: Fix crash in perf_event_read() perf callchain: Reference count maps perf diff: Fix -o/--order option behavior (again) perf diff: Fix segfault on 'perf diff -o N' option
2 parents 4e4f74a + 451d24d commit d5b76be

File tree

7 files changed

+55
-13
lines changed

7 files changed

+55
-13
lines changed

kernel/events/core.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,14 +3487,15 @@ struct perf_read_data {
34873487
int ret;
34883488
};
34893489

3490-
static int find_cpu_to_read(struct perf_event *event, int local_cpu)
3490+
static int __perf_event_read_cpu(struct perf_event *event, int event_cpu)
34913491
{
3492-
int event_cpu = event->oncpu;
34933492
u16 local_pkg, event_pkg;
34943493

34953494
if (event->group_caps & PERF_EV_CAP_READ_ACTIVE_PKG) {
3496-
event_pkg = topology_physical_package_id(event_cpu);
3497-
local_pkg = topology_physical_package_id(local_cpu);
3495+
int local_cpu = smp_processor_id();
3496+
3497+
event_pkg = topology_physical_package_id(event_cpu);
3498+
local_pkg = topology_physical_package_id(local_cpu);
34983499

34993500
if (event_pkg == local_pkg)
35003501
return local_cpu;
@@ -3624,7 +3625,7 @@ u64 perf_event_read_local(struct perf_event *event)
36243625

36253626
static int perf_event_read(struct perf_event *event, bool group)
36263627
{
3627-
int ret = 0, cpu_to_read, local_cpu;
3628+
int event_cpu, ret = 0;
36283629

36293630
/*
36303631
* If event is enabled and currently active on a CPU, update the
@@ -3637,21 +3638,25 @@ static int perf_event_read(struct perf_event *event, bool group)
36373638
.ret = 0,
36383639
};
36393640

3640-
local_cpu = get_cpu();
3641-
cpu_to_read = find_cpu_to_read(event, local_cpu);
3642-
put_cpu();
3641+
event_cpu = READ_ONCE(event->oncpu);
3642+
if ((unsigned)event_cpu >= nr_cpu_ids)
3643+
return 0;
3644+
3645+
preempt_disable();
3646+
event_cpu = __perf_event_read_cpu(event, event_cpu);
36433647

36443648
/*
36453649
* Purposely ignore the smp_call_function_single() return
36463650
* value.
36473651
*
3648-
* If event->oncpu isn't a valid CPU it means the event got
3652+
* If event_cpu isn't a valid CPU it means the event got
36493653
* scheduled out and that will have updated the event count.
36503654
*
36513655
* Therefore, either way, we'll have an up-to-date event count
36523656
* after this.
36533657
*/
3654-
(void)smp_call_function_single(cpu_to_read, __perf_event_read, &data, 1);
3658+
(void)smp_call_function_single(event_cpu, __perf_event_read, &data, 1);
3659+
preempt_enable();
36553660
ret = data.ret;
36563661
} else if (event->state == PERF_EVENT_STATE_INACTIVE) {
36573662
struct perf_event_context *ctx = event->ctx;

tools/perf/builtin-diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1199,7 +1199,7 @@ static int ui_init(void)
11991199
BUG_ON(1);
12001200
}
12011201

1202-
perf_hpp__register_sort_field(fmt);
1202+
perf_hpp__prepend_sort_field(fmt);
12031203
return 0;
12041204
}
12051205

tools/perf/ui/hist.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,12 @@ void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
521521
list_add_tail(&format->sort_list, &list->sorts);
522522
}
523523

524+
void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
525+
struct perf_hpp_fmt *format)
526+
{
527+
list_add(&format->sort_list, &list->sorts);
528+
}
529+
524530
void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
525531
{
526532
list_del(&format->list);
@@ -560,6 +566,10 @@ void perf_hpp__setup_output_field(struct perf_hpp_list *list)
560566
perf_hpp_list__for_each_sort_list(list, fmt) {
561567
struct perf_hpp_fmt *pos;
562568

569+
/* skip sort-only fields ("sort_compute" in perf diff) */
570+
if (!fmt->entry && !fmt->color)
571+
continue;
572+
563573
perf_hpp_list__for_each_format(list, pos) {
564574
if (fmt_equal(fmt, pos))
565575
goto next;

tools/perf/util/callchain.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
437437
}
438438
call->ip = cursor_node->ip;
439439
call->ms.sym = cursor_node->sym;
440-
call->ms.map = cursor_node->map;
440+
call->ms.map = map__get(cursor_node->map);
441441

442442
if (cursor_node->branch) {
443443
call->branch_count = 1;
@@ -477,6 +477,7 @@ add_child(struct callchain_node *parent,
477477

478478
list_for_each_entry_safe(call, tmp, &new->val, list) {
479479
list_del(&call->list);
480+
map__zput(call->ms.map);
480481
free(call);
481482
}
482483
free(new);
@@ -761,6 +762,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
761762
list->ms.map, list->ms.sym,
762763
false, NULL, 0, 0);
763764
list_del(&list->list);
765+
map__zput(list->ms.map);
764766
free(list);
765767
}
766768

@@ -811,7 +813,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
811813
}
812814

813815
node->ip = ip;
814-
node->map = map;
816+
map__zput(node->map);
817+
node->map = map__get(map);
815818
node->sym = sym;
816819
node->branch = branch;
817820
node->nr_loop_iter = nr_loop_iter;
@@ -1142,11 +1145,13 @@ static void free_callchain_node(struct callchain_node *node)
11421145

11431146
list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
11441147
list_del(&list->list);
1148+
map__zput(list->ms.map);
11451149
free(list);
11461150
}
11471151

11481152
list_for_each_entry_safe(list, tmp, &node->val, list) {
11491153
list_del(&list->list);
1154+
map__zput(list->ms.map);
11501155
free(list);
11511156
}
11521157

@@ -1210,6 +1215,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
12101215
goto out;
12111216
*new = *chain;
12121217
new->has_children = false;
1218+
map__get(new->ms.map);
12131219
list_add_tail(&new->list, &head);
12141220
}
12151221
parent = parent->parent;
@@ -1230,6 +1236,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
12301236
out:
12311237
list_for_each_entry_safe(chain, new, &head, list) {
12321238
list_del(&chain->list);
1239+
map__zput(chain->ms.map);
12331240
free(chain);
12341241
}
12351242
return -ENOMEM;

tools/perf/util/callchain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/list.h>
66
#include <linux/rbtree.h>
77
#include "event.h"
8+
#include "map.h"
89
#include "symbol.h"
910

1011
#define HELP_PAD "\t\t\t\t"
@@ -184,8 +185,13 @@ int callchain_merge(struct callchain_cursor *cursor,
184185
*/
185186
static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
186187
{
188+
struct callchain_cursor_node *node;
189+
187190
cursor->nr = 0;
188191
cursor->last = &cursor->first;
192+
193+
for (node = cursor->first; node != NULL; node = node->next)
194+
map__zput(node->map);
189195
}
190196

191197
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,

tools/perf/util/hist.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "util.h"
22
#include "build-id.h"
33
#include "hist.h"
4+
#include "map.h"
45
#include "session.h"
56
#include "sort.h"
67
#include "evlist.h"
@@ -1019,6 +1020,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
10191020
int max_stack_depth, void *arg)
10201021
{
10211022
int err, err2;
1023+
struct map *alm = NULL;
1024+
1025+
if (al && al->map)
1026+
alm = map__get(al->map);
10221027

10231028
err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
10241029
iter->evsel, al, max_stack_depth);
@@ -1058,6 +1063,8 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
10581063
if (!err)
10591064
err = err2;
10601065

1066+
map__put(alm);
1067+
10611068
return err;
10621069
}
10631070

tools/perf/util/hist.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ void perf_hpp_list__column_register(struct perf_hpp_list *list,
283283
struct perf_hpp_fmt *format);
284284
void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
285285
struct perf_hpp_fmt *format);
286+
void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
287+
struct perf_hpp_fmt *format);
286288

287289
static inline void perf_hpp__column_register(struct perf_hpp_fmt *format)
288290
{
@@ -294,6 +296,11 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
294296
perf_hpp_list__register_sort_field(&perf_hpp_list, format);
295297
}
296298

299+
static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
300+
{
301+
perf_hpp_list__prepend_sort_field(&perf_hpp_list, format);
302+
}
303+
297304
#define perf_hpp_list__for_each_format(_list, format) \
298305
list_for_each_entry(format, &(_list)->fields, list)
299306

0 commit comments

Comments
 (0)