[01/10] files: split collect_fd on allocate_fd and handle_fd

Submitted by Andrei Vagin on Oct. 28, 2016, 5:41 p.m.

Details

Message ID 1477676516-28669-2-git-send-email-avagin@openvz.org
State Superseded
Series "Dump and restore nested network namespaces"
Headers show

Commit Message

Andrei Vagin Oct. 28, 2016, 5:41 p.m.
From: Andrew Vagin <avagin@virtuozzo.com>

We are going to open root directories for each namespace in
the root task, so we need to collect all file descriptors to
be able to find unused file descriptors.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/cr-restore.c    | 18 +++++++++++++++++
 criu/files.c         | 56 +++++++++++++++++++++++++++++++++++++++++++---------
 criu/include/files.h |  1 +
 3 files changed, 66 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 252cc91..f9eadf0 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1322,6 +1322,21 @@  static int create_children_and_session(void)
 	return 0;
 }
 
+static int collect_fd_shared()
+{
+	struct pstree_item *pi;
+
+	for_each_pstree_item(pi) {
+		if (pi->pid.state == TASK_HELPER)
+			continue;
+
+		if  (collect_fd_pid(pi))
+			return -1;
+	}
+
+	return 0;
+}
+
 static int restore_task_with_children(void *_arg)
 {
 	struct cr_clone_arg *ca = _arg;
@@ -1409,6 +1424,9 @@  static int restore_task_with_children(void *_arg)
 		pr_info("Calling restore_sid() for init\n");
 		restore_sid();
 
+		if (collect_fd_shared())
+			goto err;
+
 		/*
 		 * We need non /proc proc mount for restoring pid and mount
 		 * namespaces and do not care for the rest of the cases.
diff --git a/criu/files.c b/criu/files.c
index 21af891..b945577 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -682,21 +682,30 @@  int rst_file_params(int fd, FownEntry *fown, int flags)
 	return 0;
 }
 
-static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
+static struct fdinfo_list_entry *allocate_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
 {
-	struct fdinfo_list_entry *le, *new_le;
-	struct file_desc *fdesc;
+	struct fdinfo_list_entry *new_le;
 
 	pr_info("Collect fdinfo pid=%d fd=%d id=%#x\n",
 		pid, e->fd, e->id);
 
 	new_le = shmalloc(sizeof(*new_le));
 	if (!new_le)
-		return -1;
+		return NULL;
 
 	futex_init(&new_le->real_pid);
 	new_le->pid = pid;
 	new_le->fe = e;
+	collect_used_fd(new_le, rst_info);
+
+	return new_le;
+}
+
+static int handle_fd(struct fdinfo_list_entry *new_le, struct rst_info *rst_info)
+{
+	struct fdinfo_list_entry *le;
+	struct file_desc *fdesc;
+	FdinfoEntry *e = new_le->fe;
 
 	fdesc = find_file_desc(e);
 	if (fdesc == NULL) {
@@ -713,14 +722,23 @@  static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
 	else
 		collect_gen_fd(new_le, rst_info);
 
-	collect_used_fd(new_le, rst_info);
-
 	list_add_tail(&new_le->desc_list, &le->desc_list);
 	new_le->desc = fdesc;
 
 	return 0;
 }
 
+static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
+{
+	struct fdinfo_list_entry *le;
+
+	le = allocate_fd(pid, e, rst_info);
+	if (le == NULL)
+		return -1;
+
+	return handle_fd(le, rst_info);
+}
+
 FdinfoEntry *dup_fdinfo(FdinfoEntry *old, int fd, unsigned flags)
 {
 	FdinfoEntry *e;
@@ -777,7 +795,7 @@  int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
 	return 0;
 }
 
-int prepare_fd_pid(struct pstree_item *item)
+int collect_fd_pid(struct pstree_item *item)
 {
 	int ret = 0;
 	struct cr_img *img;
@@ -801,6 +819,7 @@  int prepare_fd_pid(struct pstree_item *item)
 		return -1;
 
 	while (1) {
+		struct fdinfo_list_entry *le;
 		FdinfoEntry *e;
 
 		ret = pb_read_one_eof(img, &e, PB_FDINFO);
@@ -813,17 +832,36 @@  int prepare_fd_pid(struct pstree_item *item)
 			break;
 		}
 
-		ret = collect_fd(pid, e, rst_info);
-		if (ret < 0) {
+		le = allocate_fd(pid, e, rst_info);
+		if (le == NULL) {
 			fdinfo_entry__free_unpacked(e, NULL);
+			ret = -1;
 			break;
 		}
+		list_add_tail(&le->ps_list, &rst_info->fds);
 	}
 
 	close_image(img);
 	return ret;
 }
 
+int prepare_fd_pid(struct pstree_item *item)
+{
+	struct rst_info *rst_info = rsti(item);
+	struct fdinfo_list_entry *le, *t;
+	LIST_HEAD(head);
+
+	list_splice_init(&rst_info->fds, &head);
+
+	list_for_each_entry_safe(le, t, &head, ps_list) {
+		list_del(&le->ps_list);
+		if (handle_fd(le, rst_info))
+			return -1;
+	}
+
+	return 0;
+}
+
 #define SETFL_MASK (O_APPEND | O_ASYNC | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
 int set_fd_flags(int fd, int flags)
 {
diff --git a/criu/include/files.h b/criu/include/files.h
index 153e7b3..2b6d58d 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -155,6 +155,7 @@  extern int rst_file_params(int fd, FownEntry *fown, int flags);
 extern void show_saved_files(void);
 
 extern int prepare_fds(struct pstree_item *me);
+extern int collect_fd_pid(struct pstree_item *me);
 extern int prepare_fd_pid(struct pstree_item *me);
 extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
 extern int prepare_shared_fdinfo(void);