* Add a new cpus_scnprintf() function and a sysctl flag to control how cpumask sets are printed. The default is to use the current cpumask_scnprintf(). If kernel.compat_cpus_printf is '0' (default 1), then cpulist_scnprintf() is used. A nodes_scnprintf() function is also provided for compatibilty. Note that setting the kernel.compat_cpus_printf to '0' also makes the syntax compatible with the setting and showing of cpuset parameters such as cpu_exclusive and mem_exclusive. This is introduced with a CONFIG_KERN_COMPAT_CPUSET_PRINTF flag which currently is only defined for X86_64_SMP architecture. * In addition, remove the cpumask_scnprintf_len() function. This is all needed to accomodate large NR_CPUS count and the usage has been added to Documentation/sysctl/kernel.txt. Based on: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + x86/latest .../x86/linux-2.6-x86.git + sched-devel/latest .../mingo/linux-2.6-sched-devel.git Signed-off-by: Mike Travis --- v2: Renamed cpuset_scnprintf() to cpus_scnprintf to avoid confusion with "cpusets", and changed the other names to match. Added a sentinel character ('+') for the cpulist type output so scripts can be written to handle both cases. Added a warning in the Documentation/sysctl/kernel.txt that changing this option may break scripts and programs that rely on the current format. Also provided example on how to process the output. --- Documentation/sysctl/kernel.txt | 56 ++++++++++++++++++++++++++++++++++++++++ arch/x86/Kconfig | 4 ++ arch/x86/kernel/setup.c | 5 +++ include/linux/bitmap.h | 1 include/linux/cpumask.h | 35 ++++++++++++++++++++----- include/linux/nodemask.h | 31 ++++++++++++++++++++++ kernel/sysctl.c | 11 +++++++ lib/bitmap.c | 16 ----------- 8 files changed, 135 insertions(+), 24 deletions(-) --- linux-2.6.x86.orig/Documentation/sysctl/kernel.txt +++ linux-2.6.x86/Documentation/sysctl/kernel.txt @@ -18,6 +18,7 @@ Currently, these files might (depending show up in /proc/sys/kernel: - acpi_video_flags - acct +- compat_cpus_printf - core_pattern - core_uses_pid - ctrl-alt-del @@ -85,6 +86,61 @@ valid for 30 seconds. ============================================================== +compat_cpus_printf: + +compat_cpus_printf is used to alter the way cpumask_t cpu bits +are printed. To maintain compatibility with the current output +format, the default is '1'. + +** DO NOT CHANGE THIS ** if you run programs or scripts which may +rely on the current format until you are certain they can handle the +newer, more compact format. If you change the format, it will apply +to all programs that access common /proc and /sys interfaces. + +The current format results in the following print when the number +of cpus in a system is large. An example when NR_CPUS is 4096 and +compat_cpus_printf is '1': + + # cat /sys/devices/system/cpu/cpu92/cache/index2/shared_cpu_map + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,\ + 00000000,00000000,00000000,00000000,00000000,33000000,00000000,00000000 + +The same example when compat_cpus_printf = '0': + + # echo 0 > /proc/sys/kernel/compat_cpus_printf + # cat /sys/devices/system/cpu/cpu3/cache/index0/shared_cpu_map + +88-89,92-93 + +Note that when the "non-compatibile" (or "cpulist") format is specified, +a preceeding '+' is output. This allows user scripts and programs that +process the output to distinguish which format is present: + + if (buf[0] == '+') + bitmask_parselist(&buf[1], ...); + else + bitmask_parsehex(buf, ...); + +See libbitmask(3) for details on parsing the output. + +In addition to conversion of cpumask_t cpu bits, nodemask_t bits are +handled the same way. + +============================================================== + core_pattern: core_pattern is used to specify a core dumpfile pattern name. --- linux-2.6.x86.orig/arch/x86/Kconfig +++ linux-2.6.x86/arch/x86/Kconfig @@ -192,6 +192,10 @@ config X86_TRAMPOLINE depends on X86_SMP || (X86_VOYAGER && SMP) default y +config KERN_COMPAT_CPUS_PRINTF + bool + default X86_64_SMP + config KTIME_SCALAR def_bool X86_32 source "init/Kconfig" --- linux-2.6.x86.orig/arch/x86/kernel/setup.c +++ linux-2.6.x86/arch/x86/kernel/setup.c @@ -25,6 +25,11 @@ static void __init setup_nr_cpu_ids(void static inline void setup_nr_cpu_ids(void) { } #endif +#ifdef CONFIG_KERN_COMPAT_CPUS_PRINTF +/* select cpus_scnprintf output */ +int compat_cpus_printf = 1; +#endif + #if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_SMP) /* * Copy data used in early init routines from the initial arrays to the --- linux-2.6.x86.orig/include/linux/bitmap.h +++ linux-2.6.x86/include/linux/bitmap.h @@ -108,7 +108,6 @@ extern int __bitmap_weight(const unsigne extern int bitmap_scnprintf(char *buf, unsigned int len, const unsigned long *src, int nbits); -extern int bitmap_scnprintf_len(unsigned int len); 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, --- linux-2.6.x86.orig/include/linux/cpumask.h +++ linux-2.6.x86/include/linux/cpumask.h @@ -14,6 +14,8 @@ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c * For details of cpus_remap(), see bitmap_remap in lib/bitmap.c. + * For details of cpus_scnprintf(), see compat_cpus_printf in + * Documentation/sysctl/kernel.txt. * * The available cpumask operations are: * @@ -52,6 +54,9 @@ * int cpumask_parse_user(ubuf, ulen, mask) Parse ascii string as cpumask * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing * int cpulist_parse(buf, map) Parse ascii string as cpulist + * int cpus_scnprintf(buf, len, mask) Format cpumask with either + * cpumask_scnprintf or cpulist_scnprintf + * based on the value of compat_cpus_printf * int cpu_remap(oldbit, old, new) newbit = map(old, new)(oldbit) * int cpus_remap(dst, src, old, new) *dst = map(old, new)(src) * @@ -285,13 +290,6 @@ static inline int __cpumask_scnprintf(ch return bitmap_scnprintf(buf, len, srcp->bits, nbits); } -#define cpumask_scnprintf_len(len) \ - __cpumask_scnprintf_len((len)) -static inline int __cpumask_scnprintf_len(int len) -{ - return bitmap_scnprintf_len(len); -} - #define cpumask_parse_user(ubuf, ulen, dst) \ __cpumask_parse_user((ubuf), (ulen), &(dst), NR_CPUS) static inline int __cpumask_parse_user(const char __user *buf, int len, @@ -314,6 +312,29 @@ static inline int __cpulist_parse(const return bitmap_parselist(buf, dstp->bits, nbits); } +#ifdef CONFIG_KERN_COMPAT_CPUS_PRINTF +#define cpus_scnprintf(buf, len, src) __cpus_scnprintf((buf), (len), &(src)) +static inline int __cpus_scnprintf(char *buf, int len, const cpumask_t *srcp) +{ + extern int compat_cpus_printf; + + if (compat_cpus_printf) + return __cpumask_scnprintf(buf, len, srcp, NR_CPUS); + else { + int n = 0; + if (len > 1) { + *buf++ = '+'; + *buf = '\0'; + n = __cpulist_scnprintf(buf, len-1, srcp, NR_CPUS); + n++; + } + return n; + } +} +#else +#define cpus_scnprintf(buf, len, src) cpumask_scnprintf(buf, len, src) +#endif + #define cpu_remap(oldbit, old, new) \ __cpu_remap((oldbit), &(old), &(new), NR_CPUS) static inline int __cpu_remap(int oldbit, --- linux-2.6.x86.orig/include/linux/nodemask.h +++ linux-2.6.x86/include/linux/nodemask.h @@ -14,6 +14,8 @@ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c. * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c. * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c. + * For details of nodes_scnprintf(), see compat_cpus_printf in + * Documentation/sysctl/kernel.txt. * * The available nodemask operations are: * @@ -54,6 +56,9 @@ * int nodemask_parse_user(ubuf, ulen, mask) Parse ascii string as nodemask * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing * int nodelist_parse(buf, map) Parse ascii string as nodelist + * int nodes_scnprintf(buf, len, mask) Format nodemask with either + * nodemask_scnprintf or nodelist_scnprintf + * based on the value of compat_cpus_printf * int node_remap(oldbit, old, new) newbit = map(old, new)(oldbit) * int nodes_remap(dst, src, old, new) *dst = map(old, new)(dst) * @@ -310,6 +315,32 @@ static inline int __nodelist_parse(const return bitmap_parselist(buf, dstp->bits, nbits); } +#ifdef CONFIG_KERN_COMPAT_CPUS_PRINTF +#define nodes_scnprintf(buf, len, src) \ + __nodes_scnprintf((buf), (len), &(src)) +static inline int __nodes_scnprintf(char *buf, int len, const nodemask_t *srcp) +{ + extern int compat_cpus_printf; + + if (compat_cpus_printf) + return __nodemask_scnprintf(buf, len, srcp, MAX_NUMNODES); + else { + int n = 0; + if (len > 1) { + *buf++ = '+'; + *buf = '\0'; + n = __nodelist_scnprintf(buf, len-1, srcp, + MAX_NUMNODES); + n++; + } + return n; + } +} +#else +#define nodes_scnprintf(buf, len, src) nodemask_scnprintf(buf, len, src) +#endif + + #define node_remap(oldbit, old, new) \ __node_remap((oldbit), &(old), &(new), MAX_NUMNODES) static inline int __node_remap(int oldbit, --- linux-2.6.x86.orig/kernel/sysctl.c +++ linux-2.6.x86/kernel/sysctl.c @@ -82,6 +82,7 @@ extern int compat_log; extern int maps_protect; extern int sysctl_stat_interval; extern int latencytop_enabled; +extern int compat_cpus_printf; /* Constants used for minimum and maximum */ #if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) @@ -831,6 +832,16 @@ static struct ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif +#ifdef CONFIG_KERN_COMPAT_CPUS_PRINTF + { + .ctl_name = CTL_UNNUMBERED, + .procname = "compat_cpus_printf", + .data = &compat_cpus_printf, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif /* * NOTE: do not add new entries to this table unless you have read --- linux-2.6.x86.orig/lib/bitmap.c +++ linux-2.6.x86/lib/bitmap.c @@ -316,22 +316,6 @@ int bitmap_scnprintf(char *buf, unsigned EXPORT_SYMBOL(bitmap_scnprintf); /** - * bitmap_scnprintf_len - return buffer length needed to convert - * bitmap to an ASCII hex string. - * @len: number of bits to be converted - */ -int bitmap_scnprintf_len(unsigned int len) -{ - /* we need 9 chars per word for 32 bit words (8 hexdigits + sep/null) */ - int bitslen = ALIGN(len, CHUNKSZ); - int wordlen = CHUNKSZ / 4; - int buflen = (bitslen / wordlen) * (wordlen + 1) * sizeof(char); - - return buflen; -} -EXPORT_SYMBOL(bitmap_scnprintf_len); - -/** * __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 -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/