2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 01:51:51 +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:
Andrei Vagin 2020-03-23 07:37:00 +03:00
parent 967797a867
commit e3a5d09752
6 changed files with 46 additions and 54 deletions

View File

@ -233,6 +233,9 @@ static int restore_finish_ns_stage(int from, int to)
static int crtools_prepare_shared(void)
{
if (prepare_memfd_inodes())
return -1;
if (prepare_files())
return -1;

View File

@ -66,7 +66,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
FD_ENTRY(FS, "fs-%u"),
FD_ENTRY(REMAP_FPATH, "remap-fpath"),
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(MNTS, "mountpoints-%u"),
FD_ENTRY(NETDEV, "netdev-%u"),

View File

@ -65,6 +65,7 @@ enum {
CR_FD_CGROUP,
CR_FD_FILE_LOCKS,
CR_FD_SECCOMP,
CR_FD_MEMFD_INODE,
_CR_FD_GLOB_TO,
CR_FD_TMPFS_IMG,
@ -107,7 +108,6 @@ enum {
CR_FD_PIPES,
CR_FD_TTY_FILES,
CR_FD_MEMFD_FILE,
CR_FD_MEMFD_INODE,
CR_FD_AUTOFS,

View File

@ -17,6 +17,8 @@ extern struct collect_image_info memfd_cinfo;
extern struct file_desc *collect_memfd(u32 id);
extern int apply_memfd_seals(void);
extern int prepare_memfd_inodes(void);
#ifdef CONFIG_HAS_MEMFD_CREATE
# include <sys/mman.h>
#else

View File

@ -43,9 +43,10 @@ struct memfd_inode {
};
/* Only for restore */
struct {
mutex_t lock;
int fdstore_id;
unsigned int pending_seals;
mutex_t lock;
int fdstore_id;
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,
const char *name, const struct stat *st)
{
int ret = -1;
struct cr_img *img = NULL;
MemfdInodeEntry mie = MEMFD_INODE_ENTRY__INIT;
int ret = -1;
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)
goto out;
img = open_image(CR_FD_MEMFD_INODE, O_DUMP, inode->id);
if (!img)
goto out;
mie.inode_id = inode->id;
mie.uid = userns_uid(st->st_uid);
mie.gid = userns_gid(st->st_gid);
mie.name = (char *)name;
@ -104,14 +101,12 @@ static int dump_memfd_inode(int fd, struct memfd_inode *inode,
if (mie.seals == -1)
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;
ret = 0;
out:
if (img)
close_image(img);
return ret;
}
@ -212,8 +207,6 @@ struct memfd_info {
struct memfd_inode *inode;
};
static int memfd_open_inode(struct memfd_inode *inode);
static struct memfd_inode *memfd_alloc_inode(int id)
{
struct memfd_inode *inode;
@ -222,35 +215,47 @@ static struct memfd_inode *memfd_alloc_inode(int id)
if (inode->id == id)
return inode;
inode = shmalloc(sizeof(*inode));
if (!inode)
return NULL;
pr_err("Unable to find the %d memfd inode\n", id);
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);
inode->fdstore_id = -1;
inode->pending_seals = 0;
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)
{
MemfdInodeEntry *mie = NULL;
struct cr_img *img = NULL;
int fd = -1;
int ret = -1;
int flags;
img = open_image(CR_FD_MEMFD_INODE, O_RSTR, inode->id);
if (!img)
goto out;
if (pb_read_one(img, &mie, PB_MEMFD_INODE) < 0)
goto out;
mie = inode->mie;
if (mie->seals == F_SEAL_SEAL) {
inode->pending_seals = 0;
flags = 0;
@ -285,10 +290,6 @@ static int memfd_open_inode_nocache(struct memfd_inode *inode)
out:
if (fd != -1)
close(fd);
if (img)
close_image(img);
if (mie)
memfd_inode_entry__free_unpacked(mie, NULL);
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)
{
MemfdInodeEntry *mie = NULL;
struct cr_img *img = NULL;
struct memfd_info *mfi;
char *ret = NULL;
mfi = container_of(d, struct memfd_info, d);
img = open_image(CR_FD_MEMFD_INODE, O_RSTR, mfi->inode->id);
if (!img)
goto out;
if (pb_read_one(img, &mie, PB_MEMFD_INODE) < 0)
goto out;
mie = mfi->inode->mie;
if (snprintf(buf, s, "%s%s", MEMFD_PREFIX, mie->name) >= s) {
pr_err("Buffer too small for memfd name %s\n", mie->name);
goto out;
return NULL;
}
ret = buf;
out:
if (img)
close_image(img);
if (mie)
memfd_inode_entry__free_unpacked(mie, NULL);
return ret;
return buf;
}
static struct file_desc_ops memfd_desc_ops = {
@ -427,7 +412,8 @@ struct collect_image_info memfd_cinfo = {
.collect = collect_one_memfd,
};
struct file_desc *collect_memfd(u32 id) {
struct file_desc *collect_memfd(u32 id)
{
struct file_desc *fdesc;
fdesc = find_file_desc_raw(FD_TYPES__MEMFD, id);

View File

@ -18,4 +18,5 @@ message memfd_inode_entry {
required uint64 size = 4;
required uint32 shmid = 5;
required uint32 seals = 6 [(criu).flags = "seals.flags"];
required uint64 inode_id = 7;
};