Commit 490efb46 authored by Pavel Emelyanov's avatar Pavel Emelyanov

files: Properlu count number of users for mmaped/exe-d ghost files

If a file mmaped or pointed by exe link is unlinked, we will
generate a ghost file for it. On restore the ghost file will
be created with the users counter 1 and the very first open
(e.g. for mmap) will unlink the file.

Handle this by bumping up user counter for every mapping
pointing on the file.

This appeared after previous patches that packed the reg-files
image. Before it each vma and exe link created separate entry
in the reg-files image.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 40e4ae9b
......@@ -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)
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
}
......
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