diff --git a/fifo.c b/fifo.c index 67d7f569d..efd375a6e 100644 --- a/fifo.c +++ b/fifo.c @@ -112,9 +112,22 @@ static int open_fifo_fd(struct file_desc *d) return open_path_by_id(info->fe->id, do_open_fifo, info); } +static void collect_fifo_fd(struct file_desc *d, + struct fdinfo_list_entry *fle, struct rst_info *ri) +{ + struct fifo_info *info; + + info = container_of(d, struct fifo_info, d); + if (collect_special_file(info->fe->id)) + BUG(); + + collect_gen_fd(fle, ri); +} + static struct file_desc_ops fifo_desc_ops = { .type = FD_TYPES__FIFO, .open = open_fifo_fd, + .collect_fd = collect_fifo_fd, }; static int collect_one_fifo(void *o, ProtobufCMessage *base) diff --git a/files-reg.c b/files-reg.c index 28e963cb6..08595297c 100644 --- a/files-reg.c +++ b/files-reg.c @@ -144,7 +144,6 @@ static int open_remap_ghost(struct reg_file_info *rfi, gf->remap.users = 0; list_add_tail(&gf->list, &ghost_files); gf_found: - gf->remap.users++; rfi->remap = &gf->remap; return 0; @@ -664,11 +663,55 @@ int open_reg_by_id(u32 id) return open_path_by_id(id, do_open_reg, NULL); } +static void remap_get(struct file_desc *fdesc, char typ) +{ + struct reg_file_info *rfi; + + rfi = container_of(fdesc, struct reg_file_info, d); + if (rfi->remap) { + pr_debug("One more remap user (%c) for %s\n", + typ, rfi->remap->path); + /* No lock, we're still sngle-process here */ + rfi->remap->users++; + } +} + +static void collect_reg_fd(struct file_desc *fdesc, + struct fdinfo_list_entry *fle, struct rst_info *ri) +{ + if (list_empty(&fdesc->fd_info_head)) + remap_get(fdesc, 'f'); + + collect_gen_fd(fle, ri); +} + static struct file_desc_ops reg_desc_ops = { .type = FD_TYPES__REG, .open = open_fe_fd, + .collect_fd = collect_reg_fd, }; +int collect_special_file(u32 id) +{ + struct file_desc *fdesc; + + /* + * Files dumped for vmas/exe links can have remaps + * configured. Need to bump-up users for them, otherwise + * the open_path() would unlink the remap file after + * the very first open. + */ + + fdesc = find_file_desc_raw(FD_TYPES__REG, id); + if (fdesc == NULL) { + pr_err("No entry for reg-file-ID %#x\n", id); + return -1; + } + + remap_get(fdesc, 's'); + return 0; +} + static int collect_one_regfile(void *o, ProtobufCMessage *base) { struct reg_file_info *rfi = o; diff --git a/include/files-reg.h b/include/files-reg.h index d3bd4f0cd..6de0cee17 100644 --- a/include/files-reg.h +++ b/include/files-reg.h @@ -34,6 +34,7 @@ extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p); extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino); extern void remap_put(struct file_remap *remap); +extern int collect_special_file(u32 id); extern struct collect_image_info reg_file_cinfo; extern struct collect_image_info remap_cinfo; diff --git a/mem.c b/mem.c index 05e8e2536..f27d899d4 100644 --- a/mem.c +++ b/mem.c @@ -18,6 +18,7 @@ #include "shmem.h" #include "pstree.h" #include "restorer.h" +#include "files-reg.h" #include "protobuf.h" #include "protobuf/pagemap.pb-c.h" @@ -341,6 +342,11 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, return ret; } +static inline int collect_filemap(VmaEntry *vme) +{ + return collect_special_file(vme->shmid); +} + int prepare_mm_pid(struct pstree_item *i) { pid_t pid = i->pid.virt; @@ -359,6 +365,9 @@ int prepare_mm_pid(struct pstree_item *i) if (ret < 0) return -1; + if (collect_special_file(ri->mm->exe_file_id)) + return -1; + pr_debug("Found %zd VMAs in image\n", ri->mm->n_vmas); fd = -1; if (ri->mm->n_vmas == 0) { @@ -401,11 +410,14 @@ int prepare_mm_pid(struct pstree_item *i) pr_info("vma 0x%"PRIx64" 0x%"PRIx64"\n", vma->e->start, vma->e->end); - if (!vma_area_is(vma, VMA_ANON_SHARED) || - vma_area_is(vma, VMA_AREA_SYSVIPC)) - continue; - - ret = collect_shmem(pid, vma->e); + if (vma_area_is(vma, VMA_ANON_SHARED) && + !vma_area_is(vma, VMA_AREA_SYSVIPC)) + ret = collect_shmem(pid, vma->e); + else if (vma_area_is(vma, VMA_FILE_PRIVATE) || + vma_area_is(vma, VMA_FILE_SHARED)) + ret = collect_filemap(vma->e); + else + ret = 0; if (ret) break; }