mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
ipc: Keep shmem segments contents into pagemap/page images
Right now the contents of the sysvipc shmem segment is stored as raw blob in the ipcns-shm image. This is bad for two reasons. First is that huge segments with holes are filled with real zeroes in image. Second is that we prefer not to mix images with pb object and raw data. To fix both let's re-use the shmem.c code that keeps anon shared memory contents in pagemap/pages images. https://github.com/xemul/criu/issues/287 Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
0ba02b2cb5
commit
9d2e1dfebe
4 changed files with 45 additions and 31 deletions
|
|
@ -13,6 +13,8 @@ extern int collect_sysv_shmem(unsigned long shmid, unsigned long size);
|
|||
extern int cr_dump_shmem(void);
|
||||
extern int add_shmem_area(pid_t pid, VmaEntry *vma, u64 *map);
|
||||
extern int fixup_sysv_shmems(void);
|
||||
extern int dump_one_sysv_shmem(void *addr, unsigned long size, unsigned long shmid);
|
||||
extern int restore_sysv_shmem_content(void *addr, unsigned long size, unsigned long shmid);
|
||||
|
||||
#define SYSV_SHMEM_SKIP_FD (0x7fffffff)
|
||||
|
||||
|
|
|
|||
|
|
@ -338,15 +338,10 @@ static int ipc_sysctl_req(IpcVarEntry *e, int op)
|
|||
return sysctl_op(req, nr, op, CLONE_NEWIPC);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Function below should be later improved to locate and dump only dirty
|
||||
* pages via updated sys_mincore().
|
||||
*/
|
||||
static int dump_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
|
||||
static int dump_ipc_shm_pages(const IpcShmEntry *shm)
|
||||
{
|
||||
int ret;
|
||||
void *data;
|
||||
int ifd;
|
||||
ssize_t size, off;
|
||||
|
||||
data = shmat(shm->desc->id, NULL, SHM_RDONLY);
|
||||
if (data == (void *)-1) {
|
||||
|
|
@ -354,32 +349,13 @@ static int dump_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME -- this just write the whole memory segment into the
|
||||
* image. In case the segment is huge this takes time. Need
|
||||
* to adopt the holes detection code (next_data_segment) from
|
||||
* shmem.c
|
||||
*/
|
||||
ifd = img_raw_fd(img);
|
||||
size = round_up(shm->size, sizeof(u32));
|
||||
off = 0;
|
||||
do {
|
||||
ssize_t ret;
|
||||
|
||||
ret = write(ifd, data + off, size - off);
|
||||
if (ret <= 0) {
|
||||
pr_perror("Failed to write IPC shared memory data");
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
off += ret;
|
||||
} while (off < size);
|
||||
ret = dump_one_sysv_shmem(data, shm->size, shm->desc->id);
|
||||
|
||||
if (shmdt(data)) {
|
||||
pr_perror("Failed to detach IPC shared memory");
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *ds)
|
||||
|
|
@ -390,6 +366,8 @@ static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *d
|
|||
|
||||
shm.desc = &desc;
|
||||
shm.size = ds->shm_segsz;
|
||||
shm.has_in_pagemaps = true;
|
||||
shm.in_pagemaps = true;
|
||||
fill_ipc_desc(id, shm.desc, &ds->shm_perm);
|
||||
pr_info_ipc_shm(&shm);
|
||||
|
||||
|
|
@ -398,7 +376,7 @@ static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *d
|
|||
pr_err("Failed to write IPC shared memory segment\n");
|
||||
return ret;
|
||||
}
|
||||
return dump_ipc_shm_pages(img, &shm);
|
||||
return dump_ipc_shm_pages(&shm);
|
||||
}
|
||||
|
||||
static int dump_ipc_shm(struct cr_img *img)
|
||||
|
|
@ -811,7 +789,10 @@ static int prepare_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
ret = restore_content(data, img, shm);
|
||||
if (shm->has_in_pagemaps && shm->in_pagemaps)
|
||||
ret = restore_sysv_shmem_content(data, shm->size, shm->desc->id);
|
||||
else
|
||||
ret = restore_content(data, img, shm);
|
||||
|
||||
if (shmdt(data)) {
|
||||
pr_perror("Failed to detach IPC shared memory");
|
||||
|
|
|
|||
32
criu/shmem.c
32
criu/shmem.c
|
|
@ -492,6 +492,11 @@ static int restore_shmem_content(void *addr, struct shmem_info *si)
|
|||
return do_restore_shmem_content(addr, si->size, si->shmid);
|
||||
}
|
||||
|
||||
int restore_sysv_shmem_content(void *addr, unsigned long size, unsigned long shmid)
|
||||
{
|
||||
return do_restore_shmem_content(addr, round_up(size, PAGE_SIZE), shmid);
|
||||
}
|
||||
|
||||
static int open_shmem(int pid, struct vma_area *vma)
|
||||
{
|
||||
VmaEntry *vi = vma->e;
|
||||
|
|
@ -689,7 +694,7 @@ static int do_dump_one_shmem(int fd, void *addr, struct shmem_info *si)
|
|||
next_data_segment(fd, pfn, &next_data_pnf, &next_hole_pfn))
|
||||
goto err_xfer;
|
||||
|
||||
if (is_shmem_tracking_en()) {
|
||||
if (si->pstate_map && is_shmem_tracking_en()) {
|
||||
pgstate = get_pstate(si->pstate_map, pfn);
|
||||
use_mc = pgstate == PST_DONT_DUMP;
|
||||
}
|
||||
|
|
@ -757,6 +762,31 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int dump_one_sysv_shmem(void *addr, unsigned long size, unsigned long shmid)
|
||||
{
|
||||
int fd, ret;
|
||||
struct shmem_info *si, det;
|
||||
|
||||
si = shmem_find(shmid);
|
||||
if (!si) {
|
||||
pr_info("Detached shmem...\n");
|
||||
det.pid = SYSVIPC_SHMEM_PID;
|
||||
det.shmid = shmid;
|
||||
det.size = round_up(size, PAGE_SIZE);
|
||||
det.pstate_map = NULL;
|
||||
si = &det;
|
||||
}
|
||||
|
||||
fd = open_proc(PROC_SELF, "map_files/%lx-%lx",
|
||||
(unsigned long)addr, (unsigned long)addr + si->size);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
ret = do_dump_one_shmem(fd, addr, si);
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cr_dump_shmem(void)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ import "ipc-desc.proto";
|
|||
message ipc_shm_entry {
|
||||
required ipc_desc_entry desc = 1;
|
||||
required uint64 size = 2;
|
||||
optional bool in_pagemaps = 3;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue