[CRIU] [PATCH 13/14] restore: restore pocesses which share one fdtable (v4)

Andrey Vagin avagin at openvz.org
Fri Jan 11 04:22:44 EST 2013


Currenly crtools supports a case when a child shared a fd table
with parent.

Here is only two interesting things.
* Service descriptors should be cloned for each process
  who shared one fd table.
* One task should restore files and other tasks should sleep in this
* time.

v2: * allocate fdt_lock from shared memory
    * don't wait a child, if it doesn't share fdtable
v3: * don't move ids on the pstree image
v4: * save ids in a separate image
    * save fdinfo per id instead of pid

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-dump.c         | 12 +++++++-----
 cr-restore.c      | 17 ++++++++++++++---
 files.c           | 28 ++++++++++++++++++++++------
 include/crtools.h |  1 +
 pstree.c          |  1 +
 5 files changed, 45 insertions(+), 14 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index fb81bc4..7384a56 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -692,7 +692,7 @@ static int dump_task_kobj_ids(struct pstree_item *item)
 
 	new = 0;
 	ids->files_id = kid_generate_gen(&files_tree, &elem, &new);
-	if (!ids->files_id || !new) {
+	if (!ids->files_id || (!new && !shared_fdtable(item))) {
 		pr_err("Can't make FILES id for %d\n", pid);
 		return -1;
 	}
@@ -1434,10 +1434,12 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
-	ret = dump_task_files_seized(parasite_ctl, item, dfds);
-	if (ret) {
-		pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
-		goto err_cure;
+	if (!shared_fdtable(item)) {
+		ret = dump_task_files_seized(parasite_ctl, item, dfds);
+		if (ret) {
+			pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
+			goto err_cure;
+		}
 	}
 
 	ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
diff --git a/cr-restore.c b/cr-restore.c
index ccc404d..9b69eff 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -808,6 +808,9 @@ static inline int fork_with_pid(struct pstree_item *item, unsigned long ns_clone
 	ca.item = item;
 	ca.clone_flags = ns_clone_flags;
 
+	if (shared_fdtable(item))
+		ca.clone_flags |= CLONE_FILES;
+
 	if (!(ca.clone_flags & CLONE_NEWPID)) {
 		char buf[32];
 
@@ -995,11 +998,19 @@ static int restore_task_with_children(void *_arg)
 	int ret;
 	sigset_t blockmask;
 
-	close_safe(&ca->fd);
-	close_old_fds(current);
-
 	current = ca->item;
 
+	if ( !(ca->clone_flags & CLONE_FILES)) {
+		close_safe(&ca->fd);
+		close_old_fds(current);
+	}
+
+	if (current->state != TASK_HELPER) {
+		ret = clone_service_fd(current->rst->service_fd_id);
+		if (ret)
+			exit(1);
+	}
+
 	pid = getpid();
 	if (current->pid.virt != pid) {
 		pr_err("Pid %d do not match expected %d\n", pid, current->pid.virt);
diff --git a/files.c b/files.c
index 2a22c3a..681ff47 100644
--- a/files.c
+++ b/files.c
@@ -541,15 +541,29 @@ int close_old_fds(struct pstree_item *me)
 
 int prepare_fds(struct pstree_item *me)
 {
-	u32 ret;
+	u32 ret = 0;
 	int state;
 
-	ret = close_old_fds(me);
-	if (ret)
-		goto err;
-
 	pr_info("Opening fdinfo-s\n");
 
+	if (me->rst->fdt) {
+		struct fdt *fdt = me->rst->fdt;
+
+		/*
+		 * Wait all tasks, who share a current fd table.
+		 * We should be sure, that nobody use any file
+		 * descriptor while fdtable is being restored.
+		 */
+		futex_inc_and_wake(&fdt->fdt_lock);
+		futex_wait_while_lt(&fdt->fdt_lock, fdt->nr);
+
+		if (fdt->pid != me->pid.virt) {
+			pr_info("File descriptor talbe is shared with %d\n", fdt->pid);
+			futex_wait_until(&fdt->fdt_lock, fdt->nr + 1);
+			goto out;
+		}
+	}
+
 	for (state = 0; state < ARRAY_SIZE(states); state++) {
 		ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
 		if (ret)
@@ -573,7 +587,9 @@ int prepare_fds(struct pstree_item *me)
 			break;
 	}
 
-err:
+	if (me->rst->fdt)
+		futex_inc_and_wake(&me->rst->fdt->fdt_lock);
+out:
 	tty_fini_fds();
 	return ret;
 }
diff --git a/include/crtools.h b/include/crtools.h
index 00c917d..7a7f101 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -244,6 +244,7 @@ struct rst_info {
 	void			*premmapped_addr;
 	unsigned long		premmapped_len;
 
+	int service_fd_id;
 	struct fdt		*fdt;
 };
 
diff --git a/pstree.c b/pstree.c
index 85371d7..a9987f9 100644
--- a/pstree.c
+++ b/pstree.c
@@ -463,6 +463,7 @@ static int prepare_pstree_ids(void)
 			fdt = parent->rst->fdt;
 
 		item->rst->fdt = fdt;
+		item->rst->service_fd_id = fdt->nr;
 		fdt->nr++;
 		if (fdt->pid > item->pid.virt)
 			fdt->pid = item->pid.virt;
-- 
1.7.11.7



More information about the CRIU mailing list