[PATCH 8/9] ns: Add c/r for /proc/$pid/ns/$ids references
Cyrill Gorcunov
gorcunov at openvz.org
Mon May 20 04:59:45 EDT 2013
In this commit we implement c/r for files which have opened
/proc/$pid/ns/$ids entries.
The idea is rather simple one
Checkpoint
==========
- Check if the file name is the one of known to be ns ref
- If match then write protobuf entry
Restore
=======
- Read all ns entries from the image
- When criu tries to open one we lookup over process
tree to figure out which PID should be used in path
and then just open it
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
cr-restore.c | 3 ++
files.c | 12 ++---
include/files.h | 2 +
include/namespaces.h | 4 ++
namespaces.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 145 insertions(+), 7 deletions(-)
diff --git a/cr-restore.c b/cr-restore.c
index c76eed8..08dc970 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -124,6 +124,9 @@ static int root_prepare_shared(void)
if (collect_reg_files())
return -1;
+ if (collect_ns_files())
+ return -1;
+
if (collect_pipes())
return -1;
diff --git a/files.c b/files.c
index 2c40c5f..af1bffc 100644
--- a/files.c
+++ b/files.c
@@ -263,20 +263,18 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
}
if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode)) {
- struct ns_proc_entry found;
+ struct ns_proc_entry found = { };
struct fd_link link;
if (fill_fdlink(lfd, &p, &link))
return -1;
p.link = &link;
+ p.arg = &found;
- if (link.name[1] == '/') {
+ if (link.name[1] == '/')
return dump_reg_file(&p, lfd, fdinfo);
- } else if (check_ns_proc(&link.name[1], link.len - 1, &found) == 0) {
- pr_err("Found ns link %s:%li, not yet supported\n",
- found.d->str, found.i_ino);
- return -1;
- }
+ else if (check_ns_proc(&link.name[1], link.len - 1, &found) == 0)
+ return dump_ns_file(&p, lfd, fdinfo);
}
if (S_ISFIFO(p.stat.st_mode)) {
diff --git a/include/files.h b/include/files.h
index 9e49d1f..c923a6b 100644
--- a/include/files.h
+++ b/include/files.h
@@ -31,6 +31,7 @@ struct fd_parms {
pid_t pid;
FownEntry fown;
struct fd_link *link;
+ void *arg;
struct parasite_ctl *ctl;
};
@@ -40,6 +41,7 @@ struct fd_parms {
.fd = FD_DESC_INVALID, \
.fown = FOWN_ENTRY__INIT, \
.link = NULL, \
+ .arg = NULL, \
}
extern int fill_fdlink(int lfd, struct fd_parms *p, struct fd_link *link);
diff --git a/include/namespaces.h b/include/namespaces.h
index a646ea7..59914d6 100644
--- a/include/namespaces.h
+++ b/include/namespaces.h
@@ -3,6 +3,7 @@
#include "crtools.h"
#include "pstree.h"
+#include "files.h"
struct cr_options;
@@ -30,6 +31,9 @@ extern struct ns_desc pid_ns_desc;
extern struct ns_desc user_ns_desc;
extern unsigned long current_ns_mask;
+extern int dump_ns_file(struct fd_parms *p, int lfd, const int fdinfo);
+extern int collect_ns_files(void);
+
int dump_namespaces(struct pid *pid, unsigned int ns_flags);
int prepare_namespace(int pid, unsigned long clone_flags);
int try_show_namespaces(int pid, struct cr_options *o);
diff --git a/namespaces.c b/namespaces.c
index 7ba1309..b45a19a 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -10,6 +10,9 @@
#include "namespaces.h"
#include "net.h"
+#include "protobuf.h"
+#include "protobuf/ns.pb-c.h"
+
struct ns_desc *ns_desc_array[] = {
&net_ns_desc,
&uts_ns_desc,
@@ -175,6 +178,134 @@ static unsigned int get_ns_id(int pid, struct ns_desc *nd)
return generate_ns_id(pid, kid, nd);
}
+int dump_one_ns_file(int lfd, u32 id, const struct fd_parms *p)
+{
+ int fd = fdset_fd(glob_fdset, CR_FD_NS_FILES);
+ NsFileEntry nfe = NS_FILE_ENTRY__INIT;
+ struct ns_proc_entry *entry = p->arg;
+ unsigned int ns_id;
+
+ ns_id = generate_ns_id(p->pid, entry->i_ino, entry->d);
+ if (!ns_id) {
+ pr_err("Can't generate NS ID with kid %li\n", entry->i_ino);
+ return -1;
+ }
+
+ nfe.id = id;
+ nfe.ns_id = ns_id;
+ nfe.cflag = entry->d->cflag;
+ nfe.flags = p->flags;
+
+ return pb_write_one(fd, &nfe, PB_NS_FILES);
+}
+
+static const struct fdtype_ops nsfile_ops = {
+ .type = FD_TYPES__NS,
+ .dump = dump_one_ns_file,
+};
+
+int dump_ns_file(struct fd_parms *p, int lfd, const int fdinfo)
+{
+ return do_dump_gen_file(p, lfd, &nsfile_ops, fdinfo);
+}
+
+struct ns_file_info {
+ struct file_desc d;
+ NsFileEntry *nfe;
+};
+
+static int open_ns_fd(struct file_desc *d)
+{
+ struct ns_file_info *nfi = container_of(d, struct ns_file_info, d);
+ struct pstree_item *item, *t;
+ struct ns_desc *nd = NULL;
+ char path[64];
+ int fd;
+
+ /*
+ * Find out who can open us.
+ *
+ * FIXME I need a hash or RBtree here.
+ */
+ for_each_pstree_item(t) {
+ TaskKobjIdsEntry *ids = t->ids;
+
+ if (ids->pid_ns_id == nfi->nfe->ns_id) {
+ item = t;
+ nd = &pid_ns_desc;
+ break;
+ } else if (ids->net_ns_id == nfi->nfe->ns_id) {
+ item = t;
+ nd = &net_ns_desc;
+ break;
+ } else if (ids->ipc_ns_id == nfi->nfe->ns_id) {
+ item = t;
+ nd = &ipc_ns_desc;
+ break;
+ } else if (ids->uts_ns_id == nfi->nfe->ns_id) {
+ item = t;
+ nd = &uts_ns_desc;
+ break;
+ } else if (ids->mnt_ns_id == nfi->nfe->ns_id) {
+ item = t;
+ nd = &mnt_ns_desc;
+ break;
+ }
+ }
+
+ if (!nd || !item) {
+ pr_err("Can't find suitable NS ID for %#x\n",
+ nfi->nfe->ns_id);
+ return -1;
+ } else if (nd->cflag != nfi->nfe->cflag) {
+ pr_err("Clone flag mismatch for %#x\n",
+ nfi->nfe->ns_id);
+ return -1;
+ }
+
+ snprintf(path, sizeof(path) - 1, "/proc/%d/ns/%s",
+ item->pid.virt, nd->str);
+ path[sizeof(path) - 1] = '\0';
+
+ fd = open(path, nfi->nfe->flags);
+ if (fd < 0) {
+ pr_perror("Can't open file %s on restore", path);
+ return fd;
+ }
+
+ return fd;
+}
+
+static struct file_desc_ops ns_desc_ops = {
+ .type = FD_TYPES__NS,
+ .open = open_ns_fd,
+};
+
+static int collect_one_nsfile(void *o, ProtobufCMessage *base)
+{
+ struct ns_file_info *nfi = o;
+
+ nfi->nfe = pb_msg(base, NsFileEntry);
+
+ pr_info("Collected ns file ID %#x NS-ID %#x\n",
+ nfi->nfe->id, nfi->nfe->ns_id);
+ file_desc_add(&nfi->d, nfi->nfe->id, &ns_desc_ops);
+
+ return 0;
+}
+
+int collect_ns_files(void)
+{
+ int ret;
+
+ ret = collect_image(CR_FD_NS_FILES, PB_NS_FILES,
+ sizeof(struct ns_file_info),
+ collect_one_nsfile);
+ if (ret < 0 && errno == ENOENT)
+ ret = 0;
+ return ret;
+}
+
int dump_task_ns_ids(struct pstree_item *item)
{
int pid = item->pid.real;
--
1.8.1.4
--Nq2Wo0NMKNjxTN9z--
More information about the CRIU
mailing list