Skip to content

Commit f3b3614

Browse files
Hari Bathiniacmel
Hari Bathini
authored andcommitted
perf tools: Add PERF_RECORD_NAMESPACES to include namespaces related info
Introduce a new option to record PERF_RECORD_NAMESPACES events emitted by the kernel when fork, clone, setns or unshare are invoked. And update perf-record documentation with the new option to record namespace events. Committer notes: Combined it with a later patch to allow printing it via 'perf report -D' and be able to test the feature introduced in this patch. Had to move here also perf_ns__name(), that was introduced in another later patch. Also used PRIu64 and PRIx64 to fix the build in some enfironments wrt: util/event.c:1129:39: error: format '%lx' expects argument of type 'long unsigned int', but argument 6 has type 'long long unsigned int' [-Werror=format=] ret += fprintf(fp, "%u/%s: %lu/0x%lx%s", idx ^ Testing it: # perf record --namespaces -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.083 MB perf.data (423 samples) ] # # perf report -D <SNIP> 3 2028902078892 0x115140 [0xa0]: PERF_RECORD_NAMESPACES 14783/14783 - nr_namespaces: 7 [0/net: 3/0xf0000081, 1/uts: 3/0xeffffffe, 2/ipc: 3/0xefffffff, 3/pid: 3/0xeffffffc, 4/user: 3/0xeffffffd, 5/mnt: 3/0xf0000000, 6/cgroup: 3/0xeffffffb] 0x1151e0 [0x30]: event: 9 . . ... raw event: size 48 bytes . 0000: 09 00 00 00 02 00 30 00 c4 71 82 68 0c 7f 00 00 ......0..q.h.... . 0010: a9 39 00 00 a9 39 00 00 94 28 fe 63 d8 01 00 00 .9...9...(.c.... . 0020: 03 00 00 00 00 00 00 00 ce c4 02 00 00 00 00 00 ................ <SNIP> NAMESPACES events: 1 <SNIP> # Signed-off-by: Hari Bathini <[email protected]> Acked-by: Jiri Olsa <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Ananth N Mavinakayanahalli <[email protected]> Cc: Aravinda Prasad <[email protected]> Cc: Brendan Gregg <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: Eric Biederman <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sargun Dhillon <[email protected]> Cc: Steven Rostedt <[email protected]> Link: http://lkml.kernel.org/r/148891930386.25309.18412039920746995488.stgit@hbathini.in.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent e422267 commit f3b3614

28 files changed

+296
-4
lines changed

tools/include/uapi/linux/perf_event.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ struct perf_event_attr {
344344
use_clockid : 1, /* use @clockid for time fields */
345345
context_switch : 1, /* context switch data */
346346
write_backward : 1, /* Write ring buffer from end to beginning */
347-
__reserved_1 : 36;
347+
namespaces : 1, /* include namespaces data */
348+
__reserved_1 : 35;
348349

349350
union {
350351
__u32 wakeup_events; /* wakeup every n events */
@@ -610,6 +611,23 @@ struct perf_event_header {
610611
__u16 size;
611612
};
612613

614+
struct perf_ns_link_info {
615+
__u64 dev;
616+
__u64 ino;
617+
};
618+
619+
enum {
620+
NET_NS_INDEX = 0,
621+
UTS_NS_INDEX = 1,
622+
IPC_NS_INDEX = 2,
623+
PID_NS_INDEX = 3,
624+
USER_NS_INDEX = 4,
625+
MNT_NS_INDEX = 5,
626+
CGROUP_NS_INDEX = 6,
627+
628+
NR_NAMESPACES, /* number of available namespaces */
629+
};
630+
613631
enum perf_event_type {
614632

615633
/*
@@ -862,6 +880,18 @@ enum perf_event_type {
862880
*/
863881
PERF_RECORD_SWITCH_CPU_WIDE = 15,
864882

883+
/*
884+
* struct {
885+
* struct perf_event_header header;
886+
* u32 pid;
887+
* u32 tid;
888+
* u64 nr_namespaces;
889+
* { u64 dev, inode; } [nr_namespaces];
890+
* struct sample_id sample_id;
891+
* };
892+
*/
893+
PERF_RECORD_NAMESPACES = 16,
894+
865895
PERF_RECORD_MAX, /* non-ABI */
866896
};
867897

tools/perf/Documentation/perf-record.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ Enable weightened sampling. An additional weight is recorded per sample and can
347347
displayed with the weight and local_weight sort keys. This currently works for TSX
348348
abort events and some memory events in precise mode on modern Intel CPUs.
349349

350+
--namespaces::
351+
Record events of type PERF_RECORD_NAMESPACES.
352+
350353
--transaction::
351354
Record transaction flags for transaction related events.
352355

tools/perf/builtin-annotate.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
393393
.comm = perf_event__process_comm,
394394
.exit = perf_event__process_exit,
395395
.fork = perf_event__process_fork,
396+
.namespaces = perf_event__process_namespaces,
396397
.ordered_events = true,
397398
.ordering_requires_timestamps = true,
398399
},

tools/perf/builtin-diff.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ static struct perf_tool tool = {
364364
.exit = perf_event__process_exit,
365365
.fork = perf_event__process_fork,
366366
.lost = perf_event__process_lost,
367+
.namespaces = perf_event__process_namespaces,
367368
.ordered_events = true,
368369
.ordering_requires_timestamps = true,
369370
};

tools/perf/builtin-inject.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,18 @@ static int perf_event__repipe_comm(struct perf_tool *tool,
333333
return err;
334334
}
335335

336+
static int perf_event__repipe_namespaces(struct perf_tool *tool,
337+
union perf_event *event,
338+
struct perf_sample *sample,
339+
struct machine *machine)
340+
{
341+
int err = perf_event__process_namespaces(tool, event, sample, machine);
342+
343+
perf_event__repipe(tool, event, sample, machine);
344+
345+
return err;
346+
}
347+
336348
static int perf_event__repipe_exit(struct perf_tool *tool,
337349
union perf_event *event,
338350
struct perf_sample *sample,
@@ -660,6 +672,7 @@ static int __cmd_inject(struct perf_inject *inject)
660672
session->itrace_synth_opts = &inject->itrace_synth_opts;
661673
inject->itrace_synth_opts.inject = true;
662674
inject->tool.comm = perf_event__repipe_comm;
675+
inject->tool.namespaces = perf_event__repipe_namespaces;
663676
inject->tool.exit = perf_event__repipe_exit;
664677
inject->tool.id_index = perf_event__repipe_id_index;
665678
inject->tool.auxtrace_info = perf_event__process_auxtrace_info;

tools/perf/builtin-kmem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ static struct perf_tool perf_kmem = {
964964
.comm = perf_event__process_comm,
965965
.mmap = perf_event__process_mmap,
966966
.mmap2 = perf_event__process_mmap2,
967+
.namespaces = perf_event__process_namespaces,
967968
.ordered_events = true,
968969
};
969970

tools/perf/builtin-kvm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ static int read_events(struct perf_kvm_stat *kvm)
10441044
struct perf_tool eops = {
10451045
.sample = process_sample_event,
10461046
.comm = perf_event__process_comm,
1047+
.namespaces = perf_event__process_namespaces,
10471048
.ordered_events = true,
10481049
};
10491050
struct perf_data_file file = {
@@ -1348,6 +1349,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
13481349
kvm->tool.exit = perf_event__process_exit;
13491350
kvm->tool.fork = perf_event__process_fork;
13501351
kvm->tool.lost = process_lost_event;
1352+
kvm->tool.namespaces = perf_event__process_namespaces;
13511353
kvm->tool.ordered_events = true;
13521354
perf_tool__fill_defaults(&kvm->tool);
13531355

tools/perf/builtin-lock.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ static int __cmd_report(bool display_info)
858858
struct perf_tool eops = {
859859
.sample = process_sample_event,
860860
.comm = perf_event__process_comm,
861+
.namespaces = perf_event__process_namespaces,
861862
.ordered_events = true,
862863
};
863864
struct perf_data_file file = {

tools/perf/builtin-mem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
342342
.lost = perf_event__process_lost,
343343
.fork = perf_event__process_fork,
344344
.build_id = perf_event__process_build_id,
345+
.namespaces = perf_event__process_namespaces,
345346
.ordered_events = true,
346347
},
347348
.input_name = "perf.data",

tools/perf/builtin-record.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
876876
signal(SIGTERM, sig_handler);
877877
signal(SIGSEGV, sigsegv_handler);
878878

879+
if (rec->opts.record_namespaces)
880+
tool->namespace_events = true;
881+
879882
if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
880883
signal(SIGUSR2, snapshot_sig_handler);
881884
if (rec->opts.auxtrace_snapshot_mode)
@@ -1497,6 +1500,7 @@ static struct record record = {
14971500
.fork = perf_event__process_fork,
14981501
.exit = perf_event__process_exit,
14991502
.comm = perf_event__process_comm,
1503+
.namespaces = perf_event__process_namespaces,
15001504
.mmap = perf_event__process_mmap,
15011505
.mmap2 = perf_event__process_mmap2,
15021506
.ordered_events = true,
@@ -1611,6 +1615,8 @@ static struct option __record_options[] = {
16111615
"opts", "AUX area tracing Snapshot Mode", ""),
16121616
OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
16131617
"per thread proc mmap processing timeout in ms"),
1618+
OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
1619+
"Record namespaces events"),
16141620
OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
16151621
"Record context switch events"),
16161622
OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,

tools/perf/builtin-report.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
700700
.mmap = perf_event__process_mmap,
701701
.mmap2 = perf_event__process_mmap2,
702702
.comm = perf_event__process_comm,
703+
.namespaces = perf_event__process_namespaces,
703704
.exit = perf_event__process_exit,
704705
.fork = perf_event__process_fork,
705706
.lost = perf_event__process_lost,

tools/perf/builtin-sched.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
32723272
.tool = {
32733273
.sample = perf_sched__process_tracepoint_sample,
32743274
.comm = perf_event__process_comm,
3275+
.namespaces = perf_event__process_namespaces,
32753276
.lost = perf_event__process_lost,
32763277
.fork = perf_sched__process_fork_event,
32773278
.ordered_events = true,

tools/perf/builtin-script.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
20972097
.mmap = perf_event__process_mmap,
20982098
.mmap2 = perf_event__process_mmap2,
20992099
.comm = perf_event__process_comm,
2100+
.namespaces = perf_event__process_namespaces,
21002101
.exit = perf_event__process_exit,
21012102
.fork = perf_event__process_fork,
21022103
.attr = process_attr,

tools/perf/builtin-trace.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,8 +2415,9 @@ static int trace__replay(struct trace *trace)
24152415
trace->tool.exit = perf_event__process_exit;
24162416
trace->tool.fork = perf_event__process_fork;
24172417
trace->tool.attr = perf_event__process_attr;
2418-
trace->tool.tracing_data = perf_event__process_tracing_data;
2418+
trace->tool.tracing_data = perf_event__process_tracing_data;
24192419
trace->tool.build_id = perf_event__process_build_id;
2420+
trace->tool.namespaces = perf_event__process_namespaces;
24202421

24212422
trace->tool.ordered_events = true;
24222423
trace->tool.ordering_requires_timestamps = true;

tools/perf/perf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct record_opts {
5050
bool running_time;
5151
bool full_auxtrace;
5252
bool auxtrace_snapshot_mode;
53+
bool record_namespaces;
5354
bool record_switch_events;
5455
bool all_kernel;
5556
bool all_user;

tools/perf/util/Build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ libperf-y += pstack.o
4242
libperf-y += session.o
4343
libperf-$(CONFIG_AUDIT) += syscalltbl.o
4444
libperf-y += ordered-events.o
45+
libperf-y += namespaces.o
4546
libperf-y += comm.o
4647
libperf-y += thread.o
4748
libperf-y += thread_map.o

tools/perf/util/data-convert-bt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
14681468
.lost = perf_event__process_lost,
14691469
.tracing_data = perf_event__process_tracing_data,
14701470
.build_id = perf_event__process_build_id,
1471+
.namespaces = perf_event__process_namespaces,
14711472
.ordered_events = true,
14721473
.ordering_requires_timestamps = true,
14731474
},

tools/perf/util/event.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static const char *perf_event__names[] = {
3131
[PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES",
3232
[PERF_RECORD_SWITCH] = "SWITCH",
3333
[PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE",
34+
[PERF_RECORD_NAMESPACES] = "NAMESPACES",
3435
[PERF_RECORD_HEADER_ATTR] = "ATTR",
3536
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
3637
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@@ -49,6 +50,16 @@ static const char *perf_event__names[] = {
4950
[PERF_RECORD_TIME_CONV] = "TIME_CONV",
5051
};
5152

53+
static const char *perf_ns__names[] = {
54+
[NET_NS_INDEX] = "net",
55+
[UTS_NS_INDEX] = "uts",
56+
[IPC_NS_INDEX] = "ipc",
57+
[PID_NS_INDEX] = "pid",
58+
[USER_NS_INDEX] = "user",
59+
[MNT_NS_INDEX] = "mnt",
60+
[CGROUP_NS_INDEX] = "cgroup",
61+
};
62+
5263
const char *perf_event__name(unsigned int id)
5364
{
5465
if (id >= ARRAY_SIZE(perf_event__names))
@@ -58,6 +69,13 @@ const char *perf_event__name(unsigned int id)
5869
return perf_event__names[id];
5970
}
6071

72+
static const char *perf_ns__name(unsigned int id)
73+
{
74+
if (id >= ARRAY_SIZE(perf_ns__names))
75+
return "UNKNOWN";
76+
return perf_ns__names[id];
77+
}
78+
6179
static int perf_tool__process_synth_event(struct perf_tool *tool,
6280
union perf_event *event,
6381
struct machine *machine,
@@ -1008,6 +1026,33 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
10081026
return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
10091027
}
10101028

1029+
size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp)
1030+
{
1031+
size_t ret = 0;
1032+
struct perf_ns_link_info *ns_link_info;
1033+
u32 nr_namespaces, idx;
1034+
1035+
ns_link_info = event->namespaces.link_info;
1036+
nr_namespaces = event->namespaces.nr_namespaces;
1037+
1038+
ret += fprintf(fp, " %d/%d - nr_namespaces: %u\n\t\t[",
1039+
event->namespaces.pid,
1040+
event->namespaces.tid,
1041+
nr_namespaces);
1042+
1043+
for (idx = 0; idx < nr_namespaces; idx++) {
1044+
if (idx && (idx % 4 == 0))
1045+
ret += fprintf(fp, "\n\t\t ");
1046+
1047+
ret += fprintf(fp, "%u/%s: %" PRIu64 "/%#" PRIx64 "%s", idx,
1048+
perf_ns__name(idx), (u64)ns_link_info[idx].dev,
1049+
(u64)ns_link_info[idx].ino,
1050+
((idx + 1) != nr_namespaces) ? ", " : "]\n");
1051+
}
1052+
1053+
return ret;
1054+
}
1055+
10111056
int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
10121057
union perf_event *event,
10131058
struct perf_sample *sample,
@@ -1016,6 +1061,14 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
10161061
return machine__process_comm_event(machine, event, sample);
10171062
}
10181063

1064+
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused,
1065+
union perf_event *event,
1066+
struct perf_sample *sample,
1067+
struct machine *machine)
1068+
{
1069+
return machine__process_namespaces_event(machine, event, sample);
1070+
}
1071+
10191072
int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
10201073
union perf_event *event,
10211074
struct perf_sample *sample,
@@ -1196,6 +1249,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
11961249
case PERF_RECORD_MMAP:
11971250
ret += perf_event__fprintf_mmap(event, fp);
11981251
break;
1252+
case PERF_RECORD_NAMESPACES:
1253+
ret += perf_event__fprintf_namespaces(event, fp);
1254+
break;
11991255
case PERF_RECORD_MMAP2:
12001256
ret += perf_event__fprintf_mmap2(event, fp);
12011257
break;

tools/perf/util/event.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ struct comm_event {
3939
char comm[16];
4040
};
4141

42+
struct namespaces_event {
43+
struct perf_event_header header;
44+
u32 pid, tid;
45+
u64 nr_namespaces;
46+
struct perf_ns_link_info link_info[];
47+
};
48+
4249
struct fork_event {
4350
struct perf_event_header header;
4451
u32 pid, ppid;
@@ -485,6 +492,7 @@ union perf_event {
485492
struct mmap_event mmap;
486493
struct mmap2_event mmap2;
487494
struct comm_event comm;
495+
struct namespaces_event namespaces;
488496
struct fork_event fork;
489497
struct lost_event lost;
490498
struct lost_samples_event lost_samples;
@@ -587,6 +595,10 @@ int perf_event__process_switch(struct perf_tool *tool,
587595
union perf_event *event,
588596
struct perf_sample *sample,
589597
struct machine *machine);
598+
int perf_event__process_namespaces(struct perf_tool *tool,
599+
union perf_event *event,
600+
struct perf_sample *sample,
601+
struct machine *machine);
590602
int perf_event__process_mmap(struct perf_tool *tool,
591603
union perf_event *event,
592604
struct perf_sample *sample,
@@ -653,6 +665,7 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
653665
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
654666
size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
655667
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
668+
size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
656669
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
657670

658671
u64 kallsyms__get_function_start(const char *kallsyms_filename,

tools/perf/util/evsel.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
932932
attr->mmap2 = track && !perf_missing_features.mmap2;
933933
attr->comm = track;
934934

935+
if (opts->record_namespaces)
936+
attr->namespaces = track;
937+
935938
if (opts->record_switch_events)
936939
attr->context_switch = track;
937940

0 commit comments

Comments
 (0)