When a process is in a namespace, its pid, tid and ppid are relative to
the namespace. Since namespaces can be nested, we need to know the
representation of each process in each namespace.
This patch changes the lttng_enumerate_task_fd to iterate over each
PID namespace of a process if any, that way we generate, in the
statedump, an entry for each process in each namespace it belongs.
To know the nesting level, the field "level" is added to the
lttng_statedump_process_state event, 0 being the top-level.
For processes running on the top-level namespace, the statedump
behaviour is unchanged (except the added "level" field).
For example (no nesting, just one level of namespace) :
lttng_statedump_process_state: {
tid = 32185, vtid = 1, pid = 32185,
vpid = 1, ppid = 32173, vppid = 0,
level = 1, name = "init" }
lttng_statedump_process_state: {
tid = 32185, vtid = 32185, pid = 32185,
vpid = 32185, ppid = 32173, vppid = 32173,
level = 0, name = "init" }
Confirmed that the process 32173 in the top-level namespace is indeed
the lxc-start command that created the container and its namespace.
[ Edit by Mathieu Desnoyers: Minor cleanups ]
Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#include <linux/tracepoint.h>
#include <linux/nsproxy.h>
#include <linux/tracepoint.h>
#include <linux/nsproxy.h>
+#include <linux/pid_namespace.h>
TRACE_EVENT(lttng_statedump_start,
TP_PROTO(struct lttng_session *session),
TRACE_EVENT(lttng_statedump_start,
TP_PROTO(struct lttng_session *session),
TRACE_EVENT(lttng_statedump_process_state,
TP_PROTO(struct lttng_session *session,
struct task_struct *p,
TRACE_EVENT(lttng_statedump_process_state,
TP_PROTO(struct lttng_session *session,
struct task_struct *p,
- int type, int mode, int submode, int status),
- TP_ARGS(session, p, type, mode, submode, status),
+ int type, int mode, int submode, int status,
+ struct pid_namespace *pid_ns),
+ TP_ARGS(session, p, type, mode, submode, status, pid_ns),
TP_STRUCT__entry(
__field(pid_t, tid)
__field(pid_t, vtid)
TP_STRUCT__entry(
__field(pid_t, tid)
__field(pid_t, vtid)
__field(int, mode)
__field(int, submode)
__field(int, status)
__field(int, mode)
__field(int, submode)
__field(int, status)
),
TP_fast_assign(
tp_assign(tid, p->pid)
),
TP_fast_assign(
tp_assign(tid, p->pid)
- tp_assign(vtid,
- ({
- struct nsproxy *proxy;
- pid_t ret = 0;
-
- rcu_read_lock();
- proxy = task_nsproxy(p);
- if (proxy) {
- ret = task_pid_nr_ns(p,
- proxy->pid_ns);
- }
- rcu_read_unlock();
- ret;
- }))
+ tp_assign(vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
- tp_assign(vpid,
- ({
- struct nsproxy *proxy;
- pid_t ret = 0;
-
- rcu_read_lock();
- proxy = task_nsproxy(p);
- if (proxy) {
- ret = task_tgid_nr_ns(p,
- proxy->pid_ns);
- }
- rcu_read_unlock();
- ret;
- }))
+ tp_assign(vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
tp_assign(ppid,
({
pid_t ret;
tp_assign(ppid,
({
pid_t ret;
tp_assign(vppid,
({
struct task_struct *parent;
tp_assign(vppid,
({
struct task_struct *parent;
pid_t ret = 0;
rcu_read_lock();
parent = rcu_dereference(p->real_parent);
pid_t ret = 0;
rcu_read_lock();
parent = rcu_dereference(p->real_parent);
- proxy = task_nsproxy(parent);
- if (proxy) {
- ret = task_tgid_nr_ns(parent,
- proxy->pid_ns);
- }
+ ret = task_tgid_nr_ns(parent, pid_ns);
rcu_read_unlock();
ret;
}))
rcu_read_unlock();
ret;
}))
tp_assign(mode, mode)
tp_assign(submode, submode)
tp_assign(status, status)
tp_assign(mode, mode)
tp_assign(submode, submode)
tp_assign(status, status)
+ tp_assign(ns_level, pid_ns ? pid_ns->level : 0)
+static
+void lttng_statedump_process_ns(struct lttng_session *session,
+ struct task_struct *p,
+ enum lttng_thread_type type,
+ enum lttng_execution_mode mode,
+ enum lttng_execution_submode submode,
+ enum lttng_process_status status)
+{
+ struct nsproxy *proxy;
+ struct pid_namespace *pid_ns;
+
+ rcu_read_lock();
+ proxy = task_nsproxy(p);
+ if (proxy) {
+ pid_ns = proxy->pid_ns;
+ do {
+ trace_lttng_statedump_process_state(session,
+ p, type, mode, submode, status, pid_ns);
+ } while (pid_ns);
+ } else {
+ trace_lttng_statedump_process_state(session,
+ p, type, mode, submode, status, NULL);
+ }
+ rcu_read_unlock();
+}
+
static
int lttng_enumerate_process_states(struct lttng_session *session)
{
static
int lttng_enumerate_process_states(struct lttng_session *session)
{
type = LTTNG_USER_THREAD;
else
type = LTTNG_KERNEL_THREAD;
type = LTTNG_USER_THREAD;
else
type = LTTNG_KERNEL_THREAD;
- trace_lttng_statedump_process_state(session,
+ lttng_statedump_process_ns(session,
p, type, mode, submode, status);
task_unlock(p);
} while_each_thread(g, p);
p, type, mode, submode, status);
task_unlock(p);
} while_each_thread(g, p);