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

Andrey Mirkin
2008-09-03T14:09:27Z

On Wednesday 03 September 2008 16:29 Matthieu Fertré wrote:
> 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 for the idea with enum, I'll fix it in next version.

Regards,
Andrey

>
> > + 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)