2014-12-10 15:53:10

by Tejun Heo

[permalink] [raw]
Subject: [PATCHSET -mm] bitmap, cpumask, nodemask: implement pr_cont functions and use di"

Hello,

bitmap implements two variants of scnprintf functions to format a
bitmap into a string and cpumask and nodemask wrap them to provide
equivalent interfaces. The scnprintf family of functions require a
string buffer as an output target which complicates code paths which
just want to print out the mask through printk for informational or
debug purposes as they have to worry about how large the buffer should
be and whether it's too large to allocate on stack.

Neither cpumask or nodemask provides a guildeline on how large the
target buffer should be forcing users come up with their own solutions
- some allocate an arbitrarily sized buffer which is small enough to
allocate on stack but may be too short in corner cases, other come up
with a custom upper limit calculation considering the output format,
some allocate the buffer dynamically while one resorted to using lock
to synchronize access to a static buffer.

This is an artificial problem which is being solved repeatedly for no
benefit. In a lot of cases, the output area already exists and can be
targeted directly making the intermediate buffer unnecessary. This
patchset implement pr_cont variants of the formatting functions and
convert the scnprintf output function users to use them or seq_*()
functions to directly target the output area and remove the
intermediate buffers where possible.

This patchset contains the following 12 patches.

0001-bitmap-restructure-bitmap_sn-list-printf.patch
0002-bitmap-cpumask-nodemask-implement-pr_cont-variants-o.patch
0003-mips-use-cpu-node-mask-pr_cont-and-seq-output-functi.patch
0004-powerpc-use-cpu-node-mask-pr_cont-and-seq-output-fun.patch
0005-tile-use-cpu-node-mask-pr_cont-and-seq-output-functi.patch
0006-x86-use-cpu-node-mask-pr_cont-and-seq-output-functio.patch
0007-xtensa-use-cpu-node-mask-pr_cont-and-seq-output-func.patch
0008-cpuset-use-cpu-node-mask-pr_cont-and-seq-output-func.patch
0009-rcu-use-cpu-node-mask-pr_cont-and-seq-output-functio.patch
0010-sched-use-cpu-node-mask-pr_cont-and-seq-output-funct.patch
0011-timer-use-cpu-node-mask-pr_cont-and-seq-output-funct.patch
0012-percpu-use-cpu-node-mask-pr_cont-and-seq-output-func.patch

The first two patches implement the pr_cont variants of the formatting
functions. The rest convert the existing users to pr_cont and seq
functions subsystem-by-subsystem. It'd be the easiest to route all
through -mm but the conversion patches can go through individual
subsystem trees afterwards if necessary.

While there's ~70 line increase in LOC, the increase is from the
restructuring of bitmap output functions and addition of inline
interface functions along with comments and things get simplified /
more robust on the user side and future users won't have to try to
solve the same fruitless problem over and over again.

The patchset is based on top of -mm as of Dec 9, 2014 and also
available in the following git branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git review-bitmap-pr_cont

arch/mips/netlogic/common/smp.c | 11 +-
arch/powerpc/sysdev/xics/ics-opal.c | 7 -
arch/powerpc/sysdev/xics/ics-rtas.c | 8 -
arch/tile/kernel/hardwall.c | 6 -
arch/tile/kernel/proc.c | 6 -
arch/tile/kernel/setup.c | 12 +-
arch/tile/mm/homecache.c | 14 +--
arch/tile/mm/init.c | 12 +-
arch/x86/mm/numa.c | 9 --
arch/x86/platform/uv/uv_nmi.c | 27 ++----
arch/xtensa/kernel/setup.c | 10 --
drivers/net/ethernet/tile/tilegx.c | 6 -
drivers/net/ethernet/tile/tilepro.c | 6 -
include/linux/bitmap.h | 4
include/linux/cpumask.h | 18 ++++
include/linux/nodemask.h | 16 +++
kernel/cpuset.c | 13 ---
kernel/rcu/tree_plugin.h | 6 -
kernel/sched/core.c | 11 +-
kernel/sched/stats.c | 11 --
kernel/time/tick-sched.c | 12 --
lib/bitmap.c | 148 ++++++++++++++++++++++++++----------
mm/percpu.c | 7 -
23 files changed, 224 insertions(+), 156 deletions(-)

Thanks.

--
tejun


2014-12-10 15:53:23

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 06/12] x86: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

* uv_nmi_nr_cpus_pr() got overly smart and implemented "..."
abbreviation if the output stretched over the predefined 1024 byte
buffer. Replaced with plain pr_cont.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: [email protected]
Cc: Mike Travis <[email protected]>
---
arch/x86/mm/numa.c | 9 ++++-----
arch/x86/platform/uv/uv_nmi.c | 27 +++++++++------------------
2 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 1a88370..614a302 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -794,7 +794,6 @@ int early_cpu_to_node(int cpu)
void debug_cpumask_set_cpu(int cpu, int node, bool enable)
{
struct cpumask *mask;
- char buf[64];

if (node == NUMA_NO_NODE) {
/* early_cpu_to_node() already emits a warning and trace */
@@ -812,10 +811,10 @@ void debug_cpumask_set_cpu(int cpu, int node, bool enable)
else
cpumask_clear_cpu(cpu, mask);

- cpulist_scnprintf(buf, sizeof(buf), mask);
- printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
- enable ? "numa_add_cpu" : "numa_remove_cpu",
- cpu, node, buf);
+ printk(KERN_DEBUG "%s cpu %d node %d: mask now ",
+ enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node);
+ cpulist_pr_cont(mask);
+ pr_cont("\n");
return;
}

diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
index c6b146e..61ee9cf 100644
--- a/arch/x86/platform/uv/uv_nmi.c
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -273,20 +273,6 @@ static inline void uv_clear_nmi(int cpu)
}
}

-/* Print non-responding cpus */
-static void uv_nmi_nr_cpus_pr(char *fmt)
-{
- static char cpu_list[1024];
- int len = sizeof(cpu_list);
- int c = cpumask_weight(uv_nmi_cpu_mask);
- int n = cpulist_scnprintf(cpu_list, len, uv_nmi_cpu_mask);
-
- if (n >= len-1)
- strcpy(&cpu_list[len - 6], "...\n");
-
- printk(fmt, c, cpu_list);
-}
-
/* Ping non-responding cpus attemping to force them into the NMI handler */
static void uv_nmi_nr_cpus_ping(void)
{
@@ -371,16 +357,21 @@ static void uv_nmi_wait(int master)
break;

/* if not all made it in, send IPI NMI to them */
- uv_nmi_nr_cpus_pr(KERN_ALERT
- "UV: Sending NMI IPI to %d non-responding CPUs: %s\n");
+ pr_alert("UV: Sending NMI IPI to %d non-responding CPUs: ",
+ cpumask_weight(uv_nmi_cpu_mask));
+ cpulist_pr_cont(uv_nmi_cpu_mask);
+ pr_cont("\n");
+
uv_nmi_nr_cpus_ping();

/* if all cpus are in, then done */
if (!uv_nmi_wait_cpus(0))
break;

- uv_nmi_nr_cpus_pr(KERN_ALERT
- "UV: %d CPUs not in NMI loop: %s\n");
+ pr_alert("UV: %d CPUs not in NMI loop: ",
+ cpumask_weight(uv_nmi_cpu_mask));
+ cpulist_pr_cont(uv_nmi_cpu_mask);
+ pr_cont("\n");
} while (0);

