lkml.org 
[lkml]   [2016]   [Nov]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH 1/3] perf: add PERF_RECORD_NAMESPACES to include namespaces related info
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];

?

> +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.

> +
> + 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.

\
 
 \ /
  Last update: 2016-11-10 14:20    [W:0.095 / U:0.460 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site