All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Standardize c/r error reporting
@ 2009-10-29 20:54 serue-r/Jw6+rmf7HQT0dZR+AlfA
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

This patchset
	1. defines ckpt_error() 
	2. allows users to pass a logfd into sys_checkpoint and
	   sys_restart
	3. Switches ckpt_write_err() to accepting a single enhanced
	   format string, instead of two separate formats.
	4. Has ckpt_write_err() call ckpt_error() to also log the
	   error in the user-provided logfile and syslog.

Every ckpt_error() message is prefixed by current's global pid,
current's virtual pid, number of bytes read/written, and the
ctx->errno.

I'm sure we'll want another round if only to alter the format,
but I'm finding it very useful as is.

(As more callers are added I expect we'll want to add %(A) to
the format to indicate active_pid should be printed).

-serge

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
       [not found]     ` <1256849682-858-2-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2009-10-29 20:54   ` [PATCH 02/17] ckpt_write_err update arch/x86/mm/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (16 subsequent siblings)
  17 siblings, 1 reply; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Matt Helsley originally suggested this to avoid having two
format strings.  This is not bisect-safe and therefore not
even compile-tested.  Every call to ckpt_write_err must be
updated to use a single format.

Changelog:
	Oct 29: merge with the next patch, moving ckpt_generate_fmt()
		into checkpoing/sys.c and making it non-static so that
		we can use it in ckpt_error().
	Oct 28: also fix comment above ckpt_generate_fmt()
	Oct 27: ensure %(T) has a closing paren

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/checkpoint.c    |  105 +++-----------------------------------------
 checkpoint/sys.c           |   95 +++++++++++++++++++++++++++++++++++++++
 include/linux/checkpoint.h |   13 +++--
 3 files changed, 110 insertions(+), 103 deletions(-)

diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
index 6eb8f3b..c6be4f9 100644
--- a/checkpoint/checkpoint.c
+++ b/checkpoint/checkpoint.c
@@ -96,104 +96,15 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len)
 	return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING);
 }
 
-/*
- * __ckpt_generate_fmt - generate standard checkpoint error message
- * @ctx: checkpoint context
- * @fmt0: c/r-format string
- * @fmt: message format
- *
- * This generates a unified format of checkpoint error messages, to
- * ease (after the failure) inspection by userspace tools. It converts
- * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
- *
- * PREFMT is constructed from @fmt0 by subtituting format snippets
- * according to the contents of @fmt0.  The format characters in
- * @fmt0 can be E (error), O (objref), P (pointer), S (string) and
- * V (variable/symbol). For example, E will generate a "err %d" in
- * PREFMT (see prefmt_array below).
- *
- * If @fmt0 begins with T, PREFMT will begin with "pid %d tsk %s"
- * with the pid and the tsk->comm of the currently checkpointed task.
- * The latter is taken from ctx->tsk, and is it the responsbilility of
- * the caller to have a valid pointer there (in particular, functions
- * that iterate on the processes: collect_objects, checkpoint_task,
- * and tree_count_tasks).
- *
- * The caller of ckpt_write_err() and _ckpt_write_err() must provide
- * the additional variabes, in order, to match the @fmt0 (except for
- * the T key), e.g.:
- *
- *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags);
- *
- * Here, T is simply passed, E expects an integer (err), O expects an
- * integer (objref), and the last argument matches the format string.
- */
-static char *__ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt0, char *fmt)
-{
-	static int warn_notask = 0;
-	static int warn_prefmt = 0;
-	char *format;
-	int i, j, len = 0;
-
-	static struct {
-		char key;
-		char *fmt;
-	} prefmt_array[] = {
-		{ 'E', "err %d" },
-		{ 'O', "obj %d" },
-		{ 'P', "ptr %p" },
-		{ 'V', "sym %pS" },
-		{ 'S', "str %s" },
-		{ 0, "??? %pS" },
-	};
-
-	/*
-	 * 17 for "pid %d" (plus space)
-	 * 21 for "tsk %s" (tsk->comm)
-	 * up to 8 per varfmt entry
-	 */
-	format = kzalloc(37 + 8 * strlen(fmt0) + strlen(fmt), GFP_KERNEL);
-	if (!format)
-		return NULL;
-
-	format[len++] = '[';
-
-	if (fmt0[0] == 'T') {
-		if (ctx->tsk)
-			len = sprintf(format, "pid %d tsk %s ",
-				      task_pid_vnr(ctx->tsk), ctx->tsk->comm);
-		else if (warn_notask++ < 5)
-			printk(KERN_ERR "c/r: no target task set\n");
-		fmt0++;
-	}
-
-	for (i = 0; i < strlen(fmt0); i++) {
-		for (j = 0; prefmt_array[j].key; j++)
-			if (prefmt_array[j].key == fmt0[i])
-				break;
-		if (!prefmt_array[j].key && warn_prefmt++ < 5)
-			printk(KERN_ERR "c/r: unknown prefmt %c\n", fmt0[i]);
-		len += sprintf(&format[len], "%s ", prefmt_array[j].fmt);
-	}
-
-	if (len > 1)
-		sprintf(&format[len-1], "]: %s", fmt);  /* erase last space */
-	else
-		sprintf(format, "%s", fmt);
-
-	return format;
-}
-
-/* see _ckpt_generate_fmt for information on @fmt0 */
-static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt0,
-				char *fmt, va_list ap)
+/* see ckpt_generate_fmt for information on @fmt extensions */
+static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt, va_list ap)
 {
 	va_list aq;
 	char *format;
 	char *str;
 	int len;
 
-	format = __ckpt_generate_fmt(ctx, fmt0, fmt);
+	format = ckpt_generate_fmt(ctx, fmt);
 	va_copy(aq, ap);
 
 	/*
@@ -223,15 +134,14 @@ static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt0,
  * @fmt: message format
  * @...: arguments
  *
- * See _ckpt_generate_fmt for information on @fmt0.
  * Use this during checkpoint to report while holding a spinlock
  */
-void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
+void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
 {
 	va_list ap;
 
 	va_start(ap, fmt);
-	__ckpt_generate_err(ctx, fmt0, fmt, ap);
+	__ckpt_generate_err(ctx, fmt, ap);
 	va_end(ap);
 }
 
@@ -242,10 +152,9 @@ void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
  * @fmt: error string format
  * @...: error string arguments
  *
- * See _ckpt_generate_fmt for information on @fmt0.
  * If @fmt is null, the string in the ctx->err_string will be used (and freed)
  */
-int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
+int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
 {
 	va_list ap;
 	char *str;
@@ -253,7 +162,7 @@ int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
 
 	if (fmt) {
 		va_start(ap, fmt);
-		__ckpt_generate_err(ctx, fmt0, fmt, ap);
+		__ckpt_generate_err(ctx,  fmt, ap);
 		va_end(ap);
 	}
 
diff --git a/checkpoint/sys.c b/checkpoint/sys.c
index 260a1ee..9b2de18 100644
--- a/checkpoint/sys.c
+++ b/checkpoint/sys.c
@@ -339,6 +339,101 @@ int walk_task_subtree(struct task_struct *root,
 	return (ret < 0 ? ret : total);
 }
 
+/*
+ * ckpt_generate_fmt - generate standard checkpoint error message
+ * @ctx: checkpoint context
+ * @fmt: message format
+ *
+ * This generates a unified format of checkpoint error messages, to
+ * ease (after the failure) inspection by userspace tools. It converts
+ * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
+ *
+ * PREFMT is constructed from @fmt by subtituting format snippets
+ * according to the contents of @fmt.  The format characters in
+ * @fmt can be %(E) (error), %(O) (objref), %(P) (pointer), %(S) (string),
+ * %(C) (bytes read/written out of checkpoint image so far), * and %(V)
+ * (variable/symbol). For example, %(E) will generate a "err %d"
+ * in PREFMT.
+ *
+ * If @fmt begins with %(T), PREFMT will begin with "pid %d tsk %s"
+ * with the pid and the tsk->comm of the currently checkpointed task.
+ * The latter is taken from ctx->tsk, and is it the responsbilility of
+ * the caller to have a valid pointer there (in particular, functions
+ * that iterate on the processes: collect_objects, checkpoint_task,
+ * and tree_count_tasks).
+ *
+ * The caller of ckpt_write_err() and _ckpt_write_err() must provide
+ * the additional variabes, in order, to match the @fmt0 (except for
+ * the T key), e.g.:
+ *
+ *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags);
+ *
+ * Here, T is simply passed, E expects an integer (err), O expects an
+ * integer (objref), and the last argument matches the format string.
+ *
+ * XXX Do we want 'T' and 'C' to simply always be prepended?
+ */
+char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
+{
+	char *format;
+	int alloclen, len = 0;
+	int first = 1;
+
+	/*
+	 * 17 for "pid %d" (plus space)
+	 * 21 for "tsk %s" (tsk->comm)
+	 * up to 8 per varfmt entry
+	 */
+	alloclen = 37 + 8 * strlen(fmt);
+	format = kzalloc(alloclen, GFP_KERNEL);
+	if (!format)
+		return NULL;
+
+	for (; *fmt; fmt++) {
+		BUG_ON(len > alloclen);
+		if (*fmt != '%' || fmt[1] != '(' || fmt[3] != ')') {
+			format[len++] = *fmt;
+			continue;
+		}
+		if (!first)
+			format[len++] = ' ';
+		else
+			first = 0;
+		switch (fmt[2]) {
+		case 'E':
+			len += sprintf(format+len, "[%s]", "err %d");
+			break;
+		case 'O':
+			len += sprintf(format+len, "[%s]", "obj %d");
+			break;
+		case 'P':
+			len += sprintf(format+len, "[%s]", "ptr %p");
+			break;
+		case 'V':
+			len += sprintf(format+len, "[%s]", "sym %pS");
+			break;
+		case 'S':
+			len += sprintf(format+len, "[%s]", "str %s");
+			break;
+		case 'T':
+			if (ctx->tsk)
+				len += sprintf(format+len, "[pid %d tsk %s]",
+				      task_pid_vnr(ctx->tsk), ctx->tsk->comm);
+			else
+				len += sprintf(format+len, "[pid -1 tsk NULL]");
+			break;
+		default:
+			printk(KERN_ERR "c/r: bad format specifier %c\n",
+					fmt[2]);
+			BUG();
+		}
+
+		fmt += 3;
+	}
+	format[len] = '\0';
+
+	return format;
+}
 
 /**
  * sys_checkpoint - checkpoint a container
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
index dfcb59b..8a1eaa7 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -70,12 +70,13 @@ extern int ckpt_write_buffer(struct ckpt_ctx *ctx, void *ptr, int len);
 extern int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len);
 
 /*
- * Generate a checkpoint error message with unified format, of the
- * form: "[PREFMT]: @fmt", where PREFMT is constructed from @fmt0. See
- * checkpoint/checkpoint.c:__ckpt_generate_fmt() for details.
+ * Generate a checkpoint error message with unified format.  Format
+ * can include tokens like %(T) for checkpoint-specific arguments,
+ * which must come before non-checkpoint-specific ones.
+ * See checkpoint/checkpoint.c:__ckpt_generate_fmt() for details.
  */
-extern void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...);
-extern int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...);
+extern void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...);
+extern int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...);
 
 extern int _ckpt_read_obj_type(struct ckpt_ctx *ctx,
 			       void *ptr, int len, int type);
@@ -370,6 +371,8 @@ static inline void restore_debug_free(struct ckpt_ctx *ctx) {}
 
 #endif /* CONFIG_CHECKPOINT_DEBUG */
 
+extern char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt);
+
 #endif /* CONFIG_CHECKPOINT */
 #endif /* __KERNEL__ */
 
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/17] ckpt_write_err update arch/x86/mm/checkpoint.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2009-10-29 20:54   ` [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 03/17] ckpt_write_err update checkpoint/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (15 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 arch/x86/mm/checkpoint.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/checkpoint.c b/arch/x86/mm/checkpoint.c
index 9dd8e12..3b0f514 100644
--- a/arch/x86/mm/checkpoint.c
+++ b/arch/x86/mm/checkpoint.c
@@ -116,11 +116,11 @@ static unsigned short decode_segment(__u16 seg)
 static int may_checkpoint_thread(struct ckpt_ctx *ctx, struct task_struct *t)
 {
 	if (t->thread.vm86_info) {
-		ckpt_write_err(ctx, "TE", "task in VM86 mode", -EBUSY);
+		ckpt_write_err(ctx, "%(T)%(E)task in VM86 mode", -EBUSY);
 		return -EBUSY;
 	}
 	if (task_thread_info(t)->flags & CKPT_X86_TIF_UNSUPPORTED) {
-		ckpt_write_err(ctx, "TE", "bad thread info flags %#lx", -EBUSY);
+		ckpt_write_err(ctx, "%(T)%(E)bad thread info flags %#lx", -EBUSY);
 		return -EBUSY;
 	}
 	return 0;
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/17] ckpt_write_err update checkpoint/checkpoint.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2009-10-29 20:54   ` [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 02/17] ckpt_write_err update arch/x86/mm/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 04/17] ckpt_write_err update checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (14 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/checkpoint.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
index c6be4f9..35fce15 100644
--- a/checkpoint/checkpoint.c
+++ b/checkpoint/checkpoint.c
@@ -319,12 +319,12 @@ static int may_checkpoint_task(struct ckpt_ctx *ctx, struct task_struct *t)
 	ckpt_debug("check %d\n", task_pid_nr_ns(t, ctx->root_nsproxy->pid_ns));
 
 	if (t->exit_state == EXIT_DEAD) {
-		__ckpt_write_err(ctx, "TE", "task state EXIT_DEAD\n", -EBUSY);
+		__ckpt_write_err(ctx, "%(T)%(E)task state EXIT_DEAD\n", -EBUSY);
 		return -EBUSY;
 	}
 
 	if (!ptrace_may_access(t, PTRACE_MODE_ATTACH)) {
-		__ckpt_write_err(ctx, "TE", "ptrace attach denied", -EPERM);
+		__ckpt_write_err(ctx, "%(T)%(E)ptrace attach denied", -EPERM);
 		return -EPERM;
 	}
 
@@ -334,13 +334,13 @@ static int may_checkpoint_task(struct ckpt_ctx *ctx, struct task_struct *t)
 
 	/* verify that all tasks belongs to same freezer cgroup */
 	if (t != current && !in_same_cgroup_freezer(t, ctx->root_freezer)) {
-		__ckpt_write_err(ctx, "TE", "unfrozen or wrong cgroup", -EBUSY);
+		__ckpt_write_err(ctx, "%(T)%(E)unfrozen or wrong cgroup", -EBUSY);
 		return -EBUSY;
 	}
 
 	/* FIX: add support for ptraced tasks */
 	if (task_ptrace(t)) {
-		__ckpt_write_err(ctx, "TE", "task is ptraced", -EBUSY);
+		__ckpt_write_err(ctx, "%(T)%(E)task is ptraced", -EBUSY);
 		return -EBUSY;
 	}
 
@@ -350,22 +350,22 @@ static int may_checkpoint_task(struct ckpt_ctx *ctx, struct task_struct *t)
 	 */
 	if (ctx->root_init && t != root &&
 	    t->real_parent == root->real_parent && t->tgid != root->tgid) {
-		__ckpt_write_err(ctx, "TE", "task is sibling of root", -EINVAL);
+		__ckpt_write_err(ctx, "%(T)%(E)task is sibling of root", -EINVAL);
 		return -EINVAL;
 	}
 
 	rcu_read_lock();
 	nsproxy = task_nsproxy(t);
 	if (nsproxy->mnt_ns != ctx->root_nsproxy->mnt_ns) {
-		__ckpt_write_err(ctx, "TE", "bad mnt_ns", -EPERM);
+		__ckpt_write_err(ctx, "%(T)%(E)bad mnt_ns", -EPERM);
 		ret = -EPERM;
 	}
 	if (nsproxy->pid_ns != ctx->root_nsproxy->pid_ns) {
-		__ckpt_write_err(ctx, "TE", "bad pid_ns", -EPERM);
+		__ckpt_write_err(ctx, "%(T)%(E)bad pid_ns", -EPERM);
 		ret = -EPERM;
 	}
 	if (nsproxy->net_ns != ctx->root_nsproxy->net_ns) {
-		__ckpt_write_err(ctx, "TE", "bad net_ns", -EPERM);
+		__ckpt_write_err(ctx, "%(T)%(E)bad net_ns", -EPERM);
 		ret = -EPERM;
 	}
 	rcu_read_unlock();
@@ -435,7 +435,7 @@ static int collect_objects(struct ckpt_ctx *ctx)
 		ret = ckpt_collect_task(ctx, ctx->tasks_arr[n]);
 		if (ret < 0) {
 			ctx->tsk = ctx->tasks_arr[n];
-			ckpt_write_err(ctx, "TE", "collect failed", ret);
+			ckpt_write_err(ctx, "%(T)%(E)collect failed", ret);
 			ctx->tsk = NULL;
 			break;
 		}
@@ -465,7 +465,7 @@ static int __tree_count_tasks(struct task_struct *task, void *data)
 
 	if (ctx->tasks_arr) {
 		if (d->nr == ctx->nr_tasks) {  /* unlikely... try again later */
-			__ckpt_write_err(ctx, "TE", "bad task count\n", -EBUSY);
+			__ckpt_write_err(ctx, "%(T)%(E)bad task count\n", -EBUSY);
 			ret = -EBUSY;
 			goto out;
 		}
@@ -476,7 +476,7 @@ static int __tree_count_tasks(struct task_struct *task, void *data)
 	ret = 1;
  out:
 	if (ret < 0)
-		ckpt_write_err(ctx, "", NULL);
+		ckpt_write_err(ctx, NULL);
 	ctx->tsk = NULL;
 	return ret;
 }
@@ -635,7 +635,7 @@ static int init_checkpoint_ctx(struct ckpt_ctx *ctx, pid_t pid)
 	ctx->root_init = is_container_init(task);
 
 	if (!(ctx->uflags & CHECKPOINT_SUBTREE) && !ctx->root_init) {
-		ckpt_write_err(ctx, "E", "not container init", -EINVAL);
+		ckpt_write_err(ctx, "%(E)not container init", -EINVAL);
 		return -EINVAL;  /* cleanup by ckpt_ctx_free() */
 	}
 
@@ -662,7 +662,7 @@ long do_checkpoint(struct ckpt_ctx *ctx, pid_t pid)
 	if (ctx->root_freezer) {
 		ret = cgroup_freezer_begin_checkpoint(ctx->root_freezer);
 		if (ret < 0) {
-			ckpt_write_err(ctx, "E", "freezer cgroup failed", ret);
+			ckpt_write_err(ctx, "%(E)freezer cgroup failed", ret);
 			return ret;
 		}
 	}
@@ -705,7 +705,7 @@ long do_checkpoint(struct ckpt_ctx *ctx, pid_t pid)
 
 	/* verify that all objects were indeed visited */
 	if (!ckpt_obj_visited(ctx)) {
-		ckpt_write_err(ctx, "E", "leak: unvisited", -EBUSY);
+		ckpt_write_err(ctx, "%(E)leak: unvisited", -EBUSY);
 		ret = -EBUSY;
 		goto out;
 	}
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/17] ckpt_write_err update checkpoint/files.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 03/17] ckpt_write_err update checkpoint/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 05/17] ckpt_write_err update checkpoint/memory.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (13 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/files.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/checkpoint/files.c b/checkpoint/files.c
index 440b7a9..1f2ab07 100644
--- a/checkpoint/files.c
+++ b/checkpoint/files.c
@@ -88,7 +88,7 @@ int checkpoint_fname(struct ckpt_ctx *ctx, struct path *path, struct path *root)
 					  CKPT_HDR_FILE_NAME);
 	} else {
 		ret = PTR_ERR(fname);
-		ckpt_write_err(ctx, "TEP", "obtain filename (file)", ret);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)obtain filename (file)", ret);
 	}
 
 	kfree(buf);
@@ -204,20 +204,21 @@ int checkpoint_file(struct ckpt_ctx *ctx, void *ptr)
 	int ret;
 
 	if (!file->f_op || !file->f_op->checkpoint) {
-		ckpt_write_err(ctx, "TEPS", "f_op lacks checkpoint",
+		ckpt_write_err(ctx, "%(T)%(E)%(P)%(S)f_op lacks checkpoint",
 			       -EBADF, file, file->f_op);
 		ckpt_debug("f_op lacks checkpoint handler: %pS\n", file->f_op);
 		return -EBADF;
 	}
 	if (d_unlinked(file->f_dentry)) {
-		ckpt_write_err(ctx, "TEP", "unlinked file", -EBADF, file);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)unlinked file", -EBADF, file);
 		ckpt_debug("unlinked files are unsupported\n");
 		return -EBADF;
 	}
 
 	ret = file->f_op->checkpoint(ctx, file);
 	if (ret < 0)
-		ckpt_write_err(ctx, "TEP", "file checkpoint failed", ret, file);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)file checkpoint failed", ret,
+			       file);
 	return ret;
 }
 
@@ -257,7 +258,7 @@ static int checkpoint_file_desc(struct ckpt_ctx *ctx,
 	ret = -EBADF;
 	if (!file) {
 		pr_warning("c/r: file descriptor gone?");
-		ckpt_write_err(ctx, "TEP", "file gone? (%d)", ret, file, fd);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)file gone? (%d)", ret, file, fd);
 		goto out;
 	}
 
@@ -360,7 +361,7 @@ int ckpt_collect_file(struct ckpt_ctx *ctx, struct file *file)
 	if (file->f_op->collect)
 		ret = file->f_op->collect(ctx, file);
 	if (ret < 0)
-		ckpt_write_err(ctx, "TEP", "file collect", ret, file);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)file collect", ret, file);
 	return ret;
 }
 
@@ -379,7 +380,7 @@ static int collect_file_desc(struct ckpt_ctx *ctx,
 	rcu_read_unlock();
 
 	if (!file) {
-		ckpt_write_err(ctx, "TE", "file removed", -EBUSY, file);
+		ckpt_write_err(ctx, "%(T)%(E)file removed", -EBUSY, file);
 		return -EBUSY;
 	}
 
@@ -422,7 +423,7 @@ int ckpt_collect_file_table(struct ckpt_ctx *ctx, struct task_struct *t)
 
 	files = get_files_struct(t);
 	if (!files) {
-		ckpt_write_err(ctx, "TE", "files_struct missing", -EBUSY);
+		ckpt_write_err(ctx, "%(T)%(E)files_struct missing", -EBUSY);
 		return -EBUSY;
 	}
 	ret = collect_file_table(ctx, files);
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/17] ckpt_write_err update checkpoint/memory.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 04/17] ckpt_write_err update checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 06/17] ckpt_write_err update checkpoint/objhash.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (12 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/memory.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/checkpoint/memory.c b/checkpoint/memory.c
index 656614c..c94a85e 100644
--- a/checkpoint/memory.c
+++ b/checkpoint/memory.c
@@ -679,7 +679,7 @@ static int checkpoint_vmas(struct ckpt_ctx *ctx, struct mm_struct *mm)
 			 vma->vm_start, vma->vm_end, vma->vm_flags);
 
 		if (vma->vm_flags & CKPT_VMA_NOT_SUPPORTED) {
-			ckpt_write_err(ctx, "TE", "vma: bad flags (%#lx)\n",
+			ckpt_write_err(ctx, "%(T)%(E)vma: bad flags (%#lx)\n",
 				       -ENOSYS, vma->vm_flags);
 			ret = -ENOSYS;
 			break;
@@ -692,7 +692,7 @@ static int checkpoint_vmas(struct ckpt_ctx *ctx, struct mm_struct *mm)
 		else
 			ret = -ENOSYS;
 		if (ret < 0) {
-			ckpt_write_err(ctx, "TE", "vma: failed", ret);
+			ckpt_write_err(ctx, "%(T)%(E)vma: failed", ret);
 			break;
 		}
 		/*
@@ -821,7 +821,7 @@ static int collect_mm(struct ckpt_ctx *ctx, struct mm_struct *mm)
 	if (mm->exe_file) {
 		ret = ckpt_collect_file(ctx, mm->exe_file);
 		if (ret < 0) {
-			ckpt_write_err(ctx, "TE", "mm: collect exe_file", ret);
+			ckpt_write_err(ctx, "%(T)%(E)mm: collect exe_file", ret);
 			goto out;
 		}
 	}
@@ -831,7 +831,7 @@ static int collect_mm(struct ckpt_ctx *ctx, struct mm_struct *mm)
 			continue;
 		ret = ckpt_collect_file(ctx, file);
 		if (ret < 0) {
-			ckpt_write_err(ctx, "TE", "mm: collect vm_file", ret);
+			ckpt_write_err(ctx, "%(T)%(E)mm: collect vm_file", ret);
 			break;
 		}
 	}
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/17] ckpt_write_err update checkpoint/objhash.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 05/17] ckpt_write_err update checkpoint/memory.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 07/17] ckpt_write_err update checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (11 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/objhash.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/checkpoint/objhash.c b/checkpoint/objhash.c
index 730dd82..a152e69 100644
--- a/checkpoint/objhash.c
+++ b/checkpoint/objhash.c
@@ -657,7 +657,7 @@ static inline int obj_reverse_leak(struct ckpt_ctx *ctx, struct ckpt_obj *obj)
 	 * object while we were collecting, which we didn't catch.
 	 */
 	if (obj->ops->ref_users && !(ctx->uflags & CHECKPOINT_SUBTREE)) {
-		ckpt_write_err(ctx, "OP", "leak: reverse added late (%s)",
+		ckpt_write_err(ctx, "%(O)%(P)leak: reverse added late (%s)",
 			       obj->objref, obj->ptr, obj->ops->obj_name);
 		return -EBUSY;
 	}
@@ -774,7 +774,7 @@ int ckpt_obj_visit(struct ckpt_ctx *ctx, void *ptr, enum obj_type type)
 	if (!obj) {
 		if (!(ctx->uflags & CHECKPOINT_SUBTREE)) {
 			/* if not found report reverse leak (full container) */
-			ckpt_write_err(ctx, "OP", "leak: reverse unknown (%s)",
+			ckpt_write_err(ctx, "%(O)%(P)leak: reverse unknown (%s)",
 				       obj->objref, obj->ptr,
 				       obj->ops->obj_name);
 			return -EBUSY;
@@ -870,7 +870,7 @@ int ckpt_obj_contained(struct ckpt_ctx *ctx)
 
 		if (obj->ops->ref_users(obj->ptr) != obj->users) {
 			ckpt_debug("usage leak: %s\n", obj->ops->obj_name);
-			ckpt_write_err(ctx, "OP", "leak: usage (%d != %d (%s)",
+			ckpt_write_err(ctx, "%(O)%(P)leak: usage (%d != %d (%s)",
 				       obj->objref, obj->ptr,
 				       obj->ops->ref_users(obj->ptr),
 				       obj->users, obj->ops->obj_name);
@@ -896,7 +896,7 @@ int ckpt_obj_visited(struct ckpt_ctx *ctx)
 		if (!(obj->flags & CKPT_OBJ_VISITED)) {
 			ckpt_debug("reverse leak: %s (%d)\n",
 				   obj->ops->obj_name, obj->objref);
-			ckpt_write_err(ctx, "OP", "leak: not visited (%s)",
+			ckpt_write_err(ctx, "%(O)%(P)leak: not visited (%s)",
 				       obj->objref, obj->ptr,
 				       obj->ops->obj_name);
 			return 0;
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/17] ckpt_write_err update checkpoint/process.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (5 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 06/17] ckpt_write_err update checkpoint/objhash.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 08/17] ckpt_write_err update checkpoint/signal.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (10 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/process.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/checkpoint/process.c b/checkpoint/process.c
index 8e4a823..e84683f 100644
--- a/checkpoint/process.c
+++ b/checkpoint/process.c
@@ -256,21 +256,21 @@ static int checkpoint_task_objs(struct ckpt_ctx *ctx, struct task_struct *t)
 	files_objref = checkpoint_obj_file_table(ctx, t);
 	ckpt_debug("files: objref %d\n", files_objref);
 	if (files_objref < 0) {
-		ckpt_write_err(ctx, "TE", "files_struct", files_objref);
+		ckpt_write_err(ctx, "%(T)%(E)files_struct", files_objref);
 		return files_objref;
 	}
 
 	mm_objref = checkpoint_obj_mm(ctx, t);
 	ckpt_debug("mm: objref %d\n", mm_objref);
 	if (mm_objref < 0) {
-		ckpt_write_err(ctx, "TE", "mm_struct", mm_objref);
+		ckpt_write_err(ctx, "%(T)%(E)mm_struct", mm_objref);
 		return mm_objref;
 	}
 
 	sighand_objref = checkpoint_obj_sighand(ctx, t);
 	ckpt_debug("sighand: objref %d\n", sighand_objref);
 	if (sighand_objref < 0) {
-		ckpt_write_err(ctx, "TE", "sighand_struct", sighand_objref);
+		ckpt_write_err(ctx, "%(T)%(E)sighand_struct", sighand_objref);
 		return sighand_objref;
 	}
 
@@ -303,7 +303,7 @@ static int checkpoint_task_objs(struct ckpt_ctx *ctx, struct task_struct *t)
 	if (first)
 		ret = checkpoint_obj_signal(ctx, t);
 	if (ret < 0)
-		ckpt_write_err(ctx, "TE", "signal_struct", ret);
+		ckpt_write_err(ctx, "%(T)%(E)signal_struct", ret);
 
 	return ret;
 }
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/17] ckpt_write_err update checkpoint/signal.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (6 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 07/17] ckpt_write_err update checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 09/17] ckpt_write_err update fs/eventpoll.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (9 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/signal.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/checkpoint/signal.c b/checkpoint/signal.c
index cdfb142..3eed685 100644
--- a/checkpoint/signal.c
+++ b/checkpoint/signal.c
@@ -287,7 +287,7 @@ static int checkpoint_sigpending(struct ckpt_ctx *ctx,
 	list_for_each_entry(q, &pending->list, list) {
 		/* TODO: remove after adding support for posix-timers */
 		if ((q->info.si_code & __SI_MASK) == __SI_TIMER) {
-			ckpt_write_err(ctx, "TE", "signal SI_TIMER", -ENOTSUPP);
+			ckpt_write_err(ctx, "%(T)%(E)signal SI_TIMER", -ENOTSUPP);
 			return -ENOTSUPP;
 		}
 		nr_pending++;
@@ -341,7 +341,8 @@ static int checkpoint_signal(struct ckpt_ctx *ctx, struct task_struct *t)
 
 	/* TODO: remove after adding support for posix-timers */
 	if (!list_empty(&signal->posix_timers)) {
-		ckpt_write_err(ctx, "TEP", "posix-timers\n", -ENOTSUPP, signal);
+		ckpt_write_err(ctx, "%(T)%(E)%(P)posix-timers\n", -ENOTSUPP,
+				signal);
 		unlock_task_sighand(t, &flags);
 		ret = -ENOTSUPP;
 		goto out;
@@ -653,7 +654,7 @@ int checkpoint_task_signal(struct ckpt_ctx *ctx, struct task_struct *t)
 
 	/* temporarily borrow signal queue - see chekcpoint_sigpending() */
 	if (!lock_task_sighand(t, &flags)) {
-		ckpt_write_err(ctx, "TE", "signand missing", -EBUSY);
+		ckpt_write_err(ctx, "%(T)%(E)signand missing", -EBUSY);
 		return -EBUSY;
 	}
 	list_splice_init(&t->pending.list, &pending.list);
@@ -664,7 +665,7 @@ int checkpoint_task_signal(struct ckpt_ctx *ctx, struct task_struct *t)
 
 	/* re-attach the borrowed queue */
 	if (!lock_task_sighand(t, &flags)) {
-		ckpt_write_err(ctx, "TE", "signand missing", -EBUSY);
+		ckpt_write_err(ctx, "%(T)%(E)sighand missing", -EBUSY);
 		return -EBUSY;
 	}
 	list_splice(&pending.list, &t->pending.list);
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/17] ckpt_write_err update fs/eventpoll.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (7 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 08/17] ckpt_write_err update checkpoint/signal.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 10/17] define function to print error messages to user log serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (8 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 fs/eventpoll.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index e07de97..f21745b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1549,7 +1549,7 @@ unlock:
 	if (num_items != 0 || (num_items == 0 && rbp))
 		ret = -EBUSY; /* extra item(s) -- checkpoint obj leak */
 	if (ret)
-		ckpt_write_err(ctx, "E", " checkpointing epoll items.\n", ret);
+		ckpt_write_err(ctx, "%(E)checkpointing epoll items.\n", ret);
 	return ret;
 }
 
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/17] define function to print error messages to user log
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (8 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 09/17] ckpt_write_err update fs/eventpoll.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
       [not found]     ` <1256849682-858-11-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2009-10-29 20:54   ` [PATCH 11/17] have restore_debug_free use ckpt_error serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (7 subsequent siblings)
  17 siblings, 1 reply; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Error messages are both sent to an optional user-provided logfile,
and, if CONFIG_CHECKPOINT_DEBUG=y, sent to syslog.

Changelog:
	Oct 29: Split ckpt_log_error() into ckpt_log_error_v() and have
		ckpt_write_err() call it to duplicate the checkpoint
		error message into the optional user-provided log file and
		(if CONFIG_CHECKPOINT_DEBUG=y) syslog as well.
		Define a fn writing an error prefix (containing
		current->pid etc) for ckpt_error().
	Oct 28: Don't use a third va_args, and use smaller on-stack
		buffer (mhelsley comments).  It still might be cleaner
		to always kmalloc, but always using two kmallocs per
		ckpt_error is getting kinda gross...  (open to comments
		on that).
	Oct 26: Per Oren suggestion, return -EBADF for bad
		logfile in ckpt_ctx_alloc().

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/checkpoint.c          |    8 +++-
 checkpoint/objhash.c             |    2 +
 checkpoint/sys.c                 |   91 ++++++++++++++++++++++++++++++++++----
 include/linux/checkpoint.h       |    5 ++
 include/linux/checkpoint_types.h |    5 ++
 include/linux/syscalls.h         |    5 +-
 6 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
index 35fce15..30ec622 100644
--- a/checkpoint/checkpoint.c
+++ b/checkpoint/checkpoint.c
@@ -123,8 +123,6 @@ static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt, va_list ap)
 
 	va_end(aq);
 	kfree(format);
-
-	ckpt_debug("c/r: checkpoint error: %s\n", str);
 }
 
 /**
@@ -140,9 +138,15 @@ void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
 {
 	va_list ap;
 
+	/* write to checkpoint file */
 	va_start(ap, fmt);
 	__ckpt_generate_err(ctx, fmt, ap);
 	va_end(ap);
+
+	/* write to user log and syslog */
+	va_start(ap, fmt);
+	ckpt_log_error_v(ctx, fmt, ap);
+	va_end(ap);
 }
 
 /**
diff --git a/checkpoint/objhash.c b/checkpoint/objhash.c
index a152e69..25b9c10 100644
--- a/checkpoint/objhash.c
+++ b/checkpoint/objhash.c
@@ -858,6 +858,8 @@ int ckpt_obj_contained(struct ckpt_ctx *ctx)
 
 	/* account for ctx->file reference (if in the table already) */
 	ckpt_obj_users_inc(ctx, ctx->file, 1);
+	if (ctx->logfile)
+		ckpt_obj_users_inc(ctx, ctx->logfile, 1);
 	/* account for ctx->root_nsproxy reference (if in the table already) */
 	ckpt_obj_users_inc(ctx, ctx->root_nsproxy, 1);
 
diff --git a/checkpoint/sys.c b/checkpoint/sys.c
index 9b2de18..736606d 100644
--- a/checkpoint/sys.c
+++ b/checkpoint/sys.c
@@ -204,6 +204,8 @@ static void ckpt_ctx_free(struct ckpt_ctx *ctx)
 
 	if (ctx->file)
 		fput(ctx->file);
+	if (ctx->logfile)
+		fput(ctx->logfile);
 
 	ckpt_obj_hash_free(ctx);
 	path_put(&ctx->fs_mnt);
@@ -220,12 +222,13 @@ static void ckpt_ctx_free(struct ckpt_ctx *ctx)
 		put_task_struct(ctx->root_freezer);
 
 	kfree(ctx->pids_arr);
+	kfree(ctx->error_buf);
 
 	kfree(ctx);
 }
 
 static struct ckpt_ctx *ckpt_ctx_alloc(int fd, unsigned long uflags,
-				       unsigned long kflags)
+				       unsigned long kflags, int logfd)
 {
 	struct ckpt_ctx *ctx;
 	int err;
@@ -249,11 +252,23 @@ static struct ckpt_ctx *ckpt_ctx_alloc(int fd, unsigned long uflags,
 	spin_lock_init(&ctx->lock);
 #endif
 
+	err = -ENOMEM;
+	ctx->error_buf = kmalloc(CKPT_ERR_BUFSZ, GFP_KERNEL);
+	if (!ctx->error_buf)
+		goto err;
+	mutex_init(&ctx->error_buf_mutex);
+
 	err = -EBADF;
 	ctx->file = fget(fd);
 	if (!ctx->file)
 		goto err;
 
+	if (logfd != -1) {
+		ctx->logfile = fget(logfd);
+		if (!ctx->logfile)
+			goto err;
+	}
+
 	err = -ENOMEM;
 	if (ckpt_obj_hash_alloc(ctx) < 0)
 		goto err;
@@ -351,8 +366,7 @@ int walk_task_subtree(struct task_struct *root,
  * PREFMT is constructed from @fmt by subtituting format snippets
  * according to the contents of @fmt.  The format characters in
  * @fmt can be %(E) (error), %(O) (objref), %(P) (pointer), %(S) (string),
- * %(C) (bytes read/written out of checkpoint image so far), * and %(V)
- * (variable/symbol). For example, %(E) will generate a "err %d"
+ * and %(V) (variable/symbol). For example, %(E) will generate a "err %d"
  * in PREFMT.
  *
  * If @fmt begins with %(T), PREFMT will begin with "pid %d tsk %s"
@@ -370,8 +384,6 @@ int walk_task_subtree(struct task_struct *root,
  *
  * Here, T is simply passed, E expects an integer (err), O expects an
  * integer (objref), and the last argument matches the format string.
- *
- * XXX Do we want 'T' and 'C' to simply always be prepended?
  */
 char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
 {
@@ -435,6 +447,66 @@ char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
 	return format;
 }
 
+/*
+ * called only by ckpt_log_error_v() to write out a prefix, which
+ * looks like:
+ *	[current->pid]=[task_pid_vnr(current)]:[ctx->total]:[ctx->errno]
+ * the ctx->error_buf_mutex is held by caller, so we are free to
+ * write to ctx->error_buf_mutex.  We also can assume that ctx is valid.
+ * Returns the number of characters written (not including trailing \0).
+ */
+static int ckpt_write_error_prefix(struct ckpt_ctx *ctx)
+{
+	return snprintf(ctx->error_buf, CKPT_ERR_BUFSZ, "[%d]=[%d]:[%lld]:[%d] ",
+			 current->pid, task_pid_vnr(current), ctx->total,
+			 ctx->errno);
+}
+
+void ckpt_log_error_v(struct ckpt_ctx *ctx, char *fmt, va_list ap)
+{
+	mm_segment_t fs;
+	char *format;
+	struct file *file = ctx->logfile;
+	char *bufp;
+	va_list aq;
+	int count, len;
+
+	format = ckpt_generate_fmt(ctx, fmt);
+	mutex_lock(&ctx->error_buf_mutex);
+	bufp = ctx->error_buf;
+	len = ckpt_write_error_prefix(ctx);
+	va_copy(aq, ap);
+	count = vsnprintf(bufp+len, CKPT_ERR_BUFSZ-len, format ? : fmt, aq);
+	va_end(aq);
+	count += len;
+	if (count > CKPT_ERR_BUFSZ) {
+		printk(KERN_WARNING "%s:%s:%d error string too long (%d)\n",
+		       __FILE__, __func__, __LINE__, count);
+		bufp[CKPT_ERR_BUFSZ-1] = '\0';
+	}
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	_ckpt_kwrite(file, bufp, count);
+	set_fs(fs);
+
+	ckpt_debug("%s", bufp);
+	mutex_unlock(&ctx->error_buf_mutex);
+	kfree(format);
+}
+
+void ckpt_log_error(struct ckpt_ctx *ctx, char *fmt, ...)
+{
+	va_list ap;
+
+	if (!ctx || !ctx->logfile)
+		return;
+
+	va_start(ap, fmt);
+	ckpt_log_error_v(ctx, fmt, ap);
+	va_end(ap);
+}
+
 /**
  * sys_checkpoint - checkpoint a container
  * @pid: pid of the container init(1) process
@@ -444,7 +516,8 @@ char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
  * Returns positive identifier on success, 0 when returning from restart
  * or negative value on error
  */
-SYSCALL_DEFINE3(checkpoint, pid_t, pid, int, fd, unsigned long, flags)
+SYSCALL_DEFINE4(checkpoint, pid_t, pid, int, fd, unsigned long, flags,
+		int, logfd)
 {
 	struct ckpt_ctx *ctx;
 	long ret;
@@ -457,7 +530,7 @@ SYSCALL_DEFINE3(checkpoint, pid_t, pid, int, fd, unsigned long, flags)
 
 	if (pid == 0)
 		pid = task_pid_vnr(current);
-	ctx = ckpt_ctx_alloc(fd, flags, CKPT_CTX_CHECKPOINT);
+	ctx = ckpt_ctx_alloc(fd, flags, CKPT_CTX_CHECKPOINT, logfd);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
@@ -479,7 +552,7 @@ SYSCALL_DEFINE3(checkpoint, pid_t, pid, int, fd, unsigned long, flags)
  * Returns negative value on error, or otherwise returns in the realm
  * of the original checkpoint
  */
-SYSCALL_DEFINE3(restart, pid_t, pid, int, fd, unsigned long, flags)
+SYSCALL_DEFINE4(restart, pid_t, pid, int, fd, unsigned long, flags, int, logfd)
 {
 	struct ckpt_ctx *ctx = NULL;
 	long ret;
@@ -492,7 +565,7 @@ SYSCALL_DEFINE3(restart, pid_t, pid, int, fd, unsigned long, flags)
 		return -EPERM;
 
 	if (pid)
-		ctx = ckpt_ctx_alloc(fd, flags, CKPT_CTX_RESTART);
+		ctx = ckpt_ctx_alloc(fd, flags, CKPT_CTX_RESTART, logfd);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
index 8a1eaa7..d3348c5 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -372,6 +372,11 @@ static inline void restore_debug_free(struct ckpt_ctx *ctx) {}
 #endif /* CONFIG_CHECKPOINT_DEBUG */
 
 extern char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt);
+extern void ckpt_log_error_v(struct ckpt_ctx *ctx, char *fmt, va_list ap);
+extern void ckpt_log_error(struct ckpt_ctx *ctx, char *fmt, ...);
+
+#define ckpt_error(ctx, fmt, args...)					\
+	ckpt_log_error(ctx, "%s:%d " fmt, __func__, __LINE__, ## args);
 
 #endif /* CONFIG_CHECKPOINT */
 #endif /* __KERNEL__ */
diff --git a/include/linux/checkpoint_types.h b/include/linux/checkpoint_types.h
index 5cc11d9..57fd524 100644
--- a/include/linux/checkpoint_types.h
+++ b/include/linux/checkpoint_types.h
@@ -48,6 +48,7 @@ struct ckpt_ctx {
 	unsigned long oflags;	/* restart: uflags from checkpoint */
 
 	struct file *file;	/* input/output file */
+	struct file *logfile;	/* debug log file */
 	loff_t total;		/* total read/written */
 
 	atomic_t refcount;
@@ -85,6 +86,10 @@ struct ckpt_ctx {
 	struct list_head task_status;   /* list of status for each task */
 	spinlock_t lock;
 #endif
+
+#define CKPT_ERR_BUFSZ 1024
+	char *error_buf;		/* used by ckpt_error() */
+	struct mutex error_buf_mutex;
 };
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 33bce6e..4fce331 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -754,8 +754,9 @@ asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *,
 asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int,
 			  struct timespec __user *, const sigset_t __user *,
 			  size_t);
-asmlinkage long sys_checkpoint(pid_t pid, int fd, unsigned long flags);
-asmlinkage long sys_restart(pid_t pid, int fd, unsigned long flags);
+asmlinkage long sys_checkpoint(pid_t pid, int fd, unsigned long flags,
+			       int logfd);
+asmlinkage long sys_restart(pid_t pid, int fd, unsigned long flags, int logfd);
 
 int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
 
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/17] have restore_debug_free use ckpt_error
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (9 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 10/17] define function to print error messages to user log serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 12/17] use ckpt_error in checkpoint/restart.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (6 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/restart.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/checkpoint/restart.c b/checkpoint/restart.c
index 9b75de8..3f23397 100644
--- a/checkpoint/restart.c
+++ b/checkpoint/restart.c
@@ -137,15 +137,16 @@ void restore_debug_free(struct ckpt_ctx *ctx)
 	 */
 	list_for_each_entry(s, &ctx->task_status, list)
 		count++;
-	ckpt_debug("%d tasks registered, nr_tasks was %d nr_total %d\n",
+	ckpt_error(ctx, "%d tasks registered, nr_tasks was %d nr_total %d\n",
 		   count, ctx->nr_tasks, atomic_read(&ctx->nr_total));
 
-	ckpt_debug("active pid was %d, ctx->errno %d\n", ctx->active_pid,
+	ckpt_error(ctx, "active pid was %d, ctx->errno %d\n", ctx->active_pid,
 		   ctx->errno);
-	ckpt_debug("kflags %lu uflags %lu oflags %lu", ctx->kflags,
+	ckpt_error(ctx, "kflags %lu uflags %lu oflags %lu", ctx->kflags,
 		   ctx->uflags, ctx->oflags);
 	for (i = 0; i < ctx->active_pid; i++)
-		ckpt_debug("task[%d] to run %d\n", i, ctx->pids_arr[i].vpid);
+		ckpt_error(ctx, "task[%d] to run %d\n", i,
+			   ctx->pids_arr[i].vpid);
 
 	list_for_each_entry_safe(s, p, &ctx->task_status, list) {
 		if (s->flags & RESTART_DBG_COORD)
@@ -170,7 +171,8 @@ void restore_debug_free(struct ckpt_ctx *ctx)
 			state = "Exited";
 		else
 			state = "??????";
-		ckpt_debug("pid %d type %s state %s\n", s->pid, which, state);
+		ckpt_error(ctx, "pid %d type %s state %s\n", s->pid, which,
+			   state);
 		list_del(&s->list);
 		kfree(s);
 	}
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/17] use ckpt_error in checkpoint/restart.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (10 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 11/17] have restore_debug_free use ckpt_error serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 13/17] ckpt_error in checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (5 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

In cases where f(x) always returns 0 or <0, I felt free to
remove ckpt_debugs in favor of ckpt_error() only on error.

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/restart.c |   90 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/checkpoint/restart.c b/checkpoint/restart.c
index 3f23397..6eb5a70 100644
--- a/checkpoint/restart.c
+++ b/checkpoint/restart.c
@@ -64,7 +64,7 @@ static int restore_debug_task(struct ckpt_ctx *ctx, int flags)
 
 	s = kmalloc(sizeof(*s), GFP_KERNEL);
 	if (!s) {
-		ckpt_debug("no memory to register ?!\n");
+		ckpt_error(ctx, "no memory to register ?!\n");
 		return -ENOMEM;
 	}
 	s->pid = current->pid;
@@ -199,13 +199,13 @@ static int _ckpt_read_err(struct ckpt_ctx *ctx, struct ckpt_hdr *h)
 	len = h->len - sizeof(*h);
 	ptr = kzalloc(len + 1, GFP_KERNEL);
 	if (!ptr) {
-		ckpt_debug("insufficient memory to report image error\n");
+		ckpt_error(ctx, "insufficient memory to report image error\n");
 		return -ENOMEM;
 	}
 
 	ret = ckpt_kread(ctx, ptr, len);
 	if (ret >= 0) {
-		ckpt_debug("%s\n", &ptr[1]);
+		ckpt_error(ctx, "%s\n", &ptr[1]);
 		ret = -EIO;
 	}
 
@@ -717,7 +717,7 @@ static void _restore_notify_error(struct ckpt_ctx *ctx, int errno)
 {
 	/* first to fail: notify everyone (racy but harmless) */
 	if (!ckpt_test_ctx_error(ctx)) {
-		ckpt_debug("setting restart error %d\n", errno); \
+		ckpt_error(ctx, "setting restart error %d\n", errno);
 		ckpt_set_ctx_error(ctx, errno);
 		complete(&ctx->complete);
 		wake_up_all(&ctx->waitq);
@@ -731,7 +731,8 @@ static void _restore_notify_error(struct ckpt_ctx *ctx, int errno)
 */
 #define restore_notify_error(ctx, errno) \
 do { \
-	ckpt_debug("restart error %d, root pid %d\n", errno, ctx->root_pid); \
+	ckpt_error(ctx, "restart error %d, root pid %d\n", errno, \
+		   ctx->root_pid); \
 	_restore_notify_error(ctx, errno); \
 } while(0)
 
@@ -755,7 +756,8 @@ static int set_task_ctx(struct task_struct *task, struct ckpt_ctx *ctx)
 		task->checkpoint_ctx = ckpt_ctx_get(ctx);
 		ret = 0;
 	} else {
-		ckpt_debug("task %d has checkpoint_ctx\n", task_pid_vnr(task));
+		ckpt_error(ctx, "task %d has checkpoint_ctx\n",
+			   task_pid_vnr(task));
 		ret = 1;
 	}
 	task_unlock(task);
@@ -805,7 +807,7 @@ static int restore_activate_next(struct ckpt_ctx *ctx)
 		rcu_read_unlock();
 
 		if (!task) {
-			ckpt_debug("could not find task %d\n", pid);
+			ckpt_error(ctx, "could not find task %d\n", pid);
 			restore_notify_error(ctx, -ESRCH);
 			return -ESRCH;
 		}
@@ -960,29 +962,38 @@ static int do_restore_task(void)
 	current->flags |= PF_RESTARTING;
 
 	ret = wait_sync_threads();
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "wait_sync_threads ret %d\n", ret);
 		goto out;
+	}
 
 	/* wait for our turn, do the restore, and tell next task in line */
 	ret = wait_task_active(ctx);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "wait_task_active ret %d\n", ret);
 		goto out;
+	}
 
 	restore_debug_running(ctx);
 
 	ret = pre_restore_task();
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "pre_restore_task ret %d\n", ret);
 		goto out;
+	}
 
 	zombie = restore_task(ctx);
 	if (zombie < 0) {
+		ckpt_error(ctx, "restore_task ret %d\n", ret);
 		ret = zombie;
 		goto out;
 	}
 
 	ret = restore_activate_next(ctx);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore_activate_next ret %d\n", ret);
 		goto out;
+	}
 
 	/*
 	 * zombie: we're done here; do_exit() will notice the @ctx on
@@ -1023,12 +1034,12 @@ static int __prepare_descendants(struct task_struct *task, void *data)
 	ckpt_debug("consider task %d\n", task_pid_vnr(task));
 
 	if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
-		ckpt_debug("stranger task %d\n", task_pid_vnr(task));
+		ckpt_error(ctx, "stranger task %d\n", task_pid_vnr(task));
 		return -EPERM;
 	}
 
 	if (task_ptrace(task) & PT_PTRACED) {
-		ckpt_debug("ptraced task %d\n", task_pid_vnr(task));
+		ckpt_error(ctx, "ptraced task %d\n", task_pid_vnr(task));
 		return -EBUSY;
 	}
 
@@ -1184,24 +1195,31 @@ static int do_restore_coord(struct ckpt_ctx *ctx, pid_t pid)
 	restore_debug_running(ctx);
 
 	ret = restore_read_header(ctx);
-	ckpt_debug("restore header: %d\n", ret);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore header: %d\n", ret);
 		return ret;
+	}
 	ret = restore_container(ctx);
-	ckpt_debug("restore container: %d\n", ret);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore container: %d\n", ret);
 		return ret;
+	}
 	ret = restore_read_tree(ctx);
-	ckpt_debug("restore tree: %d\n", ret);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore tree: %d\n", ret);
 		return ret;
+	}
 
-	if ((ctx->uflags & RESTART_TASKSELF) && ctx->nr_pids != 1)
+	if ((ctx->uflags & RESTART_TASKSELF) && ctx->nr_pids != 1) {
+		ckpt_error(ctx, "self-restart but nr_pids=%d\n", ctx->nr_pids);
 		return -EINVAL;
+	}
 
 	ret = init_restart_ctx(ctx, pid);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "init_restart_ctx returned %d\n", ret);
 		return ret;
+	}
 
 	/*
 	 * Populate own ->checkpoint_ctx: if an ancestor attempts to
@@ -1214,7 +1232,7 @@ static int do_restore_coord(struct ckpt_ctx *ctx, pid_t pid)
 		 * We are a bad-behaving descendant: an ancestor must
 		 * have prepare_descendants() us as part of a restart.
 		 */
-		ckpt_debug("coord already has checkpoint_ctx\n");
+		ckpt_error(ctx, "coord already has checkpoint_ctx\n");
 		return -EBUSY;
 	}
 
@@ -1226,35 +1244,45 @@ static int do_restore_coord(struct ckpt_ctx *ctx, pid_t pid)
 
 	if (ctx->uflags & RESTART_TASKSELF) {
 		ret = pre_restore_task();
-		ckpt_debug("pre restore task: %d\n", ret);
-		if (ret < 0)
+		if (ret < 0) {
+			ckpt_error(ctx, "pre restore task: %d\n", ret);
 			goto out;
+		}
 		ret = restore_task(ctx);
 		ckpt_debug("restore task: %d\n", ret);
-		if (ret < 0)
+		if (ret < 0) {
+			ckpt_error(ctx, "restore task: %d\n", ret);
 			goto out;
+		}
 	} else {
 		/* prepare descendants' t->checkpoint_ctx point to coord */
 		ret = prepare_descendants(ctx, ctx->root_task);
 		ckpt_debug("restore prepare: %d\n", ret);
-		if (ret < 0)
+		if (ret < 0) {
+			ckpt_error(ctx, "restore prepare: %d\n", ret);
 			goto out;
+		}
 		/* wait for all other tasks to complete do_restore_task() */
 		ret = wait_all_tasks_finish(ctx);
 		ckpt_debug("restore finish: %d\n", ret);
-		if (ret < 0)
+		if (ret < 0) {
+			ckpt_error(ctx, "wait_all_tasks_finish: %d\n", ret);
 			goto out;
+		}
 	}
 
 	ret = deferqueue_run(ctx->deferqueue);  /* run deferred work */
 	ckpt_debug("restore deferqueue: %d\n", ret);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore deferqueue: %d\n", ret);
 		goto out;
+	}
 
 	ret = restore_read_tail(ctx);
-	ckpt_debug("restore tail: %d\n", ret);
-	if (ret < 0)
+	if (ret < 0) {
+		ckpt_error(ctx, "restore tail: %d\n", ret);
 		goto out;
+	}
 
 	if (ctx->uflags & RESTART_FROZEN) {
 		ret = cgroup_freezer_make_frozen(ctx->root_task);
@@ -1366,7 +1394,7 @@ long do_restart(struct ckpt_ctx *ctx, pid_t pid, unsigned long flags)
 	if (!ctx || (ctx->uflags & RESTART_TASKSELF)) {
 		if (ret < 0) {
 			/* partial restore is undefined: terminate */
-			ckpt_debug("restart err %ld, exiting\n", ret);
+			ckpt_error(ctx, "restart err %ld, exiting\n", ret);
 			force_sig(SIGKILL, current);
 		} else {
 			ret = restore_retval();
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/17] ckpt_error in checkpoint/files.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (11 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 12/17] use ckpt_error in checkpoint/restart.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 14/17] ckpt_error in checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (4 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Convert two ckpt_debugs to ckpt_errors - however, given that they
are merely doubling information available in ckpt_write_err(), should
they simply be removed?

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/files.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/checkpoint/files.c b/checkpoint/files.c
index 1f2ab07..e67a13f 100644
--- a/checkpoint/files.c
+++ b/checkpoint/files.c
@@ -206,12 +206,14 @@ int checkpoint_file(struct ckpt_ctx *ctx, void *ptr)
 	if (!file->f_op || !file->f_op->checkpoint) {
 		ckpt_write_err(ctx, "%(T)%(E)%(P)%(S)f_op lacks checkpoint",
 			       -EBADF, file, file->f_op);
-		ckpt_debug("f_op lacks checkpoint handler: %pS\n", file->f_op);
+		ckpt_error(ctx, "%(T)f_op lacks checkpoint handler: %pS\n",
+			   file->f_op);
 		return -EBADF;
 	}
 	if (d_unlinked(file->f_dentry)) {
 		ckpt_write_err(ctx, "%(T)%(E)%(P)unlinked file", -EBADF, file);
-		ckpt_debug("unlinked files are unsupported\n");
+		ckpt_error(ctx, "%(T)%(P)unlinked files are unsupported\n",
+			   file);
 		return -EBADF;
 	}
 
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 14/17] ckpt_error in checkpoint/process.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (12 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 13/17] ckpt_error in checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 15/17] ckpt_error in ipc/checkpoint_msg.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (3 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 checkpoint/process.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/checkpoint/process.c b/checkpoint/process.c
index e84683f..9f46769 100644
--- a/checkpoint/process.c
+++ b/checkpoint/process.c
@@ -581,14 +581,14 @@ static int restore_task_creds(struct ckpt_ctx *ctx)
 
 	realcred = ckpt_obj_fetch(ctx, h->cred_ref, CKPT_OBJ_CRED);
 	if (IS_ERR(realcred)) {
-		ckpt_debug("Error %ld fetching realcred (ref %d)\n",
+		ckpt_error(ctx, "%(T)Error %ld fetching realcred (ref %(O))\n",
 			PTR_ERR(realcred), h->cred_ref);
 		ret = PTR_ERR(realcred);
 		goto out;
 	}
 	ecred = ckpt_obj_fetch(ctx, h->ecred_ref, CKPT_OBJ_CRED);
 	if (IS_ERR(ecred)) {
-		ckpt_debug("Error %ld fetching ecred (ref %d)\n",
+		ckpt_error(ctx, "%(T)Error %ld fetching ecred (ref %(O))\n",
 			PTR_ERR(ecred), h->ecred_ref);
 		ret = PTR_ERR(ecred);
 		goto out;
@@ -614,18 +614,18 @@ static int restore_task_objs(struct ckpt_ctx *ctx)
 	 */
 	ret = restore_task_creds(ctx);
 	if (ret < 0) {
-		ckpt_debug("restore_task_creds returned %d\n", ret);
+		ckpt_error(ctx, "%(T)restore_task_creds returned %d\n", ret);
 		return ret;
 	}
 	ret = restore_task_ns(ctx);
 	if (ret < 0) {
-		ckpt_debug("restore_task_ns returned %d\n", ret);
+		ckpt_error(ctx, "%(T)restore_task_ns returned %d\n", ret);
 		return ret;
 	}
 
 	h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_TASK_OBJS);
 	if (IS_ERR(h)) {
-		ckpt_debug("Error fetching task obj\n");
+		ckpt_error(ctx, "%(T)Error %d fetching task obj\n", PTR_ERR(h));
 		return PTR_ERR(h);
 	}
 
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 15/17] ckpt_error in ipc/checkpoint_msg.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (13 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 14/17] ckpt_error in checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 16/17] ckpt_error in ipc/checkpoint_sem.c serue-r/Jw6+rmf7HQT0dZR+AlfA
                     ` (2 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 ipc/checkpoint_msg.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ipc/checkpoint_msg.c b/ipc/checkpoint_msg.c
index b933c19..806fe74 100644
--- a/ipc/checkpoint_msg.c
+++ b/ipc/checkpoint_msg.c
@@ -352,7 +352,7 @@ int restore_ipc_msg(struct ckpt_ctx *ctx, struct ipc_namespace *ns)
 	ret = load_ipc_msg_hdr(ctx, h, msq);
 
 	if (ret < 0) {
-		ckpt_debug("msq: need to remove (%d)\n", ret);
+		ckpt_error(ctx, "%(T)msq: need to remove (%d)\n", ret);
 		freeque(ns, perms);
 	} else
 		ipc_unlock(perms);
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 16/17] ckpt_error in ipc/checkpoint_sem.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (14 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 15/17] ckpt_error in ipc/checkpoint_msg.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 20:54   ` [PATCH 17/17] ckpt_error in ipc/checkpoint_shm.c serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 22:32   ` [PATCH 00/17] Standardize c/r error reporting Oren Laadan
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 ipc/checkpoint_sem.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ipc/checkpoint_sem.c b/ipc/checkpoint_sem.c
index 76eb2b9..0b610ee 100644
--- a/ipc/checkpoint_sem.c
+++ b/ipc/checkpoint_sem.c
@@ -209,7 +209,7 @@ int restore_ipc_sem(struct ckpt_ctx *ctx, struct ipc_namespace *ns)
 
 	ret = load_ipc_sem_hdr(ctx, h, sem);
 	if (ret < 0) {
-		ckpt_debug("sem: need to remove (%d)\n", ret);
+		ckpt_error(ctx, "%(T)sem: need to remove (%d)\n", ret);
 		freeary(ns, perms);
 	} else
 		ipc_unlock(perms);
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 17/17] ckpt_error in ipc/checkpoint_shm.c
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (15 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 16/17] ckpt_error in ipc/checkpoint_sem.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 20:54   ` serue-r/Jw6+rmf7HQT0dZR+AlfA
  2009-10-29 22:32   ` [PATCH 00/17] Standardize c/r error reporting Oren Laadan
  17 siblings, 0 replies; 26+ messages in thread
From: serue-r/Jw6+rmf7HQT0dZR+AlfA @ 2009-10-29 20:54 UTC (permalink / raw)
  To: orenl-RdfvBDnrOixBDgjK7y7TUQ
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 ipc/checkpoint_shm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ipc/checkpoint_shm.c b/ipc/checkpoint_shm.c
index 826e430..eb9dc50 100644
--- a/ipc/checkpoint_shm.c
+++ b/ipc/checkpoint_shm.c
@@ -266,7 +266,7 @@ int restore_ipc_shm(struct ckpt_ctx *ctx, struct ipc_namespace *ns)
  mutex:
 	fput(file);
 	if (ret < 0) {
-		ckpt_debug("shm: need to remove (%d)\n", ret);
+		ckpt_error(ctx, "%(T)shm: need to remove (%d)\n", ret);
 		do_shm_rmid(ns, perms);
 	} else
 		ipc_unlock(perms);
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found]     ` <1256849682-858-2-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-29 22:20       ` Oren Laadan
       [not found]         ` <4AEA1527.7090907-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
  2009-10-30  6:37       ` Sukadev Bhattiprolu
  1 sibling, 1 reply; 26+ messages in thread
From: Oren Laadan @ 2009-10-29 22:20 UTC (permalink / raw)
  To: serue-r/Jw6+rmf7HQT0dZR+AlfA
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA



serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
> From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> 
> Matt Helsley originally suggested this to avoid having two
> format strings.  This is not bisect-safe and therefore not
> even compile-tested.  Every call to ckpt_write_err must be
> updated to use a single format.
> 
> Changelog:
> 	Oct 29: merge with the next patch, moving ckpt_generate_fmt()
> 		into checkpoing/sys.c and making it non-static so that
> 		we can use it in ckpt_error().
> 	Oct 28: also fix comment above ckpt_generate_fmt()
> 	Oct 27: ensure %(T) has a closing paren
> 
> Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> ---
>  checkpoint/checkpoint.c    |  105 +++-----------------------------------------
>  checkpoint/sys.c           |   95 +++++++++++++++++++++++++++++++++++++++
>  include/linux/checkpoint.h |   13 +++--
>  3 files changed, 110 insertions(+), 103 deletions(-)
> 
> diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
> index 6eb8f3b..c6be4f9 100644
> --- a/checkpoint/checkpoint.c
> +++ b/checkpoint/checkpoint.c
> @@ -96,104 +96,15 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len)
>  	return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING);
>  }
>  

[...]

> diff --git a/checkpoint/sys.c b/checkpoint/sys.c
> index 260a1ee..9b2de18 100644
> --- a/checkpoint/sys.c
> +++ b/checkpoint/sys.c
> @@ -339,6 +339,101 @@ int walk_task_subtree(struct task_struct *root,
>  	return (ret < 0 ? ret : total);
>  }
>  

Some pieces of the comment below are obsolete...

> +/*
> + * ckpt_generate_fmt - generate standard checkpoint error message
> + * @ctx: checkpoint context
> + * @fmt: message format
> + *
> + * This generates a unified format of checkpoint error messages, to
> + * ease (after the failure) inspection by userspace tools. It converts
> + * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
> + *
> + * PREFMT is constructed from @fmt by subtituting format snippets
> + * according to the contents of @fmt.  The format characters in
> + * @fmt can be %(E) (error), %(O) (objref), %(P) (pointer), %(S) (string),
> + * %(C) (bytes read/written out of checkpoint image so far), * and %(V)
							      ^^^^^
> + * (variable/symbol). For example, %(E) will generate a "err %d"
> + * in PREFMT.
      ^^^^^^^^^
> + *
> + * If @fmt begins with %(T), PREFMT will begin with "pid %d tsk %s"
	    ^^^^^^^^^
> + * with the pid and the tsk->comm of the currently checkpointed task.
> + * The latter is taken from ctx->tsk, and is it the responsbilility of
						typo  ^^^^^^^^^^^^^^^^^
> + * the caller to have a valid pointer there (in particular, functions
> + * that iterate on the processes: collect_objects, checkpoint_task,
> + * and tree_count_tasks).
> + *
> + * The caller of ckpt_write_err() and _ckpt_write_err() must provide
		    ^^^^^^^^^^^^^^^^	 ^^^^^^^^^^^^^^^^^
> + * the additional variabes, in order, to match the @fmt0 (except for
		typo ^^^^^^^^			     ^^^^^^^
> + * the T key), e.g.:
      ^^^^^^^^^^  (obsolete)
> + *
> + *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags)
			  ^^^^^^^^
> + *
> + * Here, T is simply passed, E expects an integer (err), O expects an
> + * integer (objref), and the last argument matches the format string.

Rewrite example...

> + *
> + * XXX Do we want 'T' and 'C' to simply always be prepended?
> + */
> +char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
> +{
> +	char *format;
> +	int alloclen, len = 0;
> +	int first = 1;
> +
> +	/*
> +	 * 17 for "pid %d" (plus space)
> +	 * 21 for "tsk %s" (tsk->comm)
> +	 * up to 8 per varfmt entry
		      ^^^^^^^^

> +	 */
> +	alloclen = 37 + 8 * strlen(fmt);

This calculation assumed that @fmt had only format string...
At the very minimum you could take strlen(fmt)/3 (+1 to round up)

I thought you were going to use a @ctx->buffer or something ?

> +	format = kzalloc(alloclen, GFP_KERNEL);
> +	if (!format)
> +		return NULL;
> +
> +	for (; *fmt; fmt++) {
> +		BUG_ON(len > alloclen);
> +		if (*fmt != '%' || fmt[1] != '(' || fmt[3] != ')') {

This is still a bit risky .. how about adding
	|| fmt[2] == '\0'
between the 2nd and 3rd test ?

> +			format[len++] = *fmt;
> +			continue;
> +		}
> +		if (!first)
> +			format[len++] = ' ';
> +		else
> +			first = 0;

[...]

Oren.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 00/17] Standardize c/r error reporting
       [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (16 preceding siblings ...)
  2009-10-29 20:54   ` [PATCH 17/17] ckpt_error in ipc/checkpoint_shm.c serue-r/Jw6+rmf7HQT0dZR+AlfA
@ 2009-10-29 22:32   ` Oren Laadan
       [not found]     ` <4AEA17E6.6050609-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
  17 siblings, 1 reply; 26+ messages in thread
From: Oren Laadan @ 2009-10-29 22:32 UTC (permalink / raw)
  To: serue-r/Jw6+rmf7HQT0dZR+AlfA
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA



serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
> From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> 
> This patchset
> 	1. defines ckpt_error() 
> 	2. allows users to pass a logfd into sys_checkpoint and
> 	   sys_restart
> 	3. Switches ckpt_write_err() to accepting a single enhanced
> 	   format string, instead of two separate formats.
> 	4. Has ckpt_write_err() call ckpt_error() to also log the
> 	   error in the user-provided logfile and syslog.
> 
> Every ckpt_error() message is prefixed by current's global pid,
> current's virtual pid, number of bytes read/written, and the
> ctx->errno.

Hmmm... I thought that we'd have:

ckpt_error() will be used _only_ when there is an error.
(will always print ctx->errno, which is assumed to be set)

ckpt_debug() will be used to report "log-able" debugging info
(will not print ctx->errno, because there wasn't any error)

_ckpt_debug() will be used to throw debugging info that isn't
logged (only goes to dmesg) and will not be compiled unless
CONFIG_CHECKPOINT_DEBUG is selected. This is useful for those
debug messages that are a pain to add remove, but that we
don't want to spit to users' logs.

Maybe rename ckpt_debug() to ckpt_log() and then _ckpt_debug()
to ckpt_debug()...

I think it's confusing for ckpt_error() to be used everywhere.

Oren.

> 
> I'm sure we'll want another round if only to alter the format,
> but I'm finding it very useful as is.
> 
> (As more callers are added I expect we'll want to add %(A) to
> the format to indicate active_pid should be printed).
> 
> -serge

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 10/17] define function to print error messages to user log
       [not found]     ` <1256849682-858-11-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-29 22:43       ` Oren Laadan
  0 siblings, 0 replies; 26+ messages in thread
From: Oren Laadan @ 2009-10-29 22:43 UTC (permalink / raw)
  To: serue-r/Jw6+rmf7HQT0dZR+AlfA
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA



serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
> From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> 
> Error messages are both sent to an optional user-provided logfile,
> and, if CONFIG_CHECKPOINT_DEBUG=y, sent to syslog.
> 
> Changelog:
> 	Oct 29: Split ckpt_log_error() into ckpt_log_error_v() and have
> 		ckpt_write_err() call it to duplicate the checkpoint
> 		error message into the optional user-provided log file and
> 		(if CONFIG_CHECKPOINT_DEBUG=y) syslog as well.
> 		Define a fn writing an error prefix (containing
> 		current->pid etc) for ckpt_error().
> 	Oct 28: Don't use a third va_args, and use smaller on-stack
> 		buffer (mhelsley comments).  It still might be cleaner
> 		to always kmalloc, but always using two kmallocs per
> 		ckpt_error is getting kinda gross...  (open to comments
> 		on that).
> 	Oct 26: Per Oren suggestion, return -EBADF for bad
> 		logfile in ckpt_ctx_alloc().
> 
> Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> ---
>  checkpoint/checkpoint.c          |    8 +++-
>  checkpoint/objhash.c             |    2 +
>  checkpoint/sys.c                 |   91 ++++++++++++++++++++++++++++++++++----
>  include/linux/checkpoint.h       |    5 ++
>  include/linux/checkpoint_types.h |    5 ++
>  include/linux/syscalls.h         |    5 +-
>  6 files changed, 103 insertions(+), 13 deletions(-)
> 
> diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
> index 35fce15..30ec622 100644
> --- a/checkpoint/checkpoint.c
> +++ b/checkpoint/checkpoint.c
> @@ -123,8 +123,6 @@ static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt, va_list ap)
>  
>  	va_end(aq);
>  	kfree(format);
> -
> -	ckpt_debug("c/r: checkpoint error: %s\n", str);
>  }
>  
>  /**
> @@ -140,9 +138,15 @@ void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
>  {
>  	va_list ap;
>  
> +	/* write to checkpoint file */
>  	va_start(ap, fmt);
>  	__ckpt_generate_err(ctx, fmt, ap);
>  	va_end(ap);
> +
> +	/* write to user log and syslog */
> +	va_start(ap, fmt);
> +	ckpt_log_error_v(ctx, fmt, ap);
> +	va_end(ap);
>  }

__ckpt_write_err() can be called from spinlock context, so
it needs to remain as is.

Instead, call ckpt_log_error_v() from ckpt_write_err(), and if
the have ckpt_log_error_v() also avoid calling __ckpt_generate_err()
if the @fmt string is NULL, instead take from @ctx->err_string.

To be complete, we probably also need ckpt_log_{un,}lock(), that
are used in ckpt_log_error_v() and should also be used by whoever
uses _ckpt_write_err() directly.

Also, in light of my suggestion in the other email, maybe rename
ckpt_generate_err() to ckpt_generate_msg().

Oren.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 00/17] Standardize c/r error reporting
       [not found]     ` <4AEA17E6.6050609-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
@ 2009-10-30  2:12       ` Serge E. Hallyn
  0 siblings, 0 replies; 26+ messages in thread
From: Serge E. Hallyn @ 2009-10-30  2:12 UTC (permalink / raw)
  To: Oren Laadan; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Quoting Oren Laadan (orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org):
> 
> 
> serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
> > From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> > 
> > This patchset
> > 	1. defines ckpt_error() 
> > 	2. allows users to pass a logfd into sys_checkpoint and
> > 	   sys_restart
> > 	3. Switches ckpt_write_err() to accepting a single enhanced
> > 	   format string, instead of two separate formats.
> > 	4. Has ckpt_write_err() call ckpt_error() to also log the
> > 	   error in the user-provided logfile and syslog.
> > 
> > Every ckpt_error() message is prefixed by current's global pid,
> > current's virtual pid, number of bytes read/written, and the
> > ctx->errno.
> 
> Hmmm... I thought that we'd have:
> 
> ckpt_error() will be used _only_ when there is an error.
> (will always print ctx->errno, which is assumed to be set)
> 
> ckpt_debug() will be used to report "log-able" debugging info
> (will not print ctx->errno, because there wasn't any error)
> 
> _ckpt_debug() will be used to throw debugging info that isn't
> logged (only goes to dmesg) and will not be compiled unless
> CONFIG_CHECKPOINT_DEBUG is selected. This is useful for those
> debug messages that are a pain to add remove, but that we
> don't want to spit to users' logs.
> 
> Maybe rename ckpt_debug() to ckpt_log() and then _ckpt_debug()
> to ckpt_debug()...
> 
> I think it's confusing for ckpt_error() to be used everywhere.

Agreed, and I almost changed it today but didn't.  However note
that ckpt_error really is just for errors.  So I'll just rename
ckpt_log_error()->ckpt_log_msg() (and same with *_v).

-serge

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found]         ` <4AEA1527.7090907-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
@ 2009-10-30  2:18           ` Serge E. Hallyn
       [not found]             ` <20091030021819.GB10379-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Serge E. Hallyn @ 2009-10-30  2:18 UTC (permalink / raw)
  To: Oren Laadan; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Quoting Oren Laadan (orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org):
> 
> 
> serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
> > From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> > 
> > Matt Helsley originally suggested this to avoid having two
> > format strings.  This is not bisect-safe and therefore not
> > even compile-tested.  Every call to ckpt_write_err must be
> > updated to use a single format.
> > 
> > Changelog:
> > 	Oct 29: merge with the next patch, moving ckpt_generate_fmt()
> > 		into checkpoing/sys.c and making it non-static so that
> > 		we can use it in ckpt_error().
> > 	Oct 28: also fix comment above ckpt_generate_fmt()
> > 	Oct 27: ensure %(T) has a closing paren
> > 
> > Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> > ---
> >  checkpoint/checkpoint.c    |  105 +++-----------------------------------------
> >  checkpoint/sys.c           |   95 +++++++++++++++++++++++++++++++++++++++
> >  include/linux/checkpoint.h |   13 +++--
> >  3 files changed, 110 insertions(+), 103 deletions(-)
> > 
> > diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
> > index 6eb8f3b..c6be4f9 100644
> > --- a/checkpoint/checkpoint.c
> > +++ b/checkpoint/checkpoint.c
> > @@ -96,104 +96,15 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len)
> >  	return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING);
> >  }
> >  
> 
> [...]
> 
> > diff --git a/checkpoint/sys.c b/checkpoint/sys.c
> > index 260a1ee..9b2de18 100644
> > --- a/checkpoint/sys.c
> > +++ b/checkpoint/sys.c
> > @@ -339,6 +339,101 @@ int walk_task_subtree(struct task_struct *root,
> >  	return (ret < 0 ? ret : total);
> >  }
> >  
> 
> Some pieces of the comment below are obsolete...
> 
> > +/*
> > + * ckpt_generate_fmt - generate standard checkpoint error message
> > + * @ctx: checkpoint context
> > + * @fmt: message format
> > + *
> > + * This generates a unified format of checkpoint error messages, to
> > + * ease (after the failure) inspection by userspace tools. It converts
> > + * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
> > + *
> > + * PREFMT is constructed from @fmt by subtituting format snippets
> > + * according to the contents of @fmt.  The format characters in
> > + * @fmt can be %(E) (error), %(O) (objref), %(P) (pointer), %(S) (string),
> > + * %(C) (bytes read/written out of checkpoint image so far), * and %(V)
> 							      ^^^^^
> > + * (variable/symbol). For example, %(E) will generate a "err %d"
> > + * in PREFMT.
>       ^^^^^^^^^
> > + *
> > + * If @fmt begins with %(T), PREFMT will begin with "pid %d tsk %s"
> 	    ^^^^^^^^^
> > + * with the pid and the tsk->comm of the currently checkpointed task.
> > + * The latter is taken from ctx->tsk, and is it the responsbilility of
> 						typo  ^^^^^^^^^^^^^^^^^
> > + * the caller to have a valid pointer there (in particular, functions
> > + * that iterate on the processes: collect_objects, checkpoint_task,
> > + * and tree_count_tasks).
> > + *
> > + * The caller of ckpt_write_err() and _ckpt_write_err() must provide
> 		    ^^^^^^^^^^^^^^^^	 ^^^^^^^^^^^^^^^^^
> > + * the additional variabes, in order, to match the @fmt0 (except for
> 		typo ^^^^^^^^			     ^^^^^^^
> > + * the T key), e.g.:
>       ^^^^^^^^^^  (obsolete)
> > + *
> > + *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags)
> 			  ^^^^^^^^
> > + *
> > + * Here, T is simply passed, E expects an integer (err), O expects an
> > + * integer (objref), and the last argument matches the format string.
> 
> Rewrite example...

Ok, thanks for pointing that out - I'll rewrite the whole thing.

> > + * XXX Do we want 'T' and 'C' to simply always be prepended?
> > + */
> > +char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
> > +{
> > +	char *format;
> > +	int alloclen, len = 0;
> > +	int first = 1;
> > +
> > +	/*
> > +	 * 17 for "pid %d" (plus space)
> > +	 * 21 for "tsk %s" (tsk->comm)
> > +	 * up to 8 per varfmt entry
> 		      ^^^^^^^^
> 
> > +	 */
> > +	alloclen = 37 + 8 * strlen(fmt);
> 
> This calculation assumed that @fmt had only format string...
> At the very minimum you could take strlen(fmt)/3 (+1 to round up)

Yeah, I didn't want to think about that in detail yet :)

> I thought you were going to use a @ctx->buffer or something ?

And I am, for my string.  We need one for the expanded fmt here,
and then one to snprintf the final string into so we can write it
out.

Shall I just add a @ctx->fmtbuf?

> > +	format = kzalloc(alloclen, GFP_KERNEL);
> > +	if (!format)
> > +		return NULL;
> > +
> > +	for (; *fmt; fmt++) {
> > +		BUG_ON(len > alloclen);
> > +		if (*fmt != '%' || fmt[1] != '(' || fmt[3] != ')') {
> 
> This is still a bit risky .. how about adding
> 	|| fmt[2] == '\0'
> between the 2nd and 3rd test ?

Well I can do that, but since we provide the fmt strings and there is
no risk for an information leak I didn't think it was worth making
the line even longer.  But ok, I'll add it...

thanks,
-serge

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found]     ` <1256849682-858-2-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2009-10-29 22:20       ` Oren Laadan
@ 2009-10-30  6:37       ` Sukadev Bhattiprolu
       [not found]         ` <20091030063712.GA409-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  1 sibling, 1 reply; 26+ messages in thread
From: Sukadev Bhattiprolu @ 2009-10-30  6:37 UTC (permalink / raw)
  To: serue-r/Jw6+rmf7HQT0dZR+AlfA
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org [serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org] wrote:
| From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
| 
| Matt Helsley originally suggested this to avoid having two
| format strings.  This is not bisect-safe and therefore not
| even compile-tested.  Every call to ckpt_write_err must be
| updated to use a single format.

It maybe easier to review this patch if this is broken up into smaller
patches:

	- move the code to new place
	- leave the fmt0 parameter to ckpt_generate_fmt() but ensure it
	  is unused.
	- finally remove the unused parameters from ckpt_generate_fmt()
	  and the callers. 

| 
| Changelog:
| 	Oct 29: merge with the next patch, moving ckpt_generate_fmt()
| 		into checkpoing/sys.c and making it non-static so that
| 		we can use it in ckpt_error().
| 	Oct 28: also fix comment above ckpt_generate_fmt()
| 	Oct 27: ensure %(T) has a closing paren
| 
| Signed-off-by: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
| ---
|  checkpoint/checkpoint.c    |  105 +++-----------------------------------------
|  checkpoint/sys.c           |   95 +++++++++++++++++++++++++++++++++++++++
|  include/linux/checkpoint.h |   13 +++--
|  3 files changed, 110 insertions(+), 103 deletions(-)
| 
| diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
| index 6eb8f3b..c6be4f9 100644
| --- a/checkpoint/checkpoint.c
| +++ b/checkpoint/checkpoint.c
| @@ -96,104 +96,15 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len)
|  	return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING);
|  }
| 
| -/*
| - * __ckpt_generate_fmt - generate standard checkpoint error message
| - * @ctx: checkpoint context
| - * @fmt0: c/r-format string
| - * @fmt: message format
| - *
| - * This generates a unified format of checkpoint error messages, to
| - * ease (after the failure) inspection by userspace tools. It converts
| - * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
| - *
| - * PREFMT is constructed from @fmt0 by subtituting format snippets
| - * according to the contents of @fmt0.

| - * The format characters in
| - * @fmt0 can be E (error), O (objref), P (pointer), S (string) and
| - * V (variable/symbol). For example, E will generate a "err %d" in
| - * PREFMT (see prefmt_array below).
| - *
| - * If @fmt0 begins with T, PREFMT will begin with "pid %d tsk %s"
| - * with the pid and the tsk->comm of the currently checkpointed task.
| - * The latter is taken from ctx->tsk, and is it the responsbilility of
| - * the caller to have a valid pointer there (in particular, functions
| - * that iterate on the processes: collect_objects, checkpoint_task,
| - * and tree_count_tasks).
| - *
| - * The caller of ckpt_write_err() and _ckpt_write_err() must provide
| - * the additional variabes, in order, to match the @fmt0 (except for
| - * the T key), e.g.:
| - *
| - *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags);
| - *
| - * Here, T is simply passed, E expects an integer (err), O expects an
| - * integer (objref), and the last argument matches the format string.
| - */
| -static char *__ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt0, char *fmt)
| -{
| -	static int warn_notask = 0;
| -	static int warn_prefmt = 0;
| -	char *format;
| -	int i, j, len = 0;
| -
| -	static struct {
| -		char key;
| -		char *fmt;
| -	} prefmt_array[] = {
| -		{ 'E', "err %d" },
| -		{ 'O', "obj %d" },
| -		{ 'P', "ptr %p" },
| -		{ 'V', "sym %pS" },
| -		{ 'S', "str %s" },
| -		{ 0, "??? %pS" },
| -	};
| -
| -	/*
| -	 * 17 for "pid %d" (plus space)
| -	 * 21 for "tsk %s" (tsk->comm)
| -	 * up to 8 per varfmt entry
| -	 */
| -	format = kzalloc(37 + 8 * strlen(fmt0) + strlen(fmt), GFP_KERNEL);
| -	if (!format)
| -		return NULL;
| -
| -	format[len++] = '[';
| -
| -	if (fmt0[0] == 'T') {
| -		if (ctx->tsk)
| -			len = sprintf(format, "pid %d tsk %s ",
| -				      task_pid_vnr(ctx->tsk), ctx->tsk->comm);
| -		else if (warn_notask++ < 5)
| -			printk(KERN_ERR "c/r: no target task set\n");
| -		fmt0++;
| -	}
| -
| -	for (i = 0; i < strlen(fmt0); i++) {
| -		for (j = 0; prefmt_array[j].key; j++)
| -			if (prefmt_array[j].key == fmt0[i])
| -				break;
| -		if (!prefmt_array[j].key && warn_prefmt++ < 5)
| -			printk(KERN_ERR "c/r: unknown prefmt %c\n", fmt0[i]);
| -		len += sprintf(&format[len], "%s ", prefmt_array[j].fmt);
| -	}
| -
| -	if (len > 1)
| -		sprintf(&format[len-1], "]: %s", fmt);  /* erase last space */
| -	else
| -		sprintf(format, "%s", fmt);
| -
| -	return format;
| -}
| -
| -/* see _ckpt_generate_fmt for information on @fmt0 */
| -static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt0,
| -				char *fmt, va_list ap)
| +/* see ckpt_generate_fmt for information on @fmt extensions */
| +static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt, va_list ap)
|  {
|  	va_list aq;
|  	char *format;
|  	char *str;
|  	int len;
| 
| -	format = __ckpt_generate_fmt(ctx, fmt0, fmt);
| +	format = ckpt_generate_fmt(ctx, fmt);
|  	va_copy(aq, ap);
| 
|  	/*
| @@ -223,15 +134,14 @@ static void __ckpt_generate_err(struct ckpt_ctx *ctx, char *fmt0,
|   * @fmt: message format
|   * @...: arguments
|   *
| - * See _ckpt_generate_fmt for information on @fmt0.
|   * Use this during checkpoint to report while holding a spinlock
|   */
| -void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
| +void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
|  {
|  	va_list ap;
| 
|  	va_start(ap, fmt);
| -	__ckpt_generate_err(ctx, fmt0, fmt, ap);
| +	__ckpt_generate_err(ctx, fmt, ap);
|  	va_end(ap);
|  }
| 
| @@ -242,10 +152,9 @@ void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
|   * @fmt: error string format
|   * @...: error string arguments
|   *
| - * See _ckpt_generate_fmt for information on @fmt0.
|   * If @fmt is null, the string in the ctx->err_string will be used (and freed)
|   */
| -int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
| +int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...)
|  {
|  	va_list ap;
|  	char *str;
| @@ -253,7 +162,7 @@ int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...)
| 
|  	if (fmt) {
|  		va_start(ap, fmt);
| -		__ckpt_generate_err(ctx, fmt0, fmt, ap);
| +		__ckpt_generate_err(ctx,  fmt, ap);
|  		va_end(ap);
|  	}
| 
| diff --git a/checkpoint/sys.c b/checkpoint/sys.c
| index 260a1ee..9b2de18 100644
| --- a/checkpoint/sys.c
| +++ b/checkpoint/sys.c
| @@ -339,6 +339,101 @@ int walk_task_subtree(struct task_struct *root,
|  	return (ret < 0 ? ret : total);
|  }
| 
| +/*
| + * ckpt_generate_fmt - generate standard checkpoint error message
| + * @ctx: checkpoint context
| + * @fmt: message format
| + *
| + * This generates a unified format of checkpoint error messages, to
| + * ease (after the failure) inspection by userspace tools. It converts
| + * the (printf) message @fmt into a new format: "[PREFMT]: fmt".
| + *
| + * PREFMT is constructed from @fmt by subtituting format snippets
| + * according to the contents of @fmt.  The format characters in
| + * @fmt can be %(E) (error), %(O) (objref), %(P) (pointer), %(S) (string),
| + * %(C) (bytes read/written out of checkpoint image so far), * and %(V)
| + * (variable/symbol). For example, %(E) will generate a "err %d"
| + * in PREFMT.

Its a little confusing on what PREFMT is and how it differs from @fmt0.
The [] with all upper case makes it look like the P, R, E etc are the
only valid characters for fmt0. Can we s/[PREFMT]/prefmt/ ?

| + *
| + * If @fmt begins with %(T), PREFMT will begin with "pid %d tsk %s"
| + * with the pid and the tsk->comm of the currently checkpointed task.
| + * The latter is taken from ctx->tsk, and is it the responsbilility of
| + * the caller to have a valid pointer there (in particular, functions
| + * that iterate on the processes: collect_objects, checkpoint_task,
| + * and tree_count_tasks).
| + *
| + * The caller of ckpt_write_err() and _ckpt_write_err() must provide
| + * the additional variabes, in order, to match the @fmt0 (except for
| + * the T key), e.g.:
| + *
| + *   ckpt_writ_err(ctx, "TEO", "FILE flags %d", err, objref, flags);

s/writ/write/

| + *
| + * Here, T is simply passed, E expects an integer (err), O expects an
| + * integer (objref), and the last argument matches the format string.
| + *
| + * XXX Do we want 'T' and 'C' to simply always be prepended?

I think it would make sense to.

| + */
| +char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt)
| +{
| +	char *format;
| +	int alloclen, len = 0;
| +	int first = 1;
| +
| +	/*
| +	 * 17 for "pid %d" (plus space)
| +	 * 21 for "tsk %s" (tsk->comm)
| +	 * up to 8 per varfmt entry
| +	 */
| +	alloclen = 37 + 8 * strlen(fmt);
| +	format = kzalloc(alloclen, GFP_KERNEL);
| +	if (!format)
| +		return NULL;
| +
| +	for (; *fmt; fmt++) {
| +		BUG_ON(len > alloclen);
| +		if (*fmt != '%' || fmt[1] != '(' || fmt[3] != ')') {
| +			format[len++] = *fmt;
| +			continue;
| +		}
| +		if (!first)
| +			format[len++] = ' ';
| +		else
| +			first = 0;
| +		switch (fmt[2]) {
| +		case 'E':
| +			len += sprintf(format+len, "[%s]", "err %d");
| +			break;
| +		case 'O':
| +			len += sprintf(format+len, "[%s]", "obj %d");
| +			break;
| +		case 'P':
| +			len += sprintf(format+len, "[%s]", "ptr %p");
| +			break;
| +		case 'V':
| +			len += sprintf(format+len, "[%s]", "sym %pS");
| +			break;
| +		case 'S':
| +			len += sprintf(format+len, "[%s]", "str %s");
| +			break;
| +		case 'T':
| +			if (ctx->tsk)
| +				len += sprintf(format+len, "[pid %d tsk %s]",
| +				      task_pid_vnr(ctx->tsk), ctx->tsk->comm);
| +			else
| +				len += sprintf(format+len, "[pid -1 tsk NULL]");
| +			break;
| +		default:
| +			printk(KERN_ERR "c/r: bad format specifier %c\n",
| +					fmt[2]);
| +			BUG();
| +		}
| +
| +		fmt += 3;
| +	}
| +	format[len] = '\0';
| +
| +	return format;
| +}
| 
|  /**
|   * sys_checkpoint - checkpoint a container
| diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
| index dfcb59b..8a1eaa7 100644
| --- a/include/linux/checkpoint.h
| +++ b/include/linux/checkpoint.h
| @@ -70,12 +70,13 @@ extern int ckpt_write_buffer(struct ckpt_ctx *ctx, void *ptr, int len);
|  extern int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len);
| 
|  /*
| - * Generate a checkpoint error message with unified format, of the
| - * form: "[PREFMT]: @fmt", where PREFMT is constructed from @fmt0. See
| - * checkpoint/checkpoint.c:__ckpt_generate_fmt() for details.
| + * Generate a checkpoint error message with unified format.  Format
| + * can include tokens like %(T) for checkpoint-specific arguments,
| + * which must come before non-checkpoint-specific ones.
| + * See checkpoint/checkpoint.c:__ckpt_generate_fmt() for details.
|   */
| -extern void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...);
| -extern int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt0, char *fmt, ...);
| +extern void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...);
| +extern int ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...);
| 
|  extern int _ckpt_read_obj_type(struct ckpt_ctx *ctx,
|  			       void *ptr, int len, int type);
| @@ -370,6 +371,8 @@ static inline void restore_debug_free(struct ckpt_ctx *ctx) {}
| 
|  #endif /* CONFIG_CHECKPOINT_DEBUG */
| 
| +extern char *ckpt_generate_fmt(struct ckpt_ctx *ctx, char *fmt);
| +
|  #endif /* CONFIG_CHECKPOINT */
|  #endif /* __KERNEL__ */
| 
| -- 
| 1.6.1
| 
| _______________________________________________
| Containers mailing list
| Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
| https://lists.linux-foundation.org/mailman/listinfo/containers

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found]         ` <20091030063712.GA409-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-30 13:33           ` Serge E. Hallyn
  0 siblings, 0 replies; 26+ messages in thread
From: Serge E. Hallyn @ 2009-10-30 13:33 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA

Quoting Sukadev Bhattiprolu (sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org):
> serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org [serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org] wrote:
> | From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> | 
> | Matt Helsley originally suggested this to avoid having two
> | format strings.  This is not bisect-safe and therefore not
> | even compile-tested.  Every call to ckpt_write_err must be
> | updated to use a single format.
> 
> It maybe easier to review this patch if this is broken up into smaller
> patches:
> 
> 	- move the code to new place
> 	- leave the fmt0 parameter to ckpt_generate_fmt() but ensure it
> 	  is unused.
> 	- finally remove the unused parameters from ckpt_generate_fmt()
> 	  and the callers. 

That's going a bit far...  I did leave the moving of the code in a separate
patch up until this last posting, but the new and old versions of
ckpt_generate_fmt() don't look alike enough to be able to compare side by
side anyway imo.

One thing which would help however imo would be if I keep a non-rebased
tagged tree alongside the rebased tree, so you can see what changes I'm
making over the last posting.  I'll do that as of today.

-serge

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens
       [not found]             ` <20091030021819.GB10379-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-30 15:45               ` Oren Laadan
  0 siblings, 0 replies; 26+ messages in thread
From: Oren Laadan @ 2009-10-30 15:45 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA



Serge E. Hallyn wrote:
> Quoting Oren Laadan (orenl-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org):
>>
>> serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org wrote:
>>> From: Serge E. Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

[...]
>>> +	 */
>>> +	alloclen = 37 + 8 * strlen(fmt);
>> This calculation assumed that @fmt had only format string...
>> At the very minimum you could take strlen(fmt)/3 (+1 to round up)
> 
> Yeah, I didn't want to think about that in detail yet :)
> 
>> I thought you were going to use a @ctx->buffer or something ?
> 
> And I am, for my string.  We need one for the expanded fmt here,
> and then one to snprintf the final string into so we can write it
> out.
> 
> Shall I just add a @ctx->fmtbuf?

Sure.

> 
>>> +	format = kzalloc(alloclen, GFP_KERNEL);
>>> +	if (!format)
>>> +		return NULL;
>>> +
>>> +	for (; *fmt; fmt++) {
>>> +		BUG_ON(len > alloclen);
>>> +		if (*fmt != '%' || fmt[1] != '(' || fmt[3] != ')') {
>> This is still a bit risky .. how about adding
>> 	|| fmt[2] == '\0'
>> between the 2nd and 3rd test ?
> 
> Well I can do that, but since we provide the fmt strings and there is
> no risk for an information leak I didn't think it was worth making
> the line even longer.  But ok, I'll add it...

Well, if a developer gives a string like "hello %(", then you
will potentially go past the end of the string and eventually
crash (or worse).

Oren.

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-10-30 15:45 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-29 20:54 [PATCH 00/17] Standardize c/r error reporting serue-r/Jw6+rmf7HQT0dZR+AlfA
     [not found] ` <1256849682-858-1-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-29 20:54   ` [PATCH 01/17] ckpt_write_err: use single format with %(T) style tokens serue-r/Jw6+rmf7HQT0dZR+AlfA
     [not found]     ` <1256849682-858-2-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-29 22:20       ` Oren Laadan
     [not found]         ` <4AEA1527.7090907-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
2009-10-30  2:18           ` Serge E. Hallyn
     [not found]             ` <20091030021819.GB10379-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-30 15:45               ` Oren Laadan
2009-10-30  6:37       ` Sukadev Bhattiprolu
     [not found]         ` <20091030063712.GA409-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-30 13:33           ` Serge E. Hallyn
2009-10-29 20:54   ` [PATCH 02/17] ckpt_write_err update arch/x86/mm/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 03/17] ckpt_write_err update checkpoint/checkpoint.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 04/17] ckpt_write_err update checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 05/17] ckpt_write_err update checkpoint/memory.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 06/17] ckpt_write_err update checkpoint/objhash.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 07/17] ckpt_write_err update checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 08/17] ckpt_write_err update checkpoint/signal.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 09/17] ckpt_write_err update fs/eventpoll.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 10/17] define function to print error messages to user log serue-r/Jw6+rmf7HQT0dZR+AlfA
     [not found]     ` <1256849682-858-11-git-send-email-serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-29 22:43       ` Oren Laadan
2009-10-29 20:54   ` [PATCH 11/17] have restore_debug_free use ckpt_error serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 12/17] use ckpt_error in checkpoint/restart.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 13/17] ckpt_error in checkpoint/files.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 14/17] ckpt_error in checkpoint/process.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 15/17] ckpt_error in ipc/checkpoint_msg.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 16/17] ckpt_error in ipc/checkpoint_sem.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 20:54   ` [PATCH 17/17] ckpt_error in ipc/checkpoint_shm.c serue-r/Jw6+rmf7HQT0dZR+AlfA
2009-10-29 22:32   ` [PATCH 00/17] Standardize c/r error reporting Oren Laadan
     [not found]     ` <4AEA17E6.6050609-RdfvBDnrOixBDgjK7y7TUQ@public.gmane.org>
2009-10-30  2:12       ` Serge E. Hallyn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.