Commit 2105e18e authored by Pavel Emelyanov's avatar Pavel Emelyanov

core: Save tasks' namespaces IDs in the ids image

The recent kernels allow to get namespaces IDs by reading proc-ns links.
Use this to generate IDs for tasks' namespaces (I do generate them, since
IDs provided by kernel look ugly :( ).
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 47c98c63
......@@ -913,6 +913,10 @@ static int dump_task_ids(struct pstree_item *item, const struct cr_fdset *cr_fds
if (ret)
goto err_free;
ret = dump_task_ns_ids(item);
if (ret)
goto err_free;
ret = pb_write_one(fd_ids, item->ids, PB_IDS);
if (ret < 0)
goto err_free;
......
......@@ -18,4 +18,7 @@ int switch_ns(int pid, struct ns_desc *nd, int *rst);
int restore_ns(int rst, struct ns_desc *nd);
extern struct ns_desc pid_ns_desc;
struct pstree_item;
int dump_task_ns_ids(struct pstree_item *);
#endif /* __CR_NS_H__ */
......@@ -61,6 +61,104 @@ int restore_ns(int rst, struct ns_desc *nd)
return ret;
}
struct ns_id {
unsigned int kid;
unsigned int id;
struct ns_desc *nd;
struct ns_id *next;
};
static struct ns_id *ns_ids;
static unsigned int ns_next_id = 1;
static unsigned int generate_ns_id(unsigned int kid, struct ns_desc *nd)
{
struct ns_id *nsid;
for (nsid = ns_ids; nsid != NULL; nsid = nsid->next)
if (nsid->kid == kid && nsid->nd == nd)
return nsid->id;
nsid = xmalloc(sizeof(*nsid));
if (!nsid)
return 0;
nsid->id = ns_next_id++;
nsid->kid = kid;
nsid->nd = nd;
nsid->next = ns_ids;
ns_ids = nsid;
pr_info("Collected %u.%s namespace\n", nsid->id, nd->str);
return nsid->id;
}
static unsigned int get_ns_id(int pid, struct ns_desc *nd)
{
int proc_dir, ret;
unsigned int kid;
char ns_path[10], ns_id[32], *end;
proc_dir = open_pid_proc(pid);
if (proc_dir < 0)
return 0;
sprintf(ns_path, "ns/%s", nd->str);
ret = readlinkat(proc_dir, ns_path, ns_id, sizeof(ns_id));
if (ret < 0) {
pr_perror("Can't readlink ns link");
return 0;
}
/* XXX: Does it make sence to validate kernel links to <name>:[<id>]? */
kid = strtoul(ns_id + strlen(nd->str) + 2, &end, 10);
return generate_ns_id(kid, nd);
}
int dump_task_ns_ids(struct pstree_item *item)
{
int pid = item->pid.real;
TaskKobjIdsEntry *ids = item->ids;
ids->has_pid_ns_id = true;
ids->pid_ns_id = get_ns_id(pid, &pid_ns_desc);
if (!ids->pid_ns_id) {
pr_err("Can't make pidns id\n");
return -1;
}
ids->has_net_ns_id = true;
ids->net_ns_id = get_ns_id(pid, &net_ns_desc);
if (!ids->net_ns_id) {
pr_err("Can't make netns id\n");
return -1;
}
ids->has_ipc_ns_id = true;
ids->ipc_ns_id = get_ns_id(pid, &ipc_ns_desc);
if (!ids->ipc_ns_id) {
pr_err("Can't make ipcns id\n");
return -1;
}
ids->has_uts_ns_id = true;
ids->uts_ns_id = get_ns_id(pid, &uts_ns_desc);
if (!ids->uts_ns_id) {
pr_err("Can't make utsns id\n");
return -1;
}
ids->has_mnt_ns_id = true;
ids->mnt_ns_id = get_ns_id(pid, &mnt_ns_desc);
if (!ids->mnt_ns_id) {
pr_err("Can't make mntns id\n");
return -1;
}
return 0;
}
static int do_dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
{
struct cr_fdset *fdset;
......
......@@ -70,6 +70,12 @@ message task_kobj_ids_entry {
required uint32 files_id = 2;
required uint32 fs_id = 3;
required uint32 sighand_id = 4;
optional uint32 pid_ns_id = 5;
optional uint32 net_ns_id = 6;
optional uint32 ipc_ns_id = 7;
optional uint32 uts_ns_id = 8;
optional uint32 mnt_ns_id = 9;
}
message thread_info_x86 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment