mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 16:25:31 +00:00
files: add ability to set callbacks for files (v7)
Here is nothing interecting. If a file can't be dumped by criu, plugins are called. If one of plugins knows how to dump the file, the file entry is marked as need_callback. On restore if we see this mark, we execute plugins for restoring the file. v2: Callbacks are called for all files, which are not supported by CRIU. v3: Call plugins for a file instead of file descriptor. A few file descriptors can be associated with one file. v4: A file descriptor is opened in a callback. It's required for restoring anon vmas. v5: Add a separate type for unsupported files v6: define FD_TYPES__UNSUPP v7: s/unsupp/ext (external) Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
1e4b8c8c23
commit
6bbdec26f3
@@ -29,6 +29,7 @@ obj-y += sk-netlink.o
|
||||
obj-y += sk-queue.o
|
||||
obj-y += files.o
|
||||
obj-y += files-reg.o
|
||||
obj-y += files-ext.o
|
||||
obj-y += pipes.o
|
||||
obj-y += fifo.o
|
||||
obj-y += file-ids.o
|
||||
|
@@ -141,6 +141,7 @@ static struct collect_image_info *cinfos[] = {
|
||||
&tty_info_cinfo,
|
||||
&tty_cinfo,
|
||||
&tunfile_cinfo,
|
||||
&ext_file_cinfo,
|
||||
};
|
||||
|
||||
static int root_prepare_shared(void)
|
||||
|
@@ -319,6 +319,7 @@ static struct show_image_info show_infos[] = {
|
||||
SHOW_PLAINS(FILE_LOCK),
|
||||
SHOW_PLAIN(RLIMIT),
|
||||
SHOW_PLAIN(TUNFILE),
|
||||
SHOW_PLAINS(EXT_FILE),
|
||||
|
||||
{ TCP_STREAM_MAGIC, PB_TCP_STREAM, true, show_tcp_stream, "1:%u 2:%u 3:%u 4:%u 12:%u", },
|
||||
{ STATS_MAGIC, PB_STATS, true, NULL, "1.1:%u 1.2:%u 1.3:%u 1.4:%u 1.5:%Lu 1.6:%Lu 1.7:%Lu", },
|
||||
|
93
files-ext.c
Normal file
93
files-ext.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* An external file is a file, which is dumped with help a plugin */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fdset.h"
|
||||
#include "files.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "protobuf/ext-file.pb-c.h"
|
||||
|
||||
int dump_one_ext_file(int lfd, u32 id, const struct fd_parms *p)
|
||||
{
|
||||
int rfd, ret;
|
||||
|
||||
ExtFileEntry xfe = EXT_FILE_ENTRY__INIT;
|
||||
|
||||
ret = cr_plugin_dump_file(lfd, id);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
xfe.id = id;
|
||||
xfe.fown = (FownEntry *)&p->fown;
|
||||
|
||||
rfd = fdset_fd(glob_fdset, CR_FD_EXT_FILES);
|
||||
|
||||
return pb_write_one(rfd, &xfe, PB_EXT_FILE);
|
||||
}
|
||||
|
||||
const struct fdtype_ops ext_dump_ops = {
|
||||
.type = FD_TYPES__EXT,
|
||||
.dump = dump_one_ext_file,
|
||||
};
|
||||
|
||||
struct ext_file_info {
|
||||
struct file_desc d;
|
||||
ExtFileEntry *xfe;
|
||||
};
|
||||
|
||||
static int open_fd(struct file_desc *d)
|
||||
{
|
||||
struct ext_file_info *xfi;
|
||||
int fd;
|
||||
|
||||
xfi = container_of(d, struct ext_file_info, d);
|
||||
|
||||
fd = cr_plugin_restore_file(xfi->xfe->id);
|
||||
if (fd < 0) {
|
||||
pr_err("Unable to restore %#x\n", xfi->xfe->id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (restore_fown(fd, xfi->xfe->fown))
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static struct file_desc_ops ext_desc_ops = {
|
||||
.type = FD_TYPES__EXT,
|
||||
.open = open_fd,
|
||||
};
|
||||
|
||||
static int collect_one_ext(void *o, ProtobufCMessage *base)
|
||||
{
|
||||
struct ext_file_info *xfi = o;
|
||||
|
||||
xfi->xfe = pb_msg(base, ExtFileEntry);
|
||||
|
||||
pr_info("Collected external file with ID %#x\n", xfi->xfe->id);
|
||||
return file_desc_add(&xfi->d, xfi->xfe->id, &ext_desc_ops);
|
||||
}
|
||||
|
||||
struct collect_image_info ext_file_cinfo = {
|
||||
.fd_type = CR_FD_EXT_FILES,
|
||||
.pb_type = PB_EXT_FILE,
|
||||
.priv_size = sizeof(struct ext_file_info),
|
||||
.collect = collect_one_ext,
|
||||
};
|
||||
|
||||
int dump_unsupp_fd(struct fd_parms *p, int lfd,
|
||||
const int fdinfo, char *more, char *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = do_dump_gen_file(p, lfd, &ext_dump_ops, fdinfo);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
if (ret == -ENOTSUP)
|
||||
pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
|
||||
p->fd, p->stat.st_mode, more, info);
|
||||
return -1;
|
||||
}
|
@@ -20,6 +20,7 @@
|
||||
#include "protobuf/remap-file-path.pb-c.h"
|
||||
|
||||
#include "files-reg.h"
|
||||
#include "plugin.h"
|
||||
|
||||
/*
|
||||
* Ghost files are those not visible from the FS. Dumping them is
|
||||
|
14
files.c
14
files.c
@@ -32,12 +32,16 @@
|
||||
#include "signalfd.h"
|
||||
#include "namespaces.h"
|
||||
#include "tun.h"
|
||||
#include "fdset.h"
|
||||
|
||||
#include "parasite.h"
|
||||
#include "parasite-syscall.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "protobuf/fs.pb-c.h"
|
||||
#include "protobuf/ext-file.pb-c.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#define FDESC_HASH_SIZE 64
|
||||
static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
|
||||
@@ -170,7 +174,7 @@ int do_dump_gen_file(struct fd_parms *p, int lfd,
|
||||
ret = ops->dump(lfd, e.id, p);
|
||||
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return ret;
|
||||
|
||||
pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8"PRIx64" fd: %d\n",
|
||||
ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
|
||||
@@ -239,14 +243,6 @@ static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_unsupp_fd(const struct fd_parms *p, int lfd,
|
||||
const int fdinfo, char *more, char *info)
|
||||
{
|
||||
pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
|
||||
p->fd, p->stat.st_mode, more, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct fdtype_ops *get_misc_dev_ops(int minor)
|
||||
{
|
||||
switch (minor) {
|
||||
|
@@ -23,6 +23,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
|
||||
FD_ENTRY(PAGEMAP, "pagemap-%ld"),
|
||||
FD_ENTRY(SHMEM_PAGEMAP, "pagemap-shmem-%ld"),
|
||||
FD_ENTRY(REG_FILES, "reg-files"),
|
||||
FD_ENTRY(EXT_FILES, "ext-files"),
|
||||
FD_ENTRY(NS_FILES, "ns-files"),
|
||||
FD_ENTRY(EVENTFD_FILE, "eventfd"),
|
||||
FD_ENTRY(EVENTPOLL_FILE,"eventpoll"),
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __CRIU_PLUGIN_H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef int (cr_plugin_init_t)(void);
|
||||
typedef void (cr_plugin_fini_t)(void);
|
||||
@@ -28,6 +29,9 @@ typedef void (cr_plugin_fini_t)(void);
|
||||
typedef int (cr_plugin_dump_unix_sk_t)(int fd, int id);
|
||||
typedef int (cr_plugin_restore_unix_sk_t)(int id);
|
||||
|
||||
typedef int (cr_plugin_dump_file_t)(int fd, int id);
|
||||
typedef int (cr_plugin_restore_file_t)(int id);
|
||||
|
||||
/* Public API */
|
||||
extern int criu_get_image_dir(void);
|
||||
|
||||
|
@@ -147,4 +147,8 @@ extern int close_old_fds(struct pstree_item *me);
|
||||
|
||||
extern int shared_fdt_prepare(struct pstree_item *item);
|
||||
|
||||
extern struct collect_image_info ext_file_cinfo;
|
||||
extern int dump_unsupp_fd(struct fd_parms *p, int lfd,
|
||||
const int fdinfo, char *more, char *info);
|
||||
|
||||
#endif /* __CR_FILES_H__ */
|
||||
|
@@ -56,6 +56,7 @@ enum {
|
||||
_CR_FD_GLOB_FROM,
|
||||
CR_FD_SK_QUEUES,
|
||||
CR_FD_REG_FILES,
|
||||
CR_FD_EXT_FILES,
|
||||
CR_FD_NS_FILES,
|
||||
CR_FD_INETSK,
|
||||
CR_FD_UNIXSK,
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#define IPCNS_MSG_MAGIC 0x55453737 /* Moscow */
|
||||
#define IPCNS_SEM_MAGIC 0x59573019 /* St. Petersburg */
|
||||
#define REG_FILES_MAGIC 0x50363636 /* Belgorod */
|
||||
#define EXT_FILES_MAGIC 0x59255641 /* Usolye */
|
||||
#define FS_MAGIC 0x51403912 /* Voronezh */
|
||||
#define MM_MAGIC 0x57492820 /* Pskov */
|
||||
#define REMAP_FPATH_MAGIC 0x59133954 /* Vologda */
|
||||
|
@@ -11,4 +11,7 @@ int cr_plugin_init(void);
|
||||
int cr_plugin_dump_unix_sk(int fd, int id);
|
||||
int cr_plugin_restore_unix_sk(int id);
|
||||
|
||||
int cr_plugin_dump_file(int fd, int id);
|
||||
int cr_plugin_restore_file(int id);
|
||||
|
||||
#endif
|
||||
|
@@ -25,6 +25,7 @@ enum {
|
||||
PB_GHOST_FILE,
|
||||
PB_TCP_STREAM,
|
||||
PB_REG_FILE,
|
||||
PB_EXT_FILE,
|
||||
PB_NS_FILE,
|
||||
PB_INET_SK,
|
||||
PB_UNIX_SK,
|
||||
|
20
plugin.c
20
plugin.c
@@ -17,6 +17,8 @@ struct cr_plugin_entry {
|
||||
|
||||
cr_plugin_dump_unix_sk_t *cr_plugin_dump_unix_sk;
|
||||
cr_plugin_restore_unix_sk_t *cr_plugin_restore_unix_sk;
|
||||
cr_plugin_dump_file_t *cr_plugin_dump_file;
|
||||
cr_plugin_restore_file_t *cr_plugin_restore_file;
|
||||
};
|
||||
|
||||
struct cr_plugin_entry *next;
|
||||
@@ -27,6 +29,8 @@ struct cr_plugins {
|
||||
|
||||
struct cr_plugin_entry *cr_plugin_dump_unix_sk;
|
||||
struct cr_plugin_entry *cr_plugin_restore_unix_sk;
|
||||
struct cr_plugin_entry *cr_plugin_dump_file;
|
||||
struct cr_plugin_entry *cr_plugin_restore_file;
|
||||
};
|
||||
|
||||
struct cr_plugins cr_plugins;
|
||||
@@ -73,6 +77,16 @@ int cr_plugin_restore_unix_sk(int id)
|
||||
return run_plugin_funcs(cr_plugin_restore_unix_sk, id);
|
||||
}
|
||||
|
||||
int cr_plugin_dump_file(int fd, int id)
|
||||
{
|
||||
return run_plugin_funcs(cr_plugin_dump_file, fd, id);
|
||||
}
|
||||
|
||||
int cr_plugin_restore_file(int id)
|
||||
{
|
||||
return run_plugin_funcs(cr_plugin_restore_file, id);
|
||||
}
|
||||
|
||||
static int cr_lib_load(char *path)
|
||||
{
|
||||
struct cr_plugin_entry *ce;
|
||||
@@ -89,6 +103,9 @@ static int cr_lib_load(char *path)
|
||||
add_plugin_func(cr_plugin_dump_unix_sk);
|
||||
add_plugin_func(cr_plugin_restore_unix_sk);
|
||||
|
||||
add_plugin_func(cr_plugin_dump_file);
|
||||
add_plugin_func(cr_plugin_restore_file);
|
||||
|
||||
ce = NULL;
|
||||
f_fini = dlsym(h, "cr_plugin_fini");
|
||||
if (f_fini) {
|
||||
@@ -127,6 +144,9 @@ void cr_plugin_fini(void)
|
||||
cr_plugin_free(cr_plugin_dump_unix_sk);
|
||||
cr_plugin_free(cr_plugin_restore_unix_sk);
|
||||
|
||||
cr_plugin_free(cr_plugin_dump_file);
|
||||
cr_plugin_free(cr_plugin_restore_file);
|
||||
|
||||
while (cr_plugins.cr_fini) {
|
||||
ce = cr_plugins.cr_fini;
|
||||
cr_plugins.cr_fini = cr_plugins.cr_fini->next;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "protobuf/inventory.pb-c.h"
|
||||
#include "protobuf/stats.pb-c.h"
|
||||
#include "protobuf/regfile.pb-c.h"
|
||||
#include "protobuf/ext-file.pb-c.h"
|
||||
#include "protobuf/ns.pb-c.h"
|
||||
#include "protobuf/eventfd.pb-c.h"
|
||||
#include "protobuf/eventpoll.pb-c.h"
|
||||
|
@@ -57,6 +57,7 @@ proto-obj-y += rlimit.o
|
||||
proto-obj-y += pagemap.o
|
||||
proto-obj-y += siginfo.o
|
||||
proto-obj-y += rpc.o
|
||||
proto-obj-y += ext-file.o
|
||||
|
||||
proto := $(proto-obj-y:.o=)
|
||||
proto-c := $(proto-obj-y:.o=.pb-c.c)
|
||||
|
6
protobuf/ext-file.proto
Normal file
6
protobuf/ext-file.proto
Normal file
@@ -0,0 +1,6 @@
|
||||
import "fown.proto";
|
||||
|
||||
message ext_file_entry {
|
||||
required uint32 id = 1;
|
||||
required fown_entry fown = 5;
|
||||
}
|
@@ -15,6 +15,7 @@ enum fd_types {
|
||||
NETLINKSK = 13;
|
||||
NS = 14;
|
||||
TUN = 15;
|
||||
EXT = 16;
|
||||
}
|
||||
|
||||
message fdinfo_entry {
|
||||
|
Reference in New Issue
Block a user