One way to provide some meaningful information about the reason for
which a checkpoint failed, is to write the information as a regular
record to the output stream.

Specifically, if an error is detected, then we write a special 'struct
ckpt_hdr_error' record to the output file, followed by a string that
describes the details of why the checkpoint failed.

Signed-off-by: Oren Laadan <[email protected]>
---
 checkpoint/checkpoint.c        |   55 ++++++++++++++++++++++++++++++++++++++-
 include/linux/checkpoint_hdr.h |   10 ++++++-
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
index 32a0a8e..7f5c18c 100644
--- a/checkpoint/checkpoint.c
+++ b/checkpoint/checkpoint.c
@@ -95,6 +95,50 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int 
len)
        return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING);
 }
 
+/**
+ * ckpt_write_err - write an object describing an error
+ * @ctx: checkpoint context
+ * @fmt: error string format
+ * @...: error string arguments
+ */
+int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
+{
+       va_list args;
+       char str[128];
+       char *ptr = NULL;
+       int len, ret;
+
+       ret = ckpt_write_obj_type(ctx, NULL, sizeof(struct ckpt_hdr),
+                                 CKPT_HDR_ERROR);
+       if (ret < 0)
+               return ret;
+
+       va_start(args, fmt);
+       len = vsnprintf(str, 128, fmt, args) + 1;
+       va_end(args);
+
+       if (len > 128) {
+               /* doesn't fit on stack, allocate memory */
+               ptr = kmalloc(len + 1, GFP_KERNEL);
+               /* if malloc failed, fallback to truncated string */
+               if (ptr) {
+                       va_start(args, fmt);
+                       len = vsnprintf(ptr, len, fmt, args) + 1;
+                       va_end(args);
+               } else {
+                       len = 128;
+                       printk(KERN_NOTICE "c/r: error message truncated\n");
+               }
+       }
+
+       ckpt_debug("c/r: checkpoint error: %s\n", ptr ? : str);
+       ret = ckpt_write_string(ctx, ptr ? : str, len);
+
+       kfree(ptr);
+       return ret;
+}
+
+
 /***********************************************************************
  * Checkpoint
  */
@@ -198,8 +242,11 @@ static int may_checkpoint_task(struct task_struct *t, 
struct ckpt_ctx *ctx)
                return -EPERM;
 
        /* verify that the task is frozen (unless self) */
-       if (t != current && !frozen(t))
+       if (t != current && !frozen(t)) {
+               ckpt_write_err(ctx, "task %d(%s) not frozen\n",
+                              task_pid_vnr(t), t->comm);
                return -EBUSY;
+       }
 
        /* FIX: add support for ptraced tasks */
        if (task_ptrace(t))
@@ -436,8 +483,11 @@ static int get_container(struct ckpt_ctx *ctx, pid_t pid)
        ctx->root_init = is_container_init(task);
 
        /* FIX: does this error code makes sense here ? */
-       if (!(ctx->flags & CHECKPOINT_SUBTREE) && !ctx->root_init)
+       if (!(ctx->flags & CHECKPOINT_SUBTREE) && !ctx->root_init) {
+               ckpt_write_err(ctx, "task %d(%s) not container init\n",
+                              task_pid_vnr(task), task->comm);
                return -EBUSY;
+       }
 
        return 0;
 
@@ -501,6 +551,7 @@ int do_checkpoint(struct ckpt_ctx *ctx, pid_t pid)
        if (!(ctx->flags & CHECKPOINT_SUBTREE)) {
                /* verify that all objects are contained (no leaks) */
                if (!ckpt_obj_contained(ctx)) {
+                       ckpt_write_err(ctx, "container is not isolated\n");
                        ret = -EBUSY;
                        goto out;
                }
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 0e15f3f..058412c 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -73,9 +73,17 @@ enum {
        CKPT_HDR_IPC_MSG_MSG,
        CKPT_HDR_IPC_SEM,
 
-       CKPT_HDR_TAIL = 5001
+       CKPT_HDR_TAIL = 5001,
+
+       CKPT_HDR_ERROR = 9999
 };
 
+/* error report */
+struct ckpt_hdr_error {
+       struct ckpt_hdr h;
+       /* followed by the error string */
+} __attribute__((aligned(8)));
+
 /* shared objrects (objref) */
 struct ckpt_hdr_objref {
        struct ckpt_hdr h;
-- 
1.5.4.3

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to