Re: [PATCH 3/9] Introduce context structure needed during checkpointing/restart

Matthieu Fertré
2008-09-03T12:39:18Z

Andrey Mirkin a écrit :
> Add functions for context allocation/destroy.
> Introduce functions to read/write image.
> Introduce image header and object header.
>
> Signed-off-by: Andrey Mirkin <major@openvz.org>
> ---
> cpt/cpt.h | 37 ++++++++++++++++
> cpt/cpt_image.h | 63 +++++++++++++++++++++++++++
> cpt/sys.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 224 insertions(+), 3 deletions(-)
> create mode 100644 cpt/cpt_image.h
>
> diff --git a/cpt/cpt.h b/cpt/cpt.h
> index 381a9bf..607ac1b 100644
> --- a/cpt/cpt.h
> +++ b/cpt/cpt.h
> @@ -10,6 +10,8 @@
> *
> */
>
> +#include "cpt_image.h"
> +
> struct cpt_operations
> {
> struct module * owner;
> @@ -17,3 +19,38 @@ struct cpt_operations
> int (*restart)(int ctid, int fd, unsigned long flags);
> };
> extern struct cpt_operations cpt_ops;
> +
> +#define CPT_CTX_ERROR -1
> +#define CPT_CTX_IDLE 0
> +#define CPT_CTX_DUMPING 1
> +#define CPT_CTX_UNDUMPING 2
>

Maybe you can define an enum here instead.