pr_alert("UV: %d of %d CPUs in NMI\n",
--
2.1.0

2014-12-10 15:53:29

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 11/12] timer: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Gleixner <[email protected]>
---
kernel/time/tick-sched.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 4d54b75..dd43dd9 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -326,13 +326,6 @@ static int tick_nohz_cpu_down_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}

-/*
- * Worst case string length in chunks of CPU range seems 2 steps
- * separations: 0,2,4,6,...
- * This is NR_CPUS + sizeof('\0')
- */
-static char __initdata nohz_full_buf[NR_CPUS + 1];
-
static int tick_nohz_init_all(void)
{
int err = -1;
@@ -393,8 +386,9 @@ void __init tick_nohz_init(void)
context_tracking_cpu_set(cpu);

cpu_notifier(tick_nohz_cpu_down_callback, 0);
- cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), tick_nohz_full_mask);
- pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf);
+ pr_info("NO_HZ: Full dynticks CPUs: ");
+ cpulist_pr_cont(tick_nohz_full_mask);
+ pr_cont(".\n");
}
#endif

--
2.1.0

2014-12-10 15:53:28

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 10/12] sched: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
---
kernel/sched/core.c | 11 +++++------
kernel/sched/stats.c | 11 ++---------
2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 03fa7dd..7446963 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5403,9 +5403,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
struct cpumask *groupmask)
{
struct sched_group *group = sd->groups;
- char str[256];

- cpulist_scnprintf(str, sizeof(str), sched_domain_span(sd));
cpumask_clear(groupmask);

printk(KERN_DEBUG "%*s domain %d: ", level, "", level);
@@ -5418,7 +5416,9 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
return -1;
}

- printk(KERN_CONT "span %s level %s\n", str, sd->name);
+ printk(KERN_CONT "span ");
+ cpulist_pr_cont(sched_domain_span(sd));
+ printk(KERN_CONT " level %s\n", sd->name);

if (!cpumask_test_cpu(cpu, sched_domain_span(sd))) {
printk(KERN_ERR "ERROR: domain->span does not contain "
@@ -5463,9 +5463,8 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,

cpumask_or(groupmask, groupmask, sched_group_cpus(group));

- cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group));
-
- printk(KERN_CONT " %s", str);
+ printk(KERN_CONT " ");
+ cpulist_pr_cont(sched_group_cpus(group));
if (group->sgc->capacity != SCHED_CAPACITY_SCALE) {
printk(KERN_CONT " (cpu_capacity = %d)",
group->sgc->capacity);
diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
index a476bea..c2ae710 100644
--- a/kernel/sched/stats.c
+++ b/kernel/sched/stats.c
@@ -15,11 +15,6 @@
static int show_schedstat(struct seq_file *seq, void *v)
{
int cpu;
- int mask_len = DIV_ROUND_UP(NR_CPUS, 32) * 9;
- char *mask_str = kmalloc(mask_len, GFP_KERNEL);
-
- if (mask_str == NULL)
- return -ENOMEM;

if (v == (void *)1) {
seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
@@ -50,9 +45,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
for_each_domain(cpu, sd) {
enum cpu_idle_type itype;

- cpumask_scnprintf(mask_str, mask_len,
- sched_domain_span(sd));
- seq_printf(seq, "domain%d %s", dcount++, mask_str);
+ seq_printf(seq, "domain%d ", dcount++);
+ seq_cpumask(seq, sched_domain_span(sd));
for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
itype++) {
seq_printf(seq, " %u %u %u %u %u %u %u %u",
@@ -76,7 +70,6 @@ static int show_schedstat(struct seq_file *seq, void *v)
rcu_read_unlock();
#endif
}
- kfree(mask_str);
return 0;
}

--
2.1.0

2014-12-10 15:53:47

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 12/12] percpu: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Lameter <[email protected]>
---
mm/percpu.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/mm/percpu.c b/mm/percpu.c
index d39e2f4..3ff9b75 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1528,7 +1528,6 @@ static void pcpu_dump_alloc_info(const char *lvl,
int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
void *base_addr)
{
- static char cpus_buf[4096] __initdata;
static int smap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
static int dmap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
size_t dyn_size = ai->dyn_size;
@@ -1541,12 +1540,12 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
int *unit_map;
int group, unit, i;

- cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
-
#define PCPU_SETUP_BUG_ON(cond) do { \
if (unlikely(cond)) { \
pr_emerg("PERCPU: failed to initialize, %s", #cond); \
- pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf); \
+ pr_emerg("PERCPU: cpu_possible_mask="); \
+ cpumask_pr_cont(cpu_possible_mask); \
+ pr_cont("\n"); \
pcpu_dump_alloc_info(KERN_EMERG, ai); \
BUG(); \
} \
--
2.1.0

2014-12-10 15:53:20

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 01/12] bitmap: restructure bitmap_sn[list]printf()

bitmap_sn[list]printf() implement formatting a bitmap into the
specified string buffer. We want to add functions which target a
different output (printk). To enable that, this patch restructures
bitmap_sn[list]printf() so that the formatting and outputting are
separate.

Formatting is now handled by bitmap_print[_list]() and
bitmap_sn[list]printf() wrap the formatting functions with the output
callback bitmap_scnprintf_fn() which fills the string buffer. A later
patch will implement bitmap_pr_cont[_list]() by adding a different
outputting callback.

This patch doesn't change the behaviors of bitmap_sn[list]printf().

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
---
lib/bitmap.c | 113 ++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 40 deletions(-)

diff --git a/lib/bitmap.c b/lib/bitmap.c
index 324ea9e..f1d6351 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -372,25 +372,33 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
* second version by Paul Jackson, third by Joe Korty.
*/

+struct bitmap_scnprintf_data {
+ char *buf;
+ unsigned int buflen;
+ unsigned int len;
+};
+
+typedef __printf(2, 3) void (*bitmap_printfn_t)(void *data, const char *fmt, ...);
+
+static void bitmap_scnprintf_fn(void *data, const char *fmt, ...)
+{
+ struct bitmap_scnprintf_data *bsd = data;
+ va_list args;
+
+ va_start(args, fmt);
+ bsd->len += vscnprintf(bsd->buf + bsd->len, bsd->buflen - bsd->len,
+ fmt, args);
+ va_end(args);
+}
+
#define CHUNKSZ 32
#define nbits_to_hold_value(val) fls(val)
#define BASEDEC 10 /* fancier cpuset lists input in decimal */

-/**
- * bitmap_scnprintf - convert bitmap to an ASCII hex string.
- * @buf: byte buffer into which string is placed
- * @buflen: reserved size of @buf, in bytes
- * @maskp: pointer to bitmap to convert
- * @nmaskbits: size of bitmap, in bits
- *
- * Exactly @nmaskbits bits are displayed. Hex digits are grouped into
- * comma-separated sets of eight digits per set. Returns the number of
- * characters which were written to *buf, excluding the trailing \0.
- */
-int bitmap_scnprintf(char *buf, unsigned int buflen,
- const unsigned long *maskp, int nmaskbits)
+static void bitmap_print(const unsigned long *maskp, int nmaskbits,
+ bitmap_printfn_t printfn, void *printfn_data)
{
- int i, word, bit, len = 0;
+ int i, word, bit;
unsigned long val;
const char *sep = "";
int chunksz;
@@ -406,12 +414,30 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
word = i / BITS_PER_LONG;
bit = i % BITS_PER_LONG;
val = (maskp[word] >> bit) & chunkmask;
- len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
- (chunksz+3)/4, val);
+ printfn(printfn_data, "%s%0*lx", sep, (chunksz+3)/4, val);
chunksz = CHUNKSZ;
sep = ",";
}
- return len;
+}
+
+/**
+ * bitmap_scnprintf - convert bitmap to an ASCII hex string.
+ * @buf: byte buffer into which string is placed
+ * @buflen: reserved size of @buf, in bytes
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ *
+ * Exactly @nmaskbits bits are displayed. Hex digits are grouped into
+ * comma-separated sets of eight digits per set. Returns the number of
+ * characters which were written to *buf, excluding the trailing \0.
+ */
+int bitmap_scnprintf(char *buf, unsigned int buflen,
+ const unsigned long *maskp, int nmaskbits)
+{
+ struct bitmap_scnprintf_data bsd = { .buf = buf, .buflen = buflen };
+
+ bitmap_print(maskp, nmaskbits, bitmap_scnprintf_fn, &bsd);
+ return bsd.len;
}
EXPORT_SYMBOL(bitmap_scnprintf);

