2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 01:51:51 +00:00

ipc: Add support for checkpoint/restore hugetlb System V shared memory

Attach the System V shared memory segments to the address space via shmat() to
determine if they are backed by hugetlb and their page size. Use these
information for setting the correct flags on restore.

Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
This commit is contained in:
Bui Quang Minh 2021-12-15 22:53:09 +07:00 committed by Andrei Vagin
parent f69c365916
commit 4d77b19eb3
2 changed files with 47 additions and 2 deletions

View File

@ -15,6 +15,7 @@
#include "sysctl.h"
#include "ipc_ns.h"
#include "shmem.h"
#include "types.h"
#include "protobuf.h"
#include "images/ipc-var.pb-c.h"
@ -354,6 +355,42 @@ static int dump_ipc_shm_pages(const IpcShmEntry *shm)
return ret;
}
static int dump_shm_hugetlb_flag(IpcShmEntry *shm, int id, unsigned long size)
{
void *addr;
int ret, hugetlb_flag, exit_code = -1;
struct stat st;
char path[64];
addr = shmat(id, NULL, SHM_RDONLY);
if (addr == (void *)-1) {
pr_perror("Failed to attach shm");
return -1;
}
/* The shm segment size may not be aligned,
* we need to align it up to next page size
*/
size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
snprintf(path, sizeof(path), "/proc/self/map_files/%lx-%lx", (unsigned long)addr, (unsigned long)addr + size);
ret = stat(path, &st);
if (ret < 0) {
pr_perror("Can't stat map_files");
goto detach;
}
if (is_hugetlb_dev(st.st_dev, &hugetlb_flag)) {
shm->has_hugetlb_flag = true;
shm->hugetlb_flag = hugetlb_flag | SHM_HUGETLB;
}
exit_code = 0;
detach:
shmdt(addr);
return exit_code;
}
static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *ds)
{
IpcShmEntry shm = IPC_SHM_ENTRY__INIT;
@ -364,6 +401,10 @@ static int dump_ipc_shm_seg(struct cr_img *img, int id, const struct shmid_ds *d
shm.size = ds->shm_segsz;
shm.has_in_pagemaps = true;
shm.in_pagemaps = true;
if (dump_shm_hugetlb_flag(&shm, id, ds->shm_segsz))
return -1;
fill_ipc_desc(id, shm.desc, &ds->shm_perm);
pr_info_ipc_shm(&shm);
@ -798,7 +839,7 @@ static int prepare_ipc_shm_pages(struct cr_img *img, const IpcShmEntry *shm)
static int prepare_ipc_shm_seg(struct cr_img *img, const IpcShmEntry *shm)
{
int ret, id;
int ret, id, hugetlb_flag = 0;
struct sysctl_req req[] = {
{ "kernel/shm_next_id", &shm->desc->id, CTL_U32 },
};
@ -813,7 +854,10 @@ static int prepare_ipc_shm_seg(struct cr_img *img, const IpcShmEntry *shm)
return ret;
}
id = shmget(shm->desc->key, shm->size, shm->desc->mode | IPC_CREAT | IPC_EXCL);
if (shm->has_hugetlb_flag)
hugetlb_flag = shm->hugetlb_flag;
id = shmget(shm->desc->key, shm->size, hugetlb_flag | shm->desc->mode | IPC_CREAT | IPC_EXCL);
if (id == -1) {
pr_perror("Failed to create shm set");
return -errno;

View File

@ -8,4 +8,5 @@ message ipc_shm_entry {
required ipc_desc_entry desc = 1;
required uint64 size = 2;
optional bool in_pagemaps = 3;
optional uint32 hugetlb_flag = 4;
}