mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
memfd: save all memfd inodes in one image
Per-object image is acceptable if we expect to have 1-3 objects per-container. If we expect to have more objects, it is better to save them all into one image. There are a number of reasons for this: * We need fewer system calls to read all objects from one image. * It is faster to save or move one image. Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
@@ -233,6 +233,9 @@ static int restore_finish_ns_stage(int from, int to)
|
|||||||
|
|
||||||
static int crtools_prepare_shared(void)
|
static int crtools_prepare_shared(void)
|
||||||
{
|
{
|
||||||
|
if (prepare_memfd_inodes())
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (prepare_files())
|
if (prepare_files())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@@ -66,7 +66,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
|
|||||||
FD_ENTRY(FS, "fs-%u"),
|
FD_ENTRY(FS, "fs-%u"),
|
||||||
FD_ENTRY(REMAP_FPATH, "remap-fpath"),
|
FD_ENTRY(REMAP_FPATH, "remap-fpath"),
|
||||||
FD_ENTRY_F(GHOST_FILE, "ghost-file-%x", O_NOBUF),
|
FD_ENTRY_F(GHOST_FILE, "ghost-file-%x", O_NOBUF),
|
||||||
FD_ENTRY_F(MEMFD_INODE, "memfd-%u", O_NOBUF),
|
FD_ENTRY_F(MEMFD_INODE, "memfd", O_NOBUF),
|
||||||
FD_ENTRY(TCP_STREAM, "tcp-stream-%x"),
|
FD_ENTRY(TCP_STREAM, "tcp-stream-%x"),
|
||||||
FD_ENTRY(MNTS, "mountpoints-%u"),
|
FD_ENTRY(MNTS, "mountpoints-%u"),
|
||||||
FD_ENTRY(NETDEV, "netdev-%u"),
|
FD_ENTRY(NETDEV, "netdev-%u"),
|
||||||
|
@@ -65,6 +65,7 @@ enum {
|
|||||||
CR_FD_CGROUP,
|
CR_FD_CGROUP,
|
||||||
CR_FD_FILE_LOCKS,
|
CR_FD_FILE_LOCKS,
|
||||||
CR_FD_SECCOMP,
|
CR_FD_SECCOMP,
|
||||||
|
CR_FD_MEMFD_INODE,
|
||||||
_CR_FD_GLOB_TO,
|
_CR_FD_GLOB_TO,
|
||||||
|
|
||||||
CR_FD_TMPFS_IMG,
|
CR_FD_TMPFS_IMG,
|
||||||
@@ -107,7 +108,6 @@ enum {
|
|||||||
CR_FD_PIPES,
|
CR_FD_PIPES,
|
||||||
CR_FD_TTY_FILES,
|
CR_FD_TTY_FILES,
|
||||||
CR_FD_MEMFD_FILE,
|
CR_FD_MEMFD_FILE,
|
||||||
CR_FD_MEMFD_INODE,
|
|
||||||
|
|
||||||
CR_FD_AUTOFS,
|
CR_FD_AUTOFS,
|
||||||
|
|
||||||
|
@@ -17,6 +17,8 @@ extern struct collect_image_info memfd_cinfo;
|
|||||||
extern struct file_desc *collect_memfd(u32 id);
|
extern struct file_desc *collect_memfd(u32 id);
|
||||||
extern int apply_memfd_seals(void);
|
extern int apply_memfd_seals(void);
|
||||||
|
|
||||||
|
extern int prepare_memfd_inodes(void);
|
||||||
|
|
||||||
#ifdef CONFIG_HAS_MEMFD_CREATE
|
#ifdef CONFIG_HAS_MEMFD_CREATE
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#else
|
#else
|
||||||
|
90
criu/memfd.c
90
criu/memfd.c
@@ -43,9 +43,10 @@ struct memfd_inode {
|
|||||||
};
|
};
|
||||||
/* Only for restore */
|
/* Only for restore */
|
||||||
struct {
|
struct {
|
||||||
mutex_t lock;
|
mutex_t lock;
|
||||||
int fdstore_id;
|
int fdstore_id;
|
||||||
unsigned int pending_seals;
|
unsigned int pending_seals;
|
||||||
|
MemfdInodeEntry *mie;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -71,9 +72,8 @@ int is_memfd(dev_t dev)
|
|||||||
static int dump_memfd_inode(int fd, struct memfd_inode *inode,
|
static int dump_memfd_inode(int fd, struct memfd_inode *inode,
|
||||||
const char *name, const struct stat *st)
|
const char *name, const struct stat *st)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
|
||||||
struct cr_img *img = NULL;
|
|
||||||
MemfdInodeEntry mie = MEMFD_INODE_ENTRY__INIT;
|
MemfdInodeEntry mie = MEMFD_INODE_ENTRY__INIT;
|
||||||
|
int ret = -1;
|
||||||
u32 shmid;
|
u32 shmid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -90,10 +90,7 @@ static int dump_memfd_inode(int fd, struct memfd_inode *inode,
|
|||||||
if (dump_one_memfd_shmem(fd, shmid, st->st_size) < 0)
|
if (dump_one_memfd_shmem(fd, shmid, st->st_size) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
img = open_image(CR_FD_MEMFD_INODE, O_DUMP, inode->id);
|
mie.inode_id = inode->id;
|
||||||
if (!img)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
mie.uid = userns_uid(st->st_uid);
|
mie.uid = userns_uid(st->st_uid);
|
||||||
mie.gid = userns_gid(st->st_gid);
|
mie.gid = userns_gid(st->st_gid);
|
||||||
mie.name = (char *)name;
|
mie.name = (char *)name;
|
||||||
@@ -104,14 +101,12 @@ static int dump_memfd_inode(int fd, struct memfd_inode *inode,
|
|||||||
if (mie.seals == -1)
|
if (mie.seals == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (pb_write_one(img, &mie, PB_MEMFD_INODE))
|
if (pb_write_one(img_from_set(glob_imgset, CR_FD_MEMFD_INODE), &mie, PB_MEMFD_INODE))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (img)
|
|
||||||
close_image(img);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +207,6 @@ struct memfd_info {
|
|||||||
struct memfd_inode *inode;
|
struct memfd_inode *inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int memfd_open_inode(struct memfd_inode *inode);
|
|
||||||
|
|
||||||
static struct memfd_inode *memfd_alloc_inode(int id)
|
static struct memfd_inode *memfd_alloc_inode(int id)
|
||||||
{
|
{
|
||||||
struct memfd_inode *inode;
|
struct memfd_inode *inode;
|
||||||
@@ -222,35 +215,47 @@ static struct memfd_inode *memfd_alloc_inode(int id)
|
|||||||
if (inode->id == id)
|
if (inode->id == id)
|
||||||
return inode;
|
return inode;
|
||||||
|
|
||||||
inode = shmalloc(sizeof(*inode));
|
pr_err("Unable to find the %d memfd inode\n", id);
|
||||||
if (!inode)
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
inode->id = id;
|
static int collect_one_memfd_inode(void *o, ProtobufCMessage *base, struct cr_img *i)
|
||||||
|
{
|
||||||
|
MemfdInodeEntry *mie = pb_msg(base, MemfdInodeEntry);
|
||||||
|
struct memfd_inode *inode = o;
|
||||||
|
|
||||||
|
inode->mie = mie;
|
||||||
|
inode->id = mie->inode_id;
|
||||||
mutex_init(&inode->lock);
|
mutex_init(&inode->lock);
|
||||||
inode->fdstore_id = -1;
|
inode->fdstore_id = -1;
|
||||||
inode->pending_seals = 0;
|
inode->pending_seals = 0;
|
||||||
|
|
||||||
list_add_tail(&inode->list, &memfd_inodes);
|
list_add_tail(&inode->list, &memfd_inodes);
|
||||||
return inode;
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct collect_image_info memfd_inode_cinfo = {
|
||||||
|
.fd_type = CR_FD_MEMFD_INODE,
|
||||||
|
.pb_type = PB_MEMFD_INODE,
|
||||||
|
.priv_size = sizeof(struct memfd_inode),
|
||||||
|
.collect = collect_one_memfd_inode,
|
||||||
|
.flags = COLLECT_SHARED | COLLECT_NOFREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
int prepare_memfd_inodes(void)
|
||||||
|
{
|
||||||
|
return collect_image(&memfd_inode_cinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int restore_memfd_shm(int fd, u64 id, u64 size);
|
|
||||||
static int memfd_open_inode_nocache(struct memfd_inode *inode)
|
static int memfd_open_inode_nocache(struct memfd_inode *inode)
|
||||||
{
|
{
|
||||||
MemfdInodeEntry *mie = NULL;
|
MemfdInodeEntry *mie = NULL;
|
||||||
struct cr_img *img = NULL;
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
img = open_image(CR_FD_MEMFD_INODE, O_RSTR, inode->id);
|
mie = inode->mie;
|
||||||
if (!img)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (pb_read_one(img, &mie, PB_MEMFD_INODE) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (mie->seals == F_SEAL_SEAL) {
|
if (mie->seals == F_SEAL_SEAL) {
|
||||||
inode->pending_seals = 0;
|
inode->pending_seals = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
@@ -285,10 +290,6 @@ static int memfd_open_inode_nocache(struct memfd_inode *inode)
|
|||||||
out:
|
out:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
if (img)
|
|
||||||
close_image(img);
|
|
||||||
if (mie)
|
|
||||||
memfd_inode_entry__free_unpacked(mie, NULL);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,33 +374,17 @@ static int memfd_open_fe_fd(struct file_desc *fd, int *new_fd)
|
|||||||
static char *memfd_d_name(struct file_desc *d, char *buf, size_t s)
|
static char *memfd_d_name(struct file_desc *d, char *buf, size_t s)
|
||||||
{
|
{
|
||||||
MemfdInodeEntry *mie = NULL;
|
MemfdInodeEntry *mie = NULL;
|
||||||
struct cr_img *img = NULL;
|
|
||||||
struct memfd_info *mfi;
|
struct memfd_info *mfi;
|
||||||
char *ret = NULL;
|
|
||||||
|
|
||||||
mfi = container_of(d, struct memfd_info, d);
|
mfi = container_of(d, struct memfd_info, d);
|
||||||
|
|
||||||
img = open_image(CR_FD_MEMFD_INODE, O_RSTR, mfi->inode->id);
|
mie = mfi->inode->mie;
|
||||||
if (!img)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (pb_read_one(img, &mie, PB_MEMFD_INODE) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (snprintf(buf, s, "%s%s", MEMFD_PREFIX, mie->name) >= s) {
|
if (snprintf(buf, s, "%s%s", MEMFD_PREFIX, mie->name) >= s) {
|
||||||
pr_err("Buffer too small for memfd name %s\n", mie->name);
|
pr_err("Buffer too small for memfd name %s\n", mie->name);
|
||||||
goto out;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = buf;
|
return buf;
|
||||||
|
|
||||||
out:
|
|
||||||
if (img)
|
|
||||||
close_image(img);
|
|
||||||
if (mie)
|
|
||||||
memfd_inode_entry__free_unpacked(mie, NULL);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_desc_ops memfd_desc_ops = {
|
static struct file_desc_ops memfd_desc_ops = {
|
||||||
@@ -427,7 +412,8 @@ struct collect_image_info memfd_cinfo = {
|
|||||||
.collect = collect_one_memfd,
|
.collect = collect_one_memfd,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file_desc *collect_memfd(u32 id) {
|
struct file_desc *collect_memfd(u32 id)
|
||||||
|
{
|
||||||
struct file_desc *fdesc;
|
struct file_desc *fdesc;
|
||||||
|
|
||||||
fdesc = find_file_desc_raw(FD_TYPES__MEMFD, id);
|
fdesc = find_file_desc_raw(FD_TYPES__MEMFD, id);
|
||||||
|
@@ -18,4 +18,5 @@ message memfd_inode_entry {
|
|||||||
required uint64 size = 4;
|
required uint64 size = 4;
|
||||||
required uint32 shmid = 5;
|
required uint32 shmid = 5;
|
||||||
required uint32 seals = 6 [(criu).flags = "seals.flags"];
|
required uint32 seals = 6 [(criu).flags = "seals.flags"];
|
||||||
|
required uint64 inode_id = 7;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user