[CRIU] [PATCH] [POC][RFC] send inherit-fd descriptors from the criu process
Andrey Vagin
avagin at openvz.org
Thu Nov 27 04:20:42 PST 2014
File descriptors are not copied in other processes, so we don't have
conflicts with restored file descriptors.
Opened questions:
* Do we need one more fd type for inherit-fd-s. If we need, how to
restore properties, which are specific for sockets, pipes, ets
* How to handle a case, when we have two file descriptors for the same
file, but one opens the file for read-only and other one opens the
same file for write-only.
* How to handle shared struct-files. When we have a few sets of file
descriprots, where a "struct file" is shared inside a set. And all
these "struct file"-s points on the same physical file, fifo, pipe,
etc.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-restore.c | 14 +++++--
files.c | 24 +----------
include/files.h | 8 +++-
pipes.c | 80 +++++++++++++++++++++++++++++-------
test/zdtm/live/static/Makefile | 1 +
test/zdtm/live/static/pipe-inherit.c | 48 ++++++++++++++++++++++
util.c | 7 ----
7 files changed, 133 insertions(+), 49 deletions(-)
create mode 100644 test/zdtm/live/static/pipe-inherit.c
diff --git a/cr-restore.c b/cr-restore.c
index 93a6ca6..b614f4f 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1446,9 +1446,6 @@ static int restore_task_with_children(void *_arg)
if (close_old_fds(current))
goto err_fini_mnt;
- if (root_prepare_shared())
- goto err_fini_mnt;
-
if (restore_finish_stage(CR_STATE_RESTORE_SHARED) < 0)
goto err_fini_mnt;
}
@@ -1665,6 +1662,7 @@ static void ignore_kids(void)
pr_perror("Restoring CHLD sigaction failed");
}
+extern int inherit_fd_send(int pid);
static int restore_root_task(struct pstree_item *init)
{
enum trace_flags flag = TRACE_ALL;
@@ -1756,7 +1754,12 @@ static int restore_root_task(struct pstree_item *init)
timing_stop(TIME_FORK);
- ret = restore_switch_stage(CR_STATE_RESTORE);
+ __restore_switch_stage(CR_STATE_RESTORE);
+
+ if (inherit_fd_send(getpid()))
+ goto out_kill;
+
+ ret = restore_wait_inprogress_tasks();
if (ret < 0)
goto out_kill;
@@ -1898,6 +1901,9 @@ int cr_restore_tasks(void)
if (criu_signals_setup() < 0)
goto err;
+ if (root_prepare_shared())
+ goto err;
+
if (restore_root_task(root_item) < 0)
goto err;
diff --git a/files.c b/files.c
index 7bace3a..84e8d11 100644
--- a/files.c
+++ b/files.c
@@ -1223,12 +1223,6 @@ int shared_fdt_prepare(struct pstree_item *item)
* +---> criu restore ... --inherit-fd fd[1]:pipe:[686787] fd[2]:pipe:[686788]
*/
-struct inherit_fd {
- char *inh_id; /* identifier */
- int inh_fd; /* file descriptor to restore from */
- struct list_head l;
-};
-
/*
* We can't print diagnostics messages in this function because the
* log file isn't initialized yet.
@@ -1286,6 +1280,7 @@ int inherit_fd_add(char *optarg)
inh->inh_id = cp;
inh->inh_fd = fd;
list_add_tail(&inh->l, &opts.inherit_fds);
+ INIT_LIST_HEAD(&inh->files);
return 0;
}
@@ -1342,20 +1337,3 @@ int inherit_fd_lookup_id(char *id, bool need_fd)
return -1;
}
-
-/*
- * Look up the inherit fd list by a file descriptor.
- */
-bool inherit_fd_lookup_fd(int fd)
-{
- struct inherit_fd *inh;
-
- list_for_each_entry(inh, &opts.inherit_fds, l) {
- if (inh->inh_fd == fd) {
- pr_info("File descriptor %d in inherit fd list\n", fd);
- return true;
- }
- }
-
- return false;
-}
diff --git a/include/files.h b/include/files.h
index e4e304f..2bc9fec 100644
--- a/include/files.h
+++ b/include/files.h
@@ -170,10 +170,16 @@ extern int dump_unsupp_fd(struct fd_parms *p, int lfd,
#define INHERIT_FD 0xcafebabe /* marker */
+struct inherit_fd {
+ char *inh_id; /* identifier */
+ int inh_fd; /* file descriptor to restore from */
+ struct list_head l;
+ struct list_head files;
+};
+
extern int inherit_fd_add(char *optarg);
extern void inherit_fd_log(void);
extern int inherit_fd_validate_fds(void);
extern int inherit_fd_lookup_id(char *id, bool need_fd);
-extern bool inherit_fd_lookup_fd(int fd);
#endif /* __CR_FILES_H__ */
diff --git a/pipes.c b/pipes.c
index 73bc790..1469000 100644
--- a/pipes.c
+++ b/pipes.c
@@ -10,6 +10,9 @@
#include "files.h"
#include "pipes.h"
#include "util-pie.h"
+#include "cr_options.h"
+#include "namespaces.h"
+#include "net.h"
#include "protobuf.h"
#include "protobuf/pipe.pb-c.h"
@@ -109,6 +112,54 @@ int collect_pipe_data(int img_type, struct pipe_data_rst **hash)
return ret;
}
+int inherit_fd_collect(char *id, struct pipe_info *pi)
+{
+ struct inherit_fd *inh;
+
+ list_for_each_entry(inh, &opts.inherit_fds, l) {
+ if (!strcmp(inh->inh_id, id)) {
+ pr_info("File identifier %s in inherit fd list\n", id);
+ list_add(&pi->pipe_list, &inh->files);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int inherit_fd_send(int pid)
+{
+ struct inherit_fd *inh;
+ struct pipe_info *p;
+ int rst, sock;
+
+ if (switch_ns(pid, &net_ns_desc, &rst))
+ return -1;
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pr_perror("Can't create socket");
+ restore_ns(rst, &net_ns_desc);
+ return -1;
+ }
+ restore_ns(rst, &net_ns_desc);
+
+ list_for_each_entry(inh, &opts.inherit_fds, l) {
+ list_for_each_entry(p, &inh->files, pipe_list) {
+ struct fdinfo_list_entry *fle;
+
+ fle = file_master(&p->d);
+
+ if (send_fd_to_peer(inh->inh_fd, fle, sock)) {
+ pr_perror("Can't send file descriptor");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static char *pipe_id_string(int pipe_id);
/* Choose who will restore a pipe. */
void mark_pipe_master(void)
{
@@ -120,6 +171,7 @@ void mark_pipe_master(void)
struct fdinfo_list_entry *fle;
struct pipe_info *pi, *pic, *p;
struct pipe_info *pr = NULL, *pw = NULL;
+ char *pipe_name;
if (list_empty(&pipes))
break;
@@ -132,6 +184,18 @@ void mark_pipe_master(void)
fle = file_master(&pi->d);
p = pi;
+
+ pipe_name = pipe_id_string(pi->pe->pipe_id);
+ if (pi->pe->flags == INHERIT_FD) {
+ if (inherit_fd_collect(pipe_name, pi) == 1) {
+ pi->reopen = 0; // FIXME
+ continue;
+ } else {
+ pr_err("No inherit fd for pipe %s\n", pipe_name);
+ BUG(); // FIXME
+ }
+ }
+
if (!(pi->pe->flags & O_LARGEFILE)) {
if (pi->pe->flags & O_WRONLY) {
if (pw == NULL)
@@ -306,7 +370,6 @@ static char *pipe_id_string(int pipe_id)
static int open_pipe(struct file_desc *d)
{
- char *pipe_name;
struct pipe_info *pi, *p;
int ret, tmp;
int pfd[2];
@@ -314,19 +377,7 @@ static int open_pipe(struct file_desc *d)
pi = container_of(d, struct pipe_info, d);
- pr_info("\t\tCreating pipe pipe_id=%#x id=%#x\n", pi->pe->pipe_id, pi->pe->id);
-
- pipe_name = pipe_id_string(pi->pe->pipe_id);
- tmp = inherit_fd_lookup_id(pipe_name, true);
- if (tmp >= 0) {
- pr_info("Pipe %s will be restored from inherit fd %d\n",
- pipe_name, tmp);
- return tmp;
- }
- if (pi->pe->flags == INHERIT_FD) {
- pr_err("No inherit fd for pipe %s\n", pipe_name);
- return -1;
- }
+ pr_info("\t\tCreating pipe pipe_id=%d id=%#x\n", pi->pe->pipe_id, pi->pe->id);
if (!pi->create)
return recv_pipe_fd(pi);
@@ -380,6 +431,7 @@ static int want_transport(FdinfoEntry *fe, struct file_desc *d)
struct pipe_info *pi;
pi = container_of(d, struct pipe_info, d);
+
return !pi->create;
}
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index b5c1a6a..9dc1eed 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -7,6 +7,7 @@ CFLAGS = -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
CFLAGS += $(USERCFLAGS)
TST_NOFILE = \
+ pipe-inherit \
busyloop00 \
sleeping00 \
pid00 \
diff --git a/test/zdtm/live/static/pipe-inherit.c b/test/zdtm/live/static/pipe-inherit.c
new file mode 100644
index 0000000..46b1593
--- /dev/null
+++ b/test/zdtm/live/static/pipe-inherit.c
@@ -0,0 +1,48 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc = "Check that environment didn't change";
+const char *test_author = "Pavel Emelianov <xemul at parallels.com>";
+
+int main(int argc, char **argv)
+{
+ pid_t ext_pid;
+ int p[2];
+
+ if (pipe(p))
+ return -1;
+
+ ext_pid = fork();
+ if (ext_pid < 0)
+ return -1;
+
+ if (ext_pid == 0) {
+ char buf[128];
+ int ret;
+
+ test_ext_init(argc, argv);
+ ret = read(p[0], buf, sizeof(buf));
+ if (ret <= 0)
+ fail();
+ test_msg("%s\n", buf);
+ pass();
+ return 0;
+ }
+
+ test_init(argc, argv);
+
+ close(p[0]);
+
+ test_daemon();
+ test_waitsig();
+
+ write(p[1], "hello", 6);
+ close(p[1]);
+
+ pass();
+ return 0;
+}
diff --git a/util.c b/util.c
index 3b468f2..23ebb60 100644
--- a/util.c
+++ b/util.c
@@ -95,13 +95,6 @@ int close_safe(int *fd)
{
int ret = 0;
- /*
- * Don't close files descriptors that criu's caller
- * set up to be inherited by the restored process.
- */
- if (inherit_fd_lookup_fd(*fd))
- return 0;
-
if (*fd > -1) {
ret = close(*fd);
if (!ret)
--
1.9.3
More information about the CRIU
mailing list