@@ -531,20 +557,37 @@ EXPORT_SYMBOL(bitmap_parse_user);
/*
* bscnl_emit(buf, buflen, rbot, rtop, bp)
*
- * Helper routine for bitmap_scnlistprintf(). Write decimal number
- * or range to buf, suppressing output past buf+buflen, with optional
- * comma-prefix. Return len of what was written to *buf, excluding the
- * trailing \0.
+ * Helper routine for bitmap_scnlistprintf(). Write decimal number or
+ * range to buf, with optional comma-prefix.
*/
-static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
+static inline void bscnl_emit(int rbot, int rtop, bool first,
+ bitmap_printfn_t printfn, void *printfn_data)
{
- if (len > 0)
- len += scnprintf(buf + len, buflen - len, ",");
+ if (!first)
+ printfn(printfn_data, ",");
if (rbot == rtop)
- len += scnprintf(buf + len, buflen - len, "%d", rbot);
+ printfn(printfn_data, "%d", rbot);
else
- len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
- return len;
+ printfn(printfn_data, "%d-%d", rbot, rtop);
+}
+
+static void bitmap_print_list(const unsigned long *maskp, int nmaskbits,
+ bitmap_printfn_t printfn, void *printfn_data)
+{
+ bool first = true;
+ /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+ int cur, rbot, rtop;
+
+ rbot = cur = find_first_bit(maskp, nmaskbits);
+ while (cur < nmaskbits) {
+ rtop = cur;
+ cur = find_next_bit(maskp, nmaskbits, cur+1);
+ if (cur >= nmaskbits || cur > rtop + 1) {
+ bscnl_emit(rbot, rtop, first, printfn, printfn_data);
+ rbot = cur;
+ first = false;
+ }
+ }
}

/**
@@ -566,24 +609,14 @@ static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
int bitmap_scnlistprintf(char *buf, unsigned int buflen,
const unsigned long *maskp, int nmaskbits)
{
- int len = 0;
- /* current bit is 'cur', most recently seen range is [rbot, rtop] */
- int cur, rbot, rtop;
+ struct bitmap_scnprintf_data bsd = { .buf = buf, .buflen = buflen };

if (buflen == 0)
return 0;
buf[0] = 0;

- rbot = cur = find_first_bit(maskp, nmaskbits);
- while (cur < nmaskbits) {
- rtop = cur;
- cur = find_next_bit(maskp, nmaskbits, cur+1);
- if (cur >= nmaskbits || cur > rtop + 1) {
- len = bscnl_emit(buf, buflen, rbot, rtop, len);
- rbot = cur;
- }
- }
- return len;
+ bitmap_print_list(maskp, nmaskbits, bitmap_scnprintf_fn, &bsd);
+ return bsd.len;
}
EXPORT_SYMBOL(bitmap_scnlistprintf);

--
2.1.0

2014-12-10 15:54:50

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 08/12] cpuset: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

* kernel/cpuset.c::cpuset_print_task_mems_allowed() used a static
buffer which is protected by a dedicated spinlock. Replaced with
plain pr_conts.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Li Zefan <[email protected]>
---
kernel/cpuset.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index fdf1759..6a7f466 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2614,8 +2614,6 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);
}

-#define CPUSET_NODELIST_LEN (256)
-
/**
* cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
* @tsk: pointer to task_struct of some task.
@@ -2625,23 +2623,18 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
*/
void cpuset_print_task_mems_allowed(struct task_struct *tsk)
{
- /* Statically allocated to prevent using excess stack. */
- static char cpuset_nodelist[CPUSET_NODELIST_LEN];
- static DEFINE_SPINLOCK(cpuset_buffer_lock);
struct cgroup *cgrp;

- spin_lock(&cpuset_buffer_lock);
rcu_read_lock();

cgrp = task_cs(tsk)->css.cgroup;
- nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
- tsk->mems_allowed);
pr_info("%s cpuset=", tsk->comm);
pr_cont_cgroup_name(cgrp);
- pr_cont(" mems_allowed=%s\n", cpuset_nodelist);
+ pr_cont(" mems_allowed=");
+ nodelist_pr_cont(tsk->mems_allowed);
+ pr_cont("\n");

rcu_read_unlock();
- spin_unlock(&cpuset_buffer_lock);
}

/*
--
2.1.0

2014-12-10 15:54:22

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 09/12] rcu: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: "Paul E. McKenney" <[email protected]>
---
kernel/rcu/tree_plugin.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 7a72858..a788a6f 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -53,7 +53,6 @@ DEFINE_PER_CPU(char, rcu_cpu_has_work);
static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
static bool have_rcu_nocb_mask; /* Was rcu_nocb_mask allocated? */
static bool __read_mostly rcu_nocb_poll; /* Offload kthread are to poll. */
-static char __initdata nocb_buf[NR_CPUS * 5];
#endif /* #ifdef CONFIG_RCU_NOCB_CPU */

/*
@@ -2377,8 +2376,9 @@ void __init rcu_init_nohz(void)
cpumask_and(rcu_nocb_mask, cpu_possible_mask,
rcu_nocb_mask);
}
- cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
- pr_info("\tOffload RCU callbacks from CPUs: %s.\n", nocb_buf);
+ pr_info("\tOffload RCU callbacks from CPUs: ");
+ cpulist_pr_cont(rcu_nocb_mask);
+ pr_cont(".\n");
if (rcu_nocb_poll)
pr_info("\tPoll for callbacks from no-CBs CPUs.\n");

--
2.1.0

2014-12-10 15:55:10

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 07/12] xtensa: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Chris Zankel <[email protected]>
Cc: Max Filippov <[email protected]>
Cc: [email protected]
---
arch/xtensa/kernel/setup.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 06370cc..441f505 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -574,12 +574,12 @@ void machine_power_off(void)
static int
c_show(struct seq_file *f, void *slot)
{
- char buf[NR_CPUS * 5];
-
- cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask);
/* high-level stuff */
seq_printf(f, "CPU count\t: %u\n"
- "CPU list\t: %s\n"
+ "CPU list\t: ",
+ num_online_cpus());
+ seq_cpumask_list(f, cpu_online_mask);
+ seq_printf(f, "\n"
"vendor_id\t: Tensilica\n"
"model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
"core ID\t\t: " XCHAL_CORE_ID "\n"
@@ -587,8 +587,6 @@ c_show(struct seq_file *f, void *slot)
"byte order\t: %s\n"
"cpu MHz\t\t: %lu.%02lu\n"
"bogomips\t: %lu.%02lu\n",
- num_online_cpus(),
- buf,
XCHAL_BUILD_UNIQUE_ID,
XCHAL_HAVE_BE ? "big" : "little",
ccount_freq/1000000,
--
2.1.0

2014-12-10 15:53:18

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 02/12] bitmap, cpumask, nodemask: implement pr_cont variants of formatting functions

These three bitmap types implement functions which format the bitmap
into a string buffer; however, how long this buffer should be isn't
defined anywhere and given that some of these bitmaps can be too large
to be formatted into an on-stack buffer people sometimes are
unnecessarily forced to come up with creative solutions and
compromises for the buffer just to printk these bitmaps.

The previous patch restructured bitmap_scn[list]printf() so that a
different output target can be easily added. This patch implements
bitmap_pr_cont[_list]() which format the specified bitmap and output
it directly through printk so that it can be interposed with other
printk calls.

The counterparts in cpumask and nodemask - cpu{mask|list}_pr_cont()
and node{mask|list}_pr_cont() are also added.

This patch doesn't convert the existing users. The next one will.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
---
include/linux/bitmap.h | 4 ++++
include/linux/cpumask.h | 18 ++++++++++++++++++
include/linux/nodemask.h | 16 ++++++++++++++++
lib/bitmap.c | 35 +++++++++++++++++++++++++++++++++++
4 files changed, 73 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 202e403..271537e 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -53,9 +53,11 @@
* bitmap_onto(dst, orig, relmap, nbits) *dst = orig relative to relmap
* bitmap_fold(dst, orig, sz, nbits) dst bits = orig bits mod sz
* bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
+ * bitmap_pr_cont(src, nbits) pr_cont bitmap src
* bitmap_parse(buf, buflen, dst, nbits) Parse bitmap dst from kernel buf
* bitmap_parse_user(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
* bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf
+ * bitmap_pr_cont_list(src, nbits) pr_cont bitmap src as list
* bitmap_parselist(buf, dst, nbits) Parse bitmap dst from kernel buf
* bitmap_parselist_user(buf, dst, nbits) Parse bitmap dst from user buf
* bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region
@@ -149,12 +151,14 @@ bitmap_find_next_zero_area(unsigned long *map,

extern int bitmap_scnprintf(char *buf, unsigned int len,
const unsigned long *src, int nbits);
+extern void bitmap_pr_cont(const unsigned long *src, int nbits);
extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
unsigned long *dst, int nbits);
extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
unsigned long *dst, int nbits);
extern int bitmap_scnlistprintf(char *buf, unsigned int len,
const unsigned long *src, int nbits);
+extern void bitmap_pr_cont_list(const unsigned long *src, int nbits);
extern int bitmap_parselist(const char *buf, unsigned long *maskp,
int nmaskbits);
extern int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen,
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index b950e9d..743828c 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -554,6 +554,15 @@ static inline int cpumask_scnprintf(char *buf, int len,
}

