On Thursday 10 November 2016 06:49 PM, Peter Zijlstra wrote:
On Thu, Nov 10, 2016 at 05:08:06PM +0530, Hari Bathini wrote:diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index c66a485..575aed6 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -344,7 +344,8 @@ struct perf_event_attr { use_clockid : 1, /* use @clockid for time fields */ context_switch : 1, /* context switch data */ write_backward : 1, /* Write ring buffer from end to beginning */ - __reserved_1 : 36; + namespaces : 1, /* include namespaces data */ + __reserved_1 : 35;union {__u32 wakeup_events; /* wakeup every n events */ @@ -862,6 +863,24 @@ enum perf_event_type { */ PERF_RECORD_SWITCH_CPU_WIDE = 15,+ /*+ * struct { + * struct perf_event_header header; + * + * u32 pid, tid; + * u64 time; + * u32 uts_ns_inum; + * u32 ipc_ns_inum; + * u32 mnt_ns_inum; + * u32 pid_ns_inum; + * u32 net_ns_inum; + * u32 cgroup_ns_inum; + * u32 user_ns_inum; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_NAMESPACES = 16,So this format is not extensible, that is, if someone adds yet another namespace, we'll need to introduce PERF_RECORD_NAMESPACES2. Is there a 'natural' and exposed namespace index that we can use to change it like: u32 nr_nss; u32 namespace[nr_nss]; ?
Hi Peter, Nothing of that sort exists, currently. Maybe, time to introduce with this patch-set..?
+static void perf_event_namespaces_output(struct perf_event *event, + void *data) +{ + struct perf_namespaces_event *namespaces_event = data; + struct perf_output_handle handle; + struct perf_sample_data sample; + int size = namespaces_event->event_id.header.size; + struct nsproxy *nsproxy; + int ret; + + if (!perf_event_namespaces_match(event)) + return; + + perf_event_header__init_id(&namespaces_event->event_id.header, + &sample, event); + ret = perf_output_begin(&handle, event, + namespaces_event->event_id.header.size); + + if (ret) + goto out;If you were to introduce: struct ns_event_id *ei = &namespace_event->event_id;+ + namespaces_event->event_id.pid = perf_event_pid(event, + namespaces_event->task); + namespaces_event->event_id.tid = perf_event_tid(event, + namespaces_event->task); + + if (namespaces_event->task != current) + task_lock(namespaces_event->task); + + nsproxy = namespaces_event->task->nsproxy; + if (nsproxy != NULL) { + namespaces_event->event_id.uts_ns_inum = + nsproxy->uts_ns->ns.inum; +#ifdef CONFIG_IPC_NS + namespaces_event->event_id.ipc_ns_inum = + nsproxy->ipc_ns->ns.inum; +#endif + namespaces_event->event_id.mnt_ns_inum = + nsproxy->mnt_ns->ns.inum; + namespaces_event->event_id.pid_ns_inum = + nsproxy->pid_ns_for_children->ns.inum; +#ifdef CONFIG_NET + namespaces_event->event_id.net_ns_inum = + nsproxy->net_ns->ns.inum; +#endif +#ifdef CONFIG_CGROUPS + namespaces_event->event_id.cgroup_ns_inum = + nsproxy->cgroup_ns->ns.inum; +#endif + } + + namespaces_event->event_id.user_ns_inum = + __task_cred(namespaces_event->task)->user_ns->ns.inum;You can do s/namespace_event->event_id./ei->/ which is tons shorter and would result in less wrapping of lines and generally improve readability.
True.
+ + if (namespaces_event->task != current) + task_unlock(namespaces_event->task); + + namespaces_event->event_id.time = perf_event_clock(event); + + perf_output_put(&handle, namespaces_event->event_id); + + perf_event__output_id_sample(event, &handle, &sample); + + perf_output_end(&handle); +out: + namespaces_event->event_id.header.size = size; +} + +void perf_event_namespaces(struct task_struct *task) +{ + struct perf_namespaces_event namespaces_event; + + if (!atomic_read(&nr_namespaces_events)) + return; + + namespaces_event = (struct perf_namespaces_event){ + .task = task, + .event_id = { + .header = { + .type = PERF_RECORD_NAMESPACES, + .misc = 0, + .size = sizeof(namespaces_event.event_id), + }, + /* .pid */ + /* .tid */ + /* .time */ + /* .uts_ns_inum */ + /* .ipc_ns_inum */ + /* .mnt_ns_inum */ + /* .pid_ns_inum */ + /* .net_ns_inum */ + /* .cgroup_ns_inum */ + /* .user_ns_inum */ + }, + }; + + perf_iterate_sb(perf_event_namespaces_output, + &namespaces_event, + NULL); +} diff --git a/kernel/fork.c b/kernel/fork.c index 997ac1d..3faca3d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1818,6 +1818,7 @@ static __latent_entropy struct task_struct *copy_process( cgroup_post_fork(p); threadgroup_change_end(current); perf_event_fork(p); + perf_event_namespaces(p);I would much prefer calling perf_event_namespace() from perf_event_fork() and reduce the external interface.
OK. Will update.. Thanks Hari