> +
> +typedef struct cpt_context
> +{
> + pid_t pid; /* should be changed to ctid later */
> + int ctx_id; /* context id */
> + struct list_head ctx_list;
> + int refcount;
> + int ctx_state;
>

It will be more clear that ctx_state refers to it.

Thanks,

Matthieu

> + struct semaphore main_sem;
> +
> + int errno;
> +
> + struct file *file;
> + loff_t current_object;
> +
> + struct list_head object_array[CPT_OBJ_MAX];
> +
> + int (*write)(const void *addr, size_t count, struct cpt_context *ctx);
> + int (*read)(void *addr, size_t count, struct cpt_context *ctx);
> +} cpt_context_t;
> +
> +extern int debug_level;
> +
> +#define cpt_printk(lvl, fmt, args...) do { \
> + if (lvl <= debug_level) \
> + printk(fmt, ##args); \
> + } while (0)
> +
> +#define eprintk(a...) cpt_printk(1, "CPT ERR: " a)
> +#define dprintk(a...) cpt_printk(1, "CPT DBG: " a)
> diff --git a/cpt/cpt_image.h b/cpt/cpt_image.h
> new file mode 100644
> index 0000000..3d26229
> --- /dev/null
> +++ b/cpt/cpt_image.h
> @@ -0,0 +1,63 @@
> +/*
> + * Copyright (C) 2008 Parallels, Inc.
> + *
> + * Author: Andrey Mirkin <major@openvz.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation, version 2 of the
> + * License.
> + *
> + */
> +
> +#ifndef __CPT_IMAGE_H_
> +#define __CPT_IMAGE_H_ 1
> +
> +enum _cpt_object_type
> +{
> + CPT_OBJ_TASK = 0,
> + CPT_OBJ_MAX,
> + /* The objects above are stored in memory while checkpointing */
> +
> + CPT_OBJ_HEAD = 1024,
> +};
> +
> +enum _cpt_content_type {
> + CPT_CONTENT_VOID,
> + CPT_CONTENT_ARRAY,
> + CPT_CONTENT_DATA,
> + CPT_CONTENT_NAME,
> + CPT_CONTENT_REF,
> + CPT_CONTENT_MAX
> +};
> +
> +#define CPT_SIGNATURE0 0x79
> +#define CPT_SIGNATURE1 0x1c
> +#define CPT_SIGNATURE2 0x01
> +#define CPT_SIGNATURE3 0x63
> +
> +struct cpt_head
> +{
> + __u8 cpt_signature[4]; /* Magic number */
> + __u32 cpt_hdrlen; /* Header length */
> + __u16 cpt_image_major; /* Format of this file */
> + __u16 cpt_image_minor; /* Format of this file */
> + __u16 cpt_image_sublevel; /* Format of this file */
> + __u16 cpt_image_extra; /* Format of this file */
> + __u16 cpt_arch; /* Architecture */
> + __u16 cpt_pad1;
> + __u32 cpt_pad2;
> +#define CPT_ARCH_I386 0
> + __u64 cpt_time; /* Time */
> +} __attribute__ ((aligned (8)));
> +
> +/* Common object header. */
> +struct cpt_object_hdr
> +{
> + __u64 cpt_len; /* Size of current chunk of data */
> + __u16 cpt_type; /* Type of object */
> + __u32 cpt_hdrlen; /* Size of header */
> + __u16 cpt_content; /* Content type: array, reference... */
> +} __attribute__ ((aligned (8)));
> +
> +#endif /* __CPT_IMAGE_H_ */
> diff --git a/cpt/sys.c b/cpt/sys.c
> index 4051286..8334c4c 100644
> --- a/cpt/sys.c
> +++ b/cpt/sys.c
> @@ -13,21 +13,142 @@
> #include <linux/sched.h>
> #include <linux/fs.h>
> #include <linux/file.h>
> -#include <linux/notifier.h>
> +#include <linux/uaccess.h>
> #include <linux/module.h>
>
> #include "cpt.h"
> +#include "cpt_image.h"
>
> MODULE_LICENSE("GPL");
>
> +/* Debug level, constant for now */
> +int debug_level = 1;
> +
> +static int file_write(const void *addr, size_t count, struct cpt_context *ctx)
> +{
> + mm_segment_t oldfs;
> + ssize_t err = -EBADF;
> + struct file *file = ctx->file;
> +
> + oldfs = get_fs(); set_fs(KERNEL_DS);
> + if (file)
> + err = file->f_op->write(file, addr, count, &file->f_pos);
> + set_fs(oldfs);
> + if (err != count)
> + return err >= 0 ? -EIO : err;
> + return 0;
> +}
> +
> +static int file_read(void *addr, size_t count, struct cpt_context *ctx)
> +{
> + mm_segment_t oldfs;
> + ssize_t err = -EBADF;
> + struct file *file = ctx->file;
> +
> + oldfs = get_fs(); set_fs(KERNEL_DS);
> + if (file)
> + err = file->f_op->read(file, addr, count, &file->f_pos);
> + set_fs(oldfs);
> + if (err != count)
> + return err >= 0 ? -EIO : err;
> + return 0;
> +}
> +
> +struct cpt_context * context_alloc(void)
> +{
> + struct cpt_context *ctx;
> + int i;
> +
> + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> + if (!ctx)
> + return NULL;
> +
> + init_MUTEX(&ctx->main_sem);
> + ctx->refcount = 1;
> +
> + ctx->current_object = -1;
> + ctx->write = file_write;
> + ctx->read = file_read;
> + for (i = 0; i < CPT_OBJ_MAX; i++) {
> + INIT_LIST_HEAD(&ctx->object_array[i]);
> + }
> +
> + return ctx;
> +}
> +
> +void context_release(struct cpt_context *ctx)
> +{
> + ctx->ctx_state = CPT_CTX_ERROR;
> +
> + if (ctx->file)
> + fput(ctx->file);
> + kfree(ctx);
> +}
> +
> +static void context_put(struct cpt_context *ctx)
> +{
> + if (!--ctx->refcount)
> + context_release(ctx);
> +}
> +
> static int checkpoint(pid_t pid, int fd, unsigned long flags)
> {
> - return -ENOSYS;
> + struct file *file;
> + struct cpt_context *ctx;
> + int err;
> +
> + err = -EBADF;
> + file = fget(fd);
> + if (!file)
> + goto out;
> +
> + err = -ENOMEM;
> + ctx = context_alloc();
> + if (!ctx)
> + goto out_file;
> +
> + ctx->file = file;
> + ctx->ctx_state = CPT_CTX_DUMPING;
> +
> + /* checkpoint */
> + err = -ENOSYS;
> +
> + context_put(ctx);
> +
> +out_file:
> + fput(file);
> +out:
> + return err;
> }
>
> static int restart(int ctid, int fd, unsigned long flags)
> {
> - return -ENOSYS;
> + struct file *file;
> + struct cpt_context *ctx;
> + int err;
> +
> + err = -EBADF;
> + file = fget(fd);
> + if (!file)
> + goto out;
> +
> + err = -ENOMEM;
> + ctx = context_alloc();
> + if (!ctx)
> + goto out_file;
> +
> + ctx->file = file;
> + ctx->ctx_state = CPT_CTX_UNDUMPING;
> +
> + /* restart */
> + err = -ENOSYS;
> +
> + context_put(ctx);
> +
> +out_file:
> + fput(file);
> +out:
> + return err;
> }
>
> static int __init init_cptrst(void)
>

--
Matthieu Fertré

IRISA, Campus universitaire de Beaulieu - 35 042 Rennes, France
tel: +33 2 99 84 22 74
fax: +33 2 99 84 71 71
mail: mfertre@irisa.fr