2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-30 13:58:34 +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) static int crtools_prepare_shared(void)
{ {
if (prepare_memfd_inodes())
return -1;
if (prepare_files()) if (prepare_files())
return -1; 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(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"),

View File

@@ -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,

View File

@@ -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

View File

@@ -46,6 +46,7 @@ struct memfd_inode {
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);

View File

@@ -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;
}; };