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:
parent
967797a867
commit
e3a5d09752
@ -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;
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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
|
||||
|
90
criu/memfd.c
90
criu/memfd.c
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user