diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 18a72b584..aa7af0fb3 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -375,6 +375,11 @@ static int root_prepare_shared(void) if (ret) goto err; + /* This func may add new files, so it must be called before post prepare */ + ret = add_fake_fds_masters(); + if (ret) + goto err; + ret = run_post_prepare(); if (ret) goto err; diff --git a/criu/files.c b/criu/files.c index 73337e021..e1d07a1e7 100644 --- a/criu/files.c +++ b/criu/files.c @@ -1893,3 +1893,34 @@ int prepare_files(void) init_fdesc_hash(); return collect_image(&files_cinfo); } + +int add_fake_fds_masters(void) +{ + struct fdinfo_list_entry *fle; + struct file_desc *fdesc, *tmp; + FdinfoEntry *fe; + int fd; + + list_for_each_entry_safe(fdesc, tmp, &fake_master_head, fake_master_list) { + fle = list_first_entry(&fdesc->fd_info_head, + struct fdinfo_list_entry, desc_list); + /* + * All masters are created in root_item for now. + * Distribute them over pstree if someone reports, + * their number is too big, or you want support + * file->user_ns. + */ + fd = find_unused_fd(root_item, -1); + fe = dup_fdinfo(fle->fe, fd, fle->fe->flags); + if (!fe) + goto err; + + if (collect_fd(vpid(root_item), fe, rsti(root_item), true)) + goto err; + } + BUG_ON(!list_empty(&fake_master_head)); + return 0; +err: + pr_err("Can't prepare fds masters\n"); + return -1; +} diff --git a/criu/include/files.h b/criu/include/files.h index abfb5f8a1..a6a3868eb 100644 --- a/criu/include/files.h +++ b/criu/include/files.h @@ -164,6 +164,7 @@ extern int rst_file_params(int fd, FownEntry *fown, int flags); extern void show_saved_files(void); +extern int add_fake_fds_masters(void); extern int prepare_fds(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);