diff --git a/cr-restore.c b/cr-restore.c index 4171155f4..82611d47b 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -126,6 +126,10 @@ static int crtools_prepare_shared(void) if (prepare_shared_fdinfo()) return -1; + /* We might want to remove ghost files on failed restore */ + if (collect_remaps_and_regfiles()) + return -1; + /* Connections are unlocked from criu */ if (collect_inet_sockets()) return -1; @@ -149,8 +153,6 @@ static int crtools_prepare_shared(void) */ static struct collect_image_info *cinfos[] = { - ®_file_cinfo, - &remap_cinfo, &nsfile_cinfo, &pipe_cinfo, &fifo_cinfo, @@ -186,6 +188,9 @@ static int root_prepare_shared(void) if (prepare_shared_reg_files()) return -1; + if (prepare_remaps()) + return -1; + for (i = 0; i < ARRAY_SIZE(cinfos); i++) { ret = collect_image(cinfos[i]); if (ret) diff --git a/files-reg.c b/files-reg.c index c5aed6d52..7c85e01b1 100644 --- a/files-reg.c +++ b/files-reg.c @@ -301,25 +301,19 @@ static int open_remap_dead_process(struct reg_file_info *rfi, return 0; } +struct remap_info { + struct list_head list; + RemapFilePathEntry *rfe; + struct reg_file_info *rfi; +}; + static int collect_one_remap(void *obj, ProtobufCMessage *msg) { - int ret = -1; + struct remap_info *ri = obj; RemapFilePathEntry *rfe; struct file_desc *fdesc; - struct reg_file_info *rfi; - - rfe = pb_msg(msg, RemapFilePathEntry); - - fdesc = find_file_desc_raw(FD_TYPES__REG, rfe->orig_id); - if (fdesc == NULL) { - pr_err("Remap for non existing file %#x\n", - rfe->orig_id); - goto out; - } - - rfi = container_of(fdesc, struct reg_file_info, d); - pr_info("Configuring remap %#x -> %#x\n", rfi->rfe->id, rfe->remap_id); + ri->rfe = rfe = pb_msg(msg, RemapFilePathEntry); if (!rfe->has_remap_type) { rfe->has_remap_type = true; @@ -331,6 +325,27 @@ static int collect_one_remap(void *obj, ProtobufCMessage *msg) rfe->remap_type = REMAP_TYPE__LINKED; } + fdesc = find_file_desc_raw(FD_TYPES__REG, rfe->orig_id); + if (fdesc == NULL) { + pr_err("Remap for non existing file %#x\n", rfe->orig_id); + return -1; + } + + ri->rfi = container_of(fdesc, struct reg_file_info, d); + + list_add_tail(&ri->list, &remaps); + + return 0; +} + +static int prepare_one_remap(struct remap_info *ri) +{ + int ret = -1; + RemapFilePathEntry *rfe = ri->rfe; + struct reg_file_info *rfi = ri->rfi; + + pr_info("Configuring remap %#x -> %#x\n", rfi->rfe->id, rfe->remap_id); + switch (rfe->remap_type) { case REMAP_TYPE__LINKED: ret = open_remap_linked(rfi, rfe); @@ -350,9 +365,24 @@ out: return ret; } -struct collect_image_info remap_cinfo = { +int prepare_remaps(void) +{ + struct remap_info *ri; + int ret = 0; + + list_for_each_entry(ri, &remaps, list) { + ret = prepare_one_remap(ri); + if (ret) + break; + } + + return ret; +} + +static struct collect_image_info remap_cinfo = { .fd_type = CR_FD_REMAP_FPATH, .pb_type = PB_REMAP_FPATH, + .priv_size = sizeof(struct remap_info), .collect = collect_one_remap, }; @@ -1273,7 +1303,7 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base) return file_desc_add(&rfi->d, rfi->rfe->id, ®_desc_ops); } -struct collect_image_info reg_file_cinfo = { +static struct collect_image_info reg_file_cinfo = { .fd_type = CR_FD_REG_FILES, .pb_type = PB_REG_FILE, .priv_size = sizeof(struct reg_file_info), @@ -1289,3 +1319,14 @@ int prepare_shared_reg_files(void) mutex_init(ghost_file_mutex); return 0; } + +int collect_remaps_and_regfiles(void) +{ + if (collect_image(®_file_cinfo)) + return -1; + + if (collect_image(&remap_cinfo)) + return -1; + + return 0; +} diff --git a/include/files-reg.h b/include/files-reg.h index a98ef9aeb..1bafdf43f 100644 --- a/include/files-reg.h +++ b/include/files-reg.h @@ -45,11 +45,11 @@ extern void remap_put(struct file_remap *remap); extern struct file_desc *try_collect_special_file(u32 id, int optional); #define collect_special_file(id) try_collect_special_file(id, 0) -extern struct collect_image_info reg_file_cinfo; -extern struct collect_image_info remap_cinfo; +extern int collect_remaps_and_regfiles(void); extern void delete_link_remaps(void); extern void free_link_remaps(void); +extern int prepare_remaps(void); extern int strip_deleted(struct fd_link *link);