/**
+ * cpumask_pr_cont - pr_cont a cpumask as comma-separated hex
+ * @srcp: the cpumask to print
+ */
+static inline void cpumask_pr_cont(const struct cpumask *srcp)
+{
+ bitmap_pr_cont(cpumask_bits(srcp), nr_cpumask_bits);
+}
+
+/**
* cpumask_parse_user - extract a cpumask from a user string
* @buf: the buffer to extract from
* @len: the length of the buffer
@@ -599,6 +608,15 @@ static inline int cpulist_scnprintf(char *buf, int len,
}

/**
+ * cpulist_pr_cont - pr_cont a cpumask as comma-separated list
+ * @srcp: the cpumask to print
+ */
+static inline void cpulist_pr_cont(const struct cpumask *srcp)
+{
+ bitmap_pr_cont_list(cpumask_bits(srcp), nr_cpumask_bits);
+}
+
+/**
* cpumask_parse - extract a cpumask from from a string
* @buf: the buffer to extract from
* @dstp: the cpumask to set.
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 83a6aed..e8c3bdc 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -53,8 +53,10 @@
* unsigned long *nodes_addr(mask) Array of unsigned long's in mask
*
* int nodemask_scnprintf(buf, len, mask) Format nodemask for printing
+ * void nodemask_pr_cont(mask) pr_cont nodemask
* int nodemask_parse_user(ubuf, ulen, mask) Parse ascii string as nodemask
* int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
+ * void nodelist_pr_cont(mask) pr_cont nodemask as list
* int nodelist_parse(buf, map) Parse ascii string as nodelist
* int node_remap(oldbit, old, new) newbit = map(old, new)(oldbit)
* void nodes_remap(dst, src, old, new) *dst = map(old, new)(src)
@@ -312,6 +314,13 @@ static inline int __nodemask_scnprintf(char *buf, int len,
return bitmap_scnprintf(buf, len, srcp->bits, nbits);
}

+#define nodemask_pr_cont(src) \
+ __nodemask_pr_cont(&(src), MAX_NUMNODES)
+static inline void __nodemask_pr_cont(const nodemask_t *srcp, int nbits)
+{
+ bitmap_pr_cont(srcp->bits, nbits);
+}
+
#define nodemask_parse_user(ubuf, ulen, dst) \
__nodemask_parse_user((ubuf), (ulen), &(dst), MAX_NUMNODES)
static inline int __nodemask_parse_user(const char __user *buf, int len,
@@ -328,6 +337,13 @@ static inline int __nodelist_scnprintf(char *buf, int len,
return bitmap_scnlistprintf(buf, len, srcp->bits, nbits);
}

+#define nodelist_pr_cont(src) \
+ __nodelist_pr_cont(&(src), MAX_NUMNODES)
+static inline void __nodelist_pr_cont(const nodemask_t *srcp, int nbits)
+{
+ bitmap_pr_cont_list(srcp->bits, nbits);
+}
+
#define nodelist_parse(buf, dst) __nodelist_parse((buf), &(dst), MAX_NUMNODES)
static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
{
diff --git a/lib/bitmap.c b/lib/bitmap.c
index f1d6351..e4eaf30f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -391,6 +391,15 @@ static void bitmap_scnprintf_fn(void *data, const char *fmt, ...)
va_end(args);
}

+static void bitmap_pr_cont_fn(void *data, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintk(fmt, args);
+ va_end(args);
+}
+
#define CHUNKSZ 32
#define nbits_to_hold_value(val) fls(val)
#define BASEDEC 10 /* fancier cpuset lists input in decimal */
@@ -442,6 +451,19 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
EXPORT_SYMBOL(bitmap_scnprintf);

/**
+ * bitmap_pr_cont - pr_cont bitmap as an ASCII hex string.
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ *
+ * pr_cont() the same output as bitmap_scnprintf().
+ */
+void bitmap_pr_cont(const unsigned long *maskp, int nmaskbits)
+{
+ bitmap_print(maskp, nmaskbits, bitmap_pr_cont_fn, NULL);
+}
+EXPORT_SYMBOL(bitmap_pr_cont);
+
+/**
* __bitmap_parse - convert an ASCII hex string into a bitmap.
* @buf: pointer to buffer containing string.
* @buflen: buffer size in bytes. If string is smaller than this
@@ -621,6 +643,19 @@ int bitmap_scnlistprintf(char *buf, unsigned int buflen,
EXPORT_SYMBOL(bitmap_scnlistprintf);

/**
+ * bitmap_pr_cont_list - pr_cont bitmap as a list format ASCII string
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ *
+ * pr_cont() the same output as bitmap_scnlistprintf().
+ */
+void bitmap_pr_cont_list(const unsigned long *maskp, int nmaskbits)
+{
+ bitmap_print_list(maskp, nmaskbits, bitmap_pr_cont_fn, NULL);
+}
+EXPORT_SYMBOL(bitmap_pr_cont_list);
+
+/**
* bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
* @list: indicates whether the bitmap must be list
* @buf: page aligned buffer into which string is placed
--
2.1.0

2014-12-10 15:53:15

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 03/12] mips: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: [email protected]
---
arch/mips/netlogic/common/smp.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 4fde7ac..e91592a 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -162,7 +162,6 @@ void __init nlm_smp_setup(void)
unsigned int boot_cpu;
int num_cpus, i, ncore, node;
volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
- char buf[64];

boot_cpu = hard_smp_processor_id();
cpumask_clear(&phys_cpu_present_mask);
@@ -189,10 +188,12 @@ void __init nlm_smp_setup(void)
}
}

- cpumask_scnprintf(buf, ARRAY_SIZE(buf), &phys_cpu_present_mask);
- pr_info("Physical CPU mask: %s\n", buf);
- cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
- pr_info("Possible CPU mask: %s\n", buf);
+ pr_info("Physical CPU mask: ");
+ cpumask_pr_cont(&phys_cpu_present_mask);
+ pr_cont("\n");
+ pr_info("Possible CPU mask: ");
+ cpumask_pr_cont(cpu_possible_mask);
+ pr_cont("\n");

/* check with the cores we have woken up */
for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
--
2.1.0

2014-12-10 15:56:48

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 05/12] tile: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Chris Metcalf <[email protected]>
---
arch/tile/kernel/hardwall.c | 6 ++----
arch/tile/kernel/proc.c | 6 +++---
arch/tile/kernel/setup.c | 12 ++++++------
arch/tile/mm/homecache.c | 14 +++++++-------
arch/tile/mm/init.c | 12 ++++++------
drivers/net/ethernet/tile/tilegx.c | 6 +++---
drivers/net/ethernet/tile/tilepro.c | 6 +++---
7 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index c4646bb..f8b8453 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -909,11 +909,9 @@ static void hardwall_destroy(struct hardwall_info *info)
static int hardwall_proc_show(struct seq_file *sf, void *v)
{
struct hardwall_info *info = sf->private;
- char buf[256];

- int rc = cpulist_scnprintf(buf, sizeof(buf), &info->cpumask);
- buf[rc++] = '\n';
- seq_write(sf, buf, rc);
+ seq_cpumask_list(sf, &info->cpumask);
+ seq_putc(sf, '\n');
return 0;
}

diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c
index 6829a95..3dbd98a 100644
--- a/arch/tile/kernel/proc.c
+++ b/arch/tile/kernel/proc.c
@@ -45,10 +45,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
int n = ptr_to_cpu(v);

