[CRIU] [PATCH 4/5] kdat: Cache kdat object into /run/criu.kdat (v2)
Mike Rapoport
rppt at linux.vnet.ibm.com
Wed Apr 26 22:37:09 PDT 2017
On Wed, Apr 26, 2017 at 04:37:34PM +0300, Pavel Emelyanov wrote:
> Doing kerndat checks on every criu start is way too slow. We
> need some way to speed this checks up on a particular box.
>
> As suggested by Andre, Dima and Mike let's try to keep the
> collected kdat bits into some tmpfs file. Keeping it on
> tmpfs would invaludate this cache on every machine reboot.
>
> There have been many suggestions how to generate this file,
> my proposal is to create it once the kdat object is filled
> by criu, w/o any explicit command. Optionally we can add
> 'criu kdat --save|--drop' actions to manage this file.
>
> v2:
> * don't ignore return code of write() (some glibcs complain)
> * unlink tmp file in case rename failed
>
> Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
> ---
> criu/include/kerndat.h | 6 ++++
> criu/include/magic.h | 7 +++++
> criu/kerndat.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 97 insertions(+), 1 deletion(-)
>
> diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
> index 6b621c6..b1722eb 100644
> --- a/criu/include/kerndat.h
> +++ b/criu/include/kerndat.h
> @@ -29,6 +29,12 @@ enum loginuid_func {
> };
>
> struct kerndat_s {
> + /*
> + * XXX: This structure is written AS IS into a tmpfs file,
> + * so any changes in it should result in changed KDAT_MAGIC
> + * value to avoid loading of bad kdat bits.
> + */
> + u32 magic;
> dev_t shmem_dev;
> int last_cap;
> u64 zero_page_pfn;
> diff --git a/criu/include/magic.h b/criu/include/magic.h
> index 059d005..2297930 100644
> --- a/criu/include/magic.h
> +++ b/criu/include/magic.h
> @@ -116,4 +116,11 @@
> #define STATS_MAGIC 0x57093306 /* Ostashkov */
> #define IRMAP_CACHE_MAGIC 0x57004059 /* Ivanovo */
>
> +/*
> + * Magic for kerndat_s structure. When changing, keep the
> + * old magics to avoid magic re-use.
> + */
> +
> +#define KDAT_MAGIC_1 0x57023458 /* Torzhok */
> +
> #endif /* __CR_MAGIC_H__ */
> diff --git a/criu/kerndat.c b/criu/kerndat.c
> index 87a7b62..3aca1e4 100644
> --- a/criu/kerndat.c
> +++ b/criu/kerndat.c
> @@ -650,10 +650,93 @@ close:
> bclose(&f);
> return ret;
> }
> +
> +#define KERNDAT_CACHE_FILE "/run/criu.kdat"
> +#define KERNDAT_CACHE_FILE_TMP "/run/.criu.kdat"
What about running criu as non-root user?
> +static int kerndat_try_load_cache(void)
> +{
> + int fd, ret;
> +
> + fd = open(KERNDAT_CACHE_FILE, O_RDONLY);
> + if (fd < 0) {
> + if (errno == ENOENT)
> + return 1;
> +
> + pr_perror("Can't load %s", KERNDAT_CACHE_FILE);
> + return -1;
> + }
> +
> + ret = read(fd, &kdat, sizeof(kdat));
> + if (ret < 0) {
> + pr_perror("Can'r read kdat cache");
> + return -1;
> + }
> +
> + close(fd);
> +
> + if (ret != sizeof(kdat) || kdat.magic != KDAT_MAGIC_1) {
> + pr_warn("Stale %s file\n", KERNDAT_CACHE_FILE);
> + unlink(KERNDAT_CACHE_FILE);
> + return 1;
> + }
> +
> + pr_info("Loaded criu.kdat cache\n");
> + return 0;
> +}
> +
> +static int kerndat_save_cache(void)
> +{
> + int fd, ret;
> + struct statfs s;
> +
> + fd = open(KERNDAT_CACHE_FILE_TMP, O_CREAT | O_EXCL | O_WRONLY, 0600);
> + if (fd < 0) {
> + /*
> + * It can happen that we race with some other criu
> + * instance. That's OK, just ignore this error and
> + * proceed.
> + */
> + if (errno == EEXIST)
> + return 0;
> +
> + pr_perror("Can't save %s", KERNDAT_CACHE_FILE_TMP);
> + return -1;
> + }
> +
> + if (fstatfs(fd, &s) < 0) {
> + pr_perror("Can't statfs %s", KERNDAT_CACHE_FILE_TMP);
> + return -1;
> + }
> +
> + if (s.f_type != TMPFS_MAGIC) {
> + pr_warn("Can't keep criu.kdat on tempfs\n");
> + close(fd);
> + return 0;
> + }
> +
> + kdat.magic = KDAT_MAGIC_1;
> + ret = write(fd, &kdat, sizeof(kdat));
> + if (ret != sizeof(kdat))
> + pr_warn("Kerndat cache writing failed.\n");
> + close(fd);
> +
> + ret = rename(KERNDAT_CACHE_FILE_TMP, KERNDAT_CACHE_FILE);
> + if (ret < 0) {
> + pr_perror("Can't save %s", KERNDAT_CACHE_FILE);
> + unlink(KERNDAT_CACHE_FILE_TMP);
> + }
> + return ret;
> +}
> +
> int kerndat_init(void)
> {
> int ret;
>
> + ret = kerndat_try_load_cache();
> + if (ret <= 0)
> + return ret;
> +
> ret = check_pagemap();
> if (!ret)
> ret = kerndat_get_shmemdev();
> @@ -691,5 +774,5 @@ int kerndat_init(void)
> kerndat_lsm();
> kerndat_mmap_min_addr();
>
> - return ret;
> + return kerndat_save_cache();
> }
> --
> 2.5.5
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
>
More information about the CRIU
mailing list