mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +00:00
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: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
98
namespaces.c
98
namespaces.c
@@ -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;
|
||||
|
Reference in New Issue
Block a user