if (n == 0) {
- char buf[NR_CPUS*5];
- cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask);
seq_printf(m, "cpu count\t: %d\n", num_online_cpus());
- seq_printf(m, "cpu list\t: %s\n", buf);
+ seq_printf(m, "cpu list\t: ");
+ seq_cpumask_list(m, cpu_online_mask);
+ seq_printf(m, "\n");
seq_printf(m, "model name\t: %s\n", chip_model);
seq_printf(m, "flags\t\t:\n"); /* nothing for now */
seq_printf(m, "cpu MHz\t\t: %llu.%06llu\n",
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 864eea6..6532399 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -215,12 +215,12 @@ early_param("mem", setup_mem); /* compatibility with x86 */

static int __init setup_isolnodes(char *str)
{
- char buf[MAX_NUMNODES * 5];
if (str == NULL || nodelist_parse(str, isolnodes) != 0)
return -EINVAL;

- nodelist_scnprintf(buf, sizeof(buf), isolnodes);
- pr_info("Set isolnodes value to '%s'\n", buf);
+ pr_info("Set isolnodes value to '");
+ nodelist_pr_cont(isolnodes);
+ pr_cont("'\n");
return 0;
}
early_param("isolnodes", setup_isolnodes);
@@ -1316,9 +1316,9 @@ early_param("disabled_cpus", disabled_cpus);
void __init print_disabled_cpus(void)
{
if (!cpumask_empty(&disabled_map)) {
- char buf[100];
- cpulist_scnprintf(buf, sizeof(buf), &disabled_map);
- pr_info("CPUs not available for Linux: %s\n", buf);
+ pr_info("CPUs not available for Linux: ");
+ cpulist_pr_cont(&disabled_map);
+ pr_cont("\n");
}
}

diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index cd33873..a7278fe 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -115,7 +115,6 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
struct cpumask cache_cpumask_copy, tlb_cpumask_copy;
struct cpumask *cache_cpumask, *tlb_cpumask;
HV_PhysAddr cache_pa;
- char cache_buf[NR_CPUS*5], tlb_buf[NR_CPUS*5];

mb(); /* provided just to simplify "magic hypervisor" mode */

@@ -149,13 +148,14 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
asids, asidcount);
if (rc == 0)
return;
- cpumask_scnprintf(cache_buf, sizeof(cache_buf), &cache_cpumask_copy);
- cpumask_scnprintf(tlb_buf, sizeof(tlb_buf), &tlb_cpumask_copy);

- pr_err("hv_flush_remote(%#llx, %#lx, %p [%s], %#lx, %#lx, %#lx, %p [%s], %p, %d) = %d\n",
- cache_pa, cache_control, cache_cpumask, cache_buf,
- (unsigned long)tlb_va, tlb_length, tlb_pgsize,
- tlb_cpumask, tlb_buf, asids, asidcount, rc);
+ pr_err("hv_flush_remote(%#llx, %#lx, %p [",
+ cache_pa, cache_control, cache_cpumask);
+ cpumask_pr_cont(&cache_cpumask_copy);
+ pr_cont("], %#lx, %#lx, %#lx, %p [",
+ (unsigned long)tlb_va, tlb_length, tlb_pgsize, tlb_cpumask);
+ cpumask_pr_cont(&tlb_cpumask_copy);
+ pr_cont("], %p, %d) = %d\n", asids, asidcount, rc);
panic("Unsafe to continue.");
}

diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index be240cc..8e6dea3 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -353,15 +353,15 @@ static int __init setup_ktext(char *str)

/* Neighborhood ktext pages on specified mask */
else if (cpulist_parse(str, &ktext_mask) == 0) {
- char buf[NR_CPUS * 5];
- cpulist_scnprintf(buf, sizeof(buf), &ktext_mask);
if (cpumask_weight(&ktext_mask) > 1) {
ktext_small = 1;
- pr_info("ktext: using caching neighborhood %s with small pages\n",
- buf);
+ pr_info("ktext: using caching neighborhood ");
+ cpulist_pr_cont(&ktext_mask);
+ pr_cont(" with small pages\n");
} else {
- pr_info("ktext: caching on cpu %s with one huge page\n",
- buf);
+ pr_info("ktext: caching on cpu ");
+ cpulist_pr_cont(&ktext_mask);
+ pr_cont(" with one huge page\n");
}
}

diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 049747f..3ecb8b2 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -292,7 +292,6 @@ static inline int mpipe_instance(struct net_device *dev)
*/
static bool network_cpus_init(void)
{
- char buf[1024];
int rc;

if (network_cpus_string == NULL)
@@ -314,8 +313,9 @@ static bool network_cpus_init(void)
return false;
}

- cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map);
- pr_info("Linux network CPUs: %s\n", buf);
+ pr_info("Linux network CPUs: ");
+ cpulist_pr_cont(&network_cpus_map);
+ pr_cont("\n");
return true;
}

diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index fb12d31..ab9bfbf 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -2410,9 +2410,9 @@ static int __init network_cpus_setup(char *str)
if (cpumask_empty(&network_cpus_map)) {
pr_warn("Ignoring network_cpus='%s'\n", str);
} else {
- char buf[1024];
- cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map);
- pr_info("Linux network CPUs: %s\n", buf);
+ pr_info("Linux network CPUs: ");
+ cpulist_pr_cont(&network_cpus_map);
+ pr_cont("\n");
network_cpus_used = true;
}
}
--
2.1.0

2014-12-10 15:57:10

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 04/12] powerpc: use {cpu|node}mask pr_cont and seq output functions

Convert the existing user of cpu{mask|list}_scnprintf() and
node{mask|list}_scnprintf() which use them just to printk or
seq_printf() the resulting buffer to use the following functions
instead respectively.

* For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().

* For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().

Because these conversions usually break up a single output function
call into multiple, the reduction is LOC isn't too big but it removes
unnecessary complexity and/or arbitrary limit on the length printed.

This patch is dependent on the previous patch ("bitmap, cpumask,
nodemask: implement pr_cont variants of formatting functions") which
is planned to go through -mm. It'd be the easiest to route this
together. If this should go through the subsystem tree, please wait
till the forementioned patch is merged to mainline.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
---
arch/powerpc/sysdev/xics/ics-opal.c | 7 +++----
arch/powerpc/sysdev/xics/ics-rtas.c | 8 +++-----
2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index 4ba554e..0c200e8 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -131,10 +131,9 @@ static int ics_opal_set_affinity(struct irq_data *d,

wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
if (wanted_server < 0) {
- char cpulist[128];
- cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
- pr_warning("%s: No online cpus in the mask %s for irq %d\n",
- __func__, cpulist, d->irq);
+ pr_warning("%s: No online cpus in the mask ", __func__);
+ cpumask_pr_cont(cpumask);
+ pr_cont(" for irq %d\n", d->irq);
return -1;
}
server = ics_opal_mangle_server(wanted_server);
diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c
index bc81335b..1e2f562 100644
--- a/arch/powerpc/sysdev/xics/ics-rtas.c
+++ b/arch/powerpc/sysdev/xics/ics-rtas.c
@@ -140,11 +140,9 @@ static int ics_rtas_set_affinity(struct irq_data *d,

irq_server = xics_get_irq_server(d->irq, cpumask, 1);
if (irq_server == -1) {
- char cpulist[128];
- cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
- printk(KERN_WARNING
- "%s: No online cpus in the mask %s for irq %d\n",
- __func__, cpulist, d->irq);
+ pr_warning("%s: No online cpus in the mask ", __func__);
+ cpumask_pr_cont(cpumask);
+ pr_cont(" for irq %d\n", d->irq);
return -1;
}

--
2.1.0

2014-12-10 16:29:37

by Paul E. McKenney

[permalink] [raw]
Subject: Re: [PATCH 09/12] rcu: use {cpu|node}mask pr_cont and seq output functions

On Wed, Dec 10, 2014 at 10:52:51AM -0500, Tejun Heo wrote:
> Convert the existing user of cpu{mask|list}_scnprintf() and
> node{mask|list}_scnprintf() which use them just to printk or
> seq_printf() the resulting buffer to use the following functions
> instead respectively.
>
> * For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().
>
> * For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().
>
> Because these conversions usually break up a single output function
> call into multiple, the reduction is LOC isn't too big but it removes
> unnecessary complexity and/or arbitrary limit on the length printed.
>
> This patch is dependent on the previous patch ("bitmap, cpumask,
> nodemask: implement pr_cont variants of formatting functions") which
> is planned to go through -mm. It'd be the easiest to route this
> together. If this should go through the subsystem tree, please wait
> till the forementioned patch is merged to mainline.

It should be OK to send this via your tree.

> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Andrew Morton <[email protected]>
> Cc: "Paul E. McKenney" <[email protected]>

Acked-by: Paul E. McKenney <[email protected]>

> ---
> kernel/rcu/tree_plugin.h | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
> index 7a72858..a788a6f 100644
> --- a/kernel/rcu/tree_plugin.h
> +++ b/kernel/rcu/tree_plugin.h
> @@ -53,7 +53,6 @@ DEFINE_PER_CPU(char, rcu_cpu_has_work);
> static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
> static bool have_rcu_nocb_mask; /* Was rcu_nocb_mask allocated? */
> static bool __read_mostly rcu_nocb_poll; /* Offload kthread are to poll. */
> -static char __initdata nocb_buf[NR_CPUS * 5];
> #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
>
> /*
> @@ -2377,8 +2376,9 @@ void __init rcu_init_nohz(void)
> cpumask_and(rcu_nocb_mask, cpu_possible_mask,
> rcu_nocb_mask);
> }
> - cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
> - pr_info("\tOffload RCU callbacks from CPUs: %s.\n", nocb_buf);
> + pr_info("\tOffload RCU callbacks from CPUs: ");
> + cpulist_pr_cont(rcu_nocb_mask);
> + pr_cont(".\n");
> if (rcu_nocb_poll)
> pr_info("\tPoll for callbacks from no-CBs CPUs.\n");
>
> --
> 2.1.0
>

2014-12-10 18:38:37

by Max Filippov

[permalink] [raw]
Subject: Re: [PATCH 07/12] xtensa: use {cpu|node}mask pr_cont and seq output functions

On Wed, Dec 10, 2014 at 6:52 PM, Tejun Heo <[email protected]> wrote:
> Convert the existing user of cpu{mask|list}_scnprintf() and
> node{mask|list}_scnprintf() which use them just to printk or
> seq_printf() the resulting buffer to use the following functions
> instead respectively.
>
> * For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().
>
> * For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().
>
> Because these conversions usually break up a single output function
> call into multiple, the reduction is LOC isn't too big but it removes
> unnecessary complexity and/or arbitrary limit on the length printed.
>
> This patch is dependent on the previous patch ("bitmap, cpumask,
> nodemask: implement pr_cont variants of formatting functions") which
> is planned to go through -mm. It'd be the easiest to route this
> together. If this should go through the subsystem tree, please wait
> till the forementioned patch is merged to mainline.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Andrew Morton <[email protected]>
> Cc: Chris Zankel <[email protected]>
> Cc: Max Filippov <[email protected]>
> Cc: [email protected]
> ---
> arch/xtensa/kernel/setup.c | 10 ++++------
> 1 file changed, 4 insertions(+), 6 deletions(-)

Acked-by: Max Filippov <[email protected]>

--
Thanks.
-- Max

2014-12-10 21:49:47

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCHSET -mm] bitmap, cpumask, nodemask: implement pr_cont functions and use di"

On Wed, 10 Dec 2014 10:52:42 -0500 Tejun Heo <[email protected]> wrote:

> 0001-bitmap-restructure-bitmap_sn-list-printf.patch
> 0002-bitmap-cpumask-nodemask-implement-pr_cont-variants-o.patch
> 0003-mips-use-cpu-node-mask-pr_cont-and-seq-output-functi.patch
> 0004-powerpc-use-cpu-node-mask-pr_cont-and-seq-output-fun.patch
> 0005-tile-use-cpu-node-mask-pr_cont-and-seq-output-functi.patch
> 0006-x86-use-cpu-node-mask-pr_cont-and-seq-output-functio.patch
> 0007-xtensa-use-cpu-node-mask-pr_cont-and-seq-output-func.patch
> 0008-cpuset-use-cpu-node-mask-pr_cont-and-seq-output-func.patch
> 0009-rcu-use-cpu-node-mask-pr_cont-and-seq-output-functio.patch
> 0010-sched-use-cpu-node-mask-pr_cont-and-seq-output-funct.patch
> 0011-timer-use-cpu-node-mask-pr_cont-and-seq-output-funct.patch
> 0012-percpu-use-cpu-node-mask-pr_cont-and-seq-output-func.patch
>
> The first two patches implement the pr_cont variants of the formatting
> functions. The rest convert the existing users to pr_cont and seq
> functions subsystem-by-subsystem. It'd be the easiest to route all
> through -mm but the conversion patches can go through individual
> subsystem trees afterwards if necessary.

But you're working on other code which will depend on this? If so
perhaps these should be held in your tree.

2014-12-10 22:12:14

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCHSET -mm] bitmap, cpumask, nodemask: implement pr_cont functions and use di"

On Wed, Dec 10, 2014 at 01:49:44PM -0800, Andrew Morton wrote:
> On Wed, 10 Dec 2014 10:52:42 -0500 Tejun Heo <[email protected]> wrote:
> > The first two patches implement the pr_cont variants of the formatting
> > functions. The rest convert the existing users to pr_cont and seq
> > functions subsystem-by-subsystem. It'd be the easiest to route all
> > through -mm but the conversion patches can go through individual
> > subsystem trees afterwards if necessary.
>
> But you're working on other code which will depend on this? If so
> perhaps these should be held in your tree.

Yeah, that works too. I was still targeting 3.19 window and some of
the conversion patches were conflicting, so thought it'd be easier
through -mm.

Given that the changes aren't that invasive, I think it'd be still a
good idea to merge the workqueue debugging during this merge window as
it gives a lot more visibility into tricky issues. Once it's agreed
on, I'll try to route the feature patches (the first two from this
series + actual workqueue changes) early through wq branch.

Thanks.

--
tejun

2014-12-15 10:39:33

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH 10/12] sched: use {cpu|node}mask pr_cont and seq output functions

On Wed, Dec 10, 2014 at 10:52:52AM -0500, Tejun Heo wrote:
> Convert the existing user of cpu{mask|list}_scnprintf() and
> node{mask|list}_scnprintf() which use them just to printk or
> seq_printf() the resulting buffer to use the following functions
> instead respectively.
>
> * For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().
>
> * For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().
>
> Because these conversions usually break up a single output function
> call into multiple, the reduction is LOC isn't too big but it removes
> unnecessary complexity and/or arbitrary limit on the length printed.
>
> This patch is dependent on the previous patch ("bitmap, cpumask,
> nodemask: implement pr_cont variants of formatting functions") which
> is planned to go through -mm. It'd be the easiest to route this
> together. If this should go through the subsystem tree, please wait
> till the forementioned patch is merged to mainline.
>

I would very much prefer something like the below instead..

I'm not a great fan of pr_cont, it makes a mess of things if there's
multiple cpus printing bits.

---
Subject: lib/vsprintf: Provide %pc to print cpumasks
From: Peter Zijlstra <[email protected]>
Date: Fri May 11 00:35:15 CEST 2012


Signed-off-by: Peter Zijlstra <[email protected]>
---
arch/x86/mm/numa.c | 6 ++----
kernel/sched/core.c | 8 ++------
lib/vsprintf.c | 5 +++++
3 files changed, 9 insertions(+), 10 deletions(-)

--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -737,7 +737,6 @@ int early_cpu_to_node(int cpu)
void debug_cpumask_set_cpu(int cpu, int node, bool enable)
{
struct cpumask *mask;
- char buf[64];

if (node == NUMA_NO_NODE) {
/* early_cpu_to_node() already emits a warning and trace */
@@ -755,10 +754,9 @@ void debug_cpumask_set_cpu(int cpu, int
else
cpumask_clear_cpu(cpu, mask);

- cpulist_scnprintf(buf, sizeof(buf), mask);
- printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
+ printk(KERN_DEBUG "%s cpu %d node %d: mask now %pc\n",
enable ? "numa_add_cpu" : "numa_remove_cpu",
- cpu, node, buf);
+ cpu, node, mask);
return;
}

--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4944,9 +4944,7 @@ static int sched_domain_debug_one(struct
struct cpumask *groupmask)
{
struct sched_group *group = sd->groups;
- char str[256];

- cpulist_scnprintf(str, sizeof(str), sched_domain_span(sd));
cpumask_clear(groupmask);

printk(KERN_DEBUG "%*s domain %d: ", level, "", level);
@@ -4959,7 +4957,7 @@ static int sched_domain_debug_one(struct
return -1;
}

- printk(KERN_CONT "span %s level %s\n", str, sd->name);
+ printk(KERN_CONT "span %pc level %s\n", sched_domain_span(sd), sd->name);

if (!cpumask_test_cpu(cpu, sched_domain_span(sd))) {
printk(KERN_ERR "ERROR: domain->span does not contain "
@@ -5005,9 +5003,7 @@ static int sched_domain_debug_one(struct

cpumask_or(groupmask, groupmask, sched_group_cpus(group));

- cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group));
-
- printk(KERN_CONT " %s", str);
+ printk(KERN_CONT " %pc", sched_group_cpus(group));
if (group->sgp->power != SCHED_POWER_SCALE) {
printk(KERN_CONT " (cpu_power = %d)",
group->sgp->power);
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -27,6 +27,7 @@
#include <linux/uaccess.h>
#include <linux/ioport.h>
#include <linux/dcache.h>
+#include <linux/cpumask.h>
#include <net/addrconf.h>

#include <asm/page.h> /* for PAGE_SIZE */
@@ -1218,6 +1219,7 @@ int kptr_restrict __read_mostly;
* The maximum supported length is 64 bytes of the input. Consider
* to use print_hex_dump() for the larger input.
* - 'a' For a phys_addr_t type and its derivative types (passed by reference)
+ * - 'c' For a cpumask list
*
* Note: The difference between 'S' and 'F' is that on ia64 and ppc64
* function pointers are really function descriptors, which contain a
@@ -1335,6 +1337,8 @@ char *pointer(const char *fmt, char *buf
return dentry_name(buf, end,
((const struct file *)ptr)->f_path.dentry,
spec, fmt);
+ case 'c':
+ return buf + cpulist_scnprintf(buf, end - buf, ptr);
}
spec.flags |= SMALL;
if (spec.field_width == -1) {
@@ -1576,6 +1580,7 @@ int format_decode(const char *fmt, struc
* case.
* %*ph[CDN] a variable-length hex string with a separator (supports up to 64
* bytes of the input)
+ * %pc print a cpumask as comma-separated list
* %n is ignored
*
* ** Please update Documentation/printk-formats.txt when making changes **

2014-12-15 17:03:13

by Chris Metcalf

[permalink] [raw]
Subject: Re: [PATCH 05/12] tile: use {cpu|node}mask pr_cont and seq output functions

On 12/10/2014 10:52 AM, Tejun Heo wrote:
> Convert the existing user of cpu{mask|list}_scnprintf() and
> node{mask|list}_scnprintf() which use them just to printk or
> seq_printf() the resulting buffer to use the following functions
> instead respectively.
>
> * For printk: cpu{mask|list}_pr_cont() and node{mask|list}_pr_cont().
>
> * For seq_file: seq_cpumask[_list]() and seq_nodemask[_list]().
>
> Because these conversions usually break up a single output function
> call into multiple, the reduction is LOC isn't too big but it removes
> unnecessary complexity and/or arbitrary limit on the length printed.
>
> This patch is dependent on the previous patch ("bitmap, cpumask,
> nodemask: implement pr_cont variants of formatting functions") which
> is planned to go through -mm. It'd be the easiest to route this
> together. If this should go through the subsystem tree, please wait
> till the forementioned patch is merged to mainline.
>
> Signed-off-by: Tejun Heo<[email protected]>
> Cc: Andrew Morton<[email protected]>
> Cc: Chris Metcalf<[email protected]>
> ---
> arch/tile/kernel/hardwall.c | 6 ++----
> arch/tile/kernel/proc.c | 6 +++---
> arch/tile/kernel/setup.c | 12 ++++++------
> arch/tile/mm/homecache.c | 14 +++++++-------
> arch/tile/mm/init.c | 12 ++++++------
> drivers/net/ethernet/tile/tilegx.c | 6 +++---
> drivers/net/ethernet/tile/tilepro.c | 6 +++---
> 7 files changed, 30 insertions(+), 32 deletions(-)

Acked-by: Chris Metcalf <[email protected]>

--
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com