From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752357AbcF1Pej (ORCPT ); Tue, 28 Jun 2016 11:34:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49873 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752071AbcF1Pei (ORCPT ); Tue, 28 Jun 2016 11:34:38 -0400 From: Jiri Olsa To: Lai Jiangshan Cc: Steven Rostedt , lkml , Rasmus Villemoes , Frederic Weisbecker Subject: [RFC/PATCH] lib/vsprintf: Add support to store cpumask Date: Tue, 28 Jun 2016 17:34:34 +0200 Message-Id: <1467128075-10841-1-git-send-email-jolsa@kernel.org> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 28 Jun 2016 15:34:37 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When using trace_printk for cpumask I've got wrong results, some bitmaps were completely different from what I expected. Currently you get wrong results when using trace_printk on local cpumask, like: void test(void) { struct cpumask mask; ... trace_printk("mask '%*pbl'\n", cpumask_pr_args(&mask)); } The reason is that trace_printk stores the data into binary buffer (pointer for cpumask), which is read after via read handler of trace/trace_pipe files. At that time pointer for local cpumask is no longer valid and you get wrong data. Fixing this by storing complete cpumask into tracing buffer. Cc: Steven Rostedt Signed-off-by: Jiri Olsa --- lib/vsprintf.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 0967771d8f7f..f21d68e1b5fc 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -388,7 +388,8 @@ enum format_type { struct printf_spec { unsigned int type:8; /* format_type enum */ signed int field_width:24; /* width of output field */ - unsigned int flags:8; /* flags to number() */ + unsigned int flags:7; /* flags to number() */ + unsigned int cpumask:1; /* pointer to cpumask flag */ unsigned int base:8; /* number base, 8, 10 or 16 only */ signed int precision:16; /* # of digits/chars */ } __packed; @@ -1864,6 +1865,7 @@ qualifier: case 'p': spec->type = FORMAT_TYPE_PTR; + spec->cpumask = fmt[1] == 'b'; return ++fmt - start; case '%': @@ -2338,7 +2340,23 @@ do { \ } case FORMAT_TYPE_PTR: - save_arg(void *); + if (spec.cpumask) { + /* + * Store entire cpumask directly to buffer + * instead of storing just a pointer. + */ + struct cpumask *mask = va_arg(args, void *); + + str = PTR_ALIGN(str, sizeof(u32)); + + if (str + sizeof(*mask) <= end) + cpumask_copy((struct cpumask *) str, mask); + + str += sizeof(*mask); + } else { + save_arg(void *); + } + /* skip all alphanumeric pointer suffixes */ while (isalnum(*fmt)) fmt++; @@ -2490,12 +2508,25 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) break; } - case FORMAT_TYPE_PTR: - str = pointer(fmt, str, end, get_arg(void *), spec); + case FORMAT_TYPE_PTR: { + void *ptr; + + if (spec.cpumask) { + /* + * Load cpumask directly from buffer. + */ + args = PTR_ALIGN(args, sizeof(u32)); + ptr = (void *) args; + args += sizeof(struct cpumask); + } else { + ptr = get_arg(void *); + } + + str = pointer(fmt, str, end, ptr, spec); while (isalnum(*fmt)) fmt++; break; - + } case FORMAT_TYPE_PERCENT_CHAR: if (str < end) *str = '%'; -- 2.4.11