Commit 979eb2a1 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

restore: restore pocesses which share one fdtable (v5)

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
v5: fix alignment of service_fd_id
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent d50c786c
...@@ -723,7 +723,7 @@ static int dump_task_kobj_ids(struct pstree_item *item) ...@@ -723,7 +723,7 @@ static int dump_task_kobj_ids(struct pstree_item *item)
new = 0; new = 0;
ids->files_id = kid_generate_gen(&files_tree, &elem, &new); 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); pr_err("Can't make FILES id for %d\n", pid);
return -1; return -1;
} }
...@@ -1465,11 +1465,13 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1465,11 +1465,13 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure; goto err_cure;
} }
if (!shared_fdtable(item)) {
ret = dump_task_files_seized(parasite_ctl, item, dfds); ret = dump_task_files_seized(parasite_ctl, item, dfds);
if (ret) { if (ret) {
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret); pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
goto err_cure; goto err_cure;
} }
}
ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset); ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
if (ret) { if (ret) {
......
...@@ -806,6 +806,9 @@ static inline int fork_with_pid(struct pstree_item *item, unsigned long ns_clone ...@@ -806,6 +806,9 @@ static inline int fork_with_pid(struct pstree_item *item, unsigned long ns_clone
ca.item = item; ca.item = item;
ca.clone_flags = ns_clone_flags; ca.clone_flags = ns_clone_flags;
if (shared_fdtable(item))
ca.clone_flags |= CLONE_FILES;
if (!(ca.clone_flags & CLONE_NEWPID)) { if (!(ca.clone_flags & CLONE_NEWPID)) {
char buf[32]; char buf[32];
...@@ -995,10 +998,18 @@ static int restore_task_with_children(void *_arg) ...@@ -995,10 +998,18 @@ static int restore_task_with_children(void *_arg)
current = ca->item; current = ca->item;
if ( !(ca->clone_flags & CLONE_FILES)) {
close_safe(&ca->fd); close_safe(&ca->fd);
ret = close_old_fds(current); ret = close_old_fds(current);
if (ret) if (ret)
exit(1); exit(1);
}
if (current->state != TASK_HELPER) {
ret = clone_service_fd(current->rst->service_fd_id);
if (ret)
exit(1);
}
pid = getpid(); pid = getpid();
if (current->pid.virt != pid) { if (current->pid.virt != pid) {
......
...@@ -541,11 +541,29 @@ int close_old_fds(struct pstree_item *me) ...@@ -541,11 +541,29 @@ int close_old_fds(struct pstree_item *me)
int prepare_fds(struct pstree_item *me) int prepare_fds(struct pstree_item *me)
{ {
u32 ret; u32 ret = 0;
int state; int state;
pr_info("Opening fdinfo-s\n"); 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++) { for (state = 0; state < ARRAY_SIZE(states); state++) {
ret = open_fdinfos(me->pid.virt, &me->rst->fds, state); ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
if (ret) if (ret)
...@@ -569,6 +587,9 @@ int prepare_fds(struct pstree_item *me) ...@@ -569,6 +587,9 @@ int prepare_fds(struct pstree_item *me)
break; break;
} }
if (me->rst->fdt)
futex_inc_and_wake(&me->rst->fdt->fdt_lock);
out:
tty_fini_fds(); tty_fini_fds();
return ret; return ret;
} }
......
...@@ -250,6 +250,7 @@ struct rst_info { ...@@ -250,6 +250,7 @@ struct rst_info {
void *premmapped_addr; void *premmapped_addr;
unsigned long premmapped_len; unsigned long premmapped_len;
int service_fd_id;
struct fdt *fdt; struct fdt *fdt;
}; };
......
...@@ -463,6 +463,7 @@ static int prepare_pstree_ids(void) ...@@ -463,6 +463,7 @@ static int prepare_pstree_ids(void)
fdt = parent->rst->fdt; fdt = parent->rst->fdt;
item->rst->fdt = fdt; item->rst->fdt = fdt;
item->rst->service_fd_id = fdt->nr;
fdt->nr++; fdt->nr++;
if (fdt->pid > item->pid.virt) if (fdt->pid > item->pid.virt)
fdt->pid = item->pid.virt; fdt->pid = item->pid.virt;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment