From: Serge E. Hallyn <serue@xxxxxxxxxx> Signed-off-by: Serge E. Hallyn <serue@xxxxxxxxxx> --- checkpoint/checkpoint.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c index 71340de..f057c7a 100644 --- a/checkpoint/checkpoint.c +++ b/checkpoint/checkpoint.c @@ -96,6 +96,13 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, int len) return ckpt_write_obj_type(ctx, str, len, CKPT_HDR_STRING); } +/* + * ckpt_fill_err_string() can be called under spinlock and therefore + * must not sleep. So we protect ctx->err_string and ->err_string_len + * with ctx->err_string_lock which is a spinlock. + * We must also take the ctx->fmt_buf_lock (also a spin_lock) for the + * whole time that we are writing to and reading from ctx->fmt_buf. + */ static void ckpt_fill_err_string(struct ckpt_ctx *ctx, char *fmt, va_list ap) { va_list aq; @@ -166,6 +173,20 @@ void __ckpt_write_err(struct ckpt_ctx *ctx, char *fmt, ...) * @fmt: error string format * @...: error string arguments * + * Here is the locking rationale: + * __ckpt_write_err() (which can be called from spinlock context) + * writes to ctx->err_string under ctx->err_string_lock. + * + * ckpt_write_err() in turn copies ctx->err_string to ctx->msg_buf + * under both ctx->msg_buf_mutex and ctx->err_string_lock, and clears + * out ctx->err_sring (so theoretically it can be written to again). + * It then drops ctx->err_string_lock (which is a spinlock) and keeps + * the ctx->msg_buf_mutex. + * + * It then can leisurely write out msg_buf under mutex ( by calling + * ckpt_do_write_msg() ), while another task could be writing new + * messages to ctx->err_string. + * * 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 *fmt, ...) -- 1.6.1 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers