From 7b4967c532045a1983d6d4af5c69cc7c5109f62b Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Fri, 19 Dec 2008 16:56:37 +1030 Subject: cpumask: Add alloc_cpumask_var_node() Impact: New API This will be needed in x86 code to allocate the domain and old_domain cpumasks on the same node as where the containing irq_cfg struct is allocated. (Also fixes double-dump_stack on rare CONFIG_DEBUG_PER_CPU_MAPS case) Signed-off-by: Mike Travis Signed-off-by: Rusty Russell (re-impl alloc_cpumask_var) --- lib/cpumask.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/cpumask.c b/lib/cpumask.c index 8d03f22c6ced..3f258f58c85b 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -76,15 +76,14 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu) /* These are not inline because of header tangles. */ #ifdef CONFIG_CPUMASK_OFFSTACK -bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) +bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) { if (likely(slab_is_available())) - *mask = kmalloc(cpumask_size(), flags); + *mask = kmalloc_node(cpumask_size(), flags, node); else { #ifdef CONFIG_DEBUG_PER_CPU_MAPS printk(KERN_ERR "=> alloc_cpumask_var: kmalloc not available!\n"); - dump_stack(); #endif *mask = NULL; } @@ -96,6 +95,12 @@ bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) #endif return *mask != NULL; } +EXPORT_SYMBOL(alloc_cpumask_var_node); + +bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) +{ + return alloc_cpumask_var_node(mask, flags, numa_node_id()); +} EXPORT_SYMBOL(alloc_cpumask_var); void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask) -- cgit v1.2.3-59-g8ed1b From ec26b805879c7e77865b39ee91b737985e80006d Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Fri, 19 Dec 2008 16:56:52 +1030 Subject: cpumask: documentation for cpumask_var_t Impact: New kerneldoc comments Additional documentation added to all the alloc_cpumask and free_cpumask functions. Signed-off-by: Mike Travis Signed-off-by: Rusty Russell (minor additions) --- lib/cpumask.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'lib') diff --git a/lib/cpumask.c b/lib/cpumask.c index 3f258f58c85b..a24edf137f41 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -76,6 +76,20 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu) /* These are not inline because of header tangles. */ #ifdef CONFIG_CPUMASK_OFFSTACK +/** + * alloc_cpumask_var_node - allocate a struct cpumask on a given node + * @mask: pointer to cpumask_var_t where the cpumask is returned + * @flags: GFP_ flags + * + * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is + * a nop returning a constant 1 (in ) + * Returns TRUE if memory allocation succeeded, FALSE otherwise. + * + * In addition, mask will be NULL if this fails. Note that gcc is + * usually smart enough to know that mask can never be NULL if + * CONFIG_CPUMASK_OFFSTACK=n, so does code elimination in that case + * too. + */ bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) { if (likely(slab_is_available())) @@ -97,23 +111,52 @@ bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) } EXPORT_SYMBOL(alloc_cpumask_var_node); +/** + * alloc_cpumask_var - allocate a struct cpumask + * @mask: pointer to cpumask_var_t where the cpumask is returned + * @flags: GFP_ flags + * + * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is + * a nop returning a constant 1 (in ). + * + * See alloc_cpumask_var_node. + */ bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) { return alloc_cpumask_var_node(mask, flags, numa_node_id()); } EXPORT_SYMBOL(alloc_cpumask_var); +/** + * alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena. + * @mask: pointer to cpumask_var_t where the cpumask is returned + * + * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is + * a nop returning a constant 1 (in ) + * Either returns an allocated (zero-filled) cpumask, or causes the + * system to panic. + */ void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask) { *mask = alloc_bootmem(cpumask_size()); } +/** + * free_cpumask_var - frees memory allocated for a struct cpumask. + * @mask: cpumask to free + * + * This is safe on a NULL mask. + */ void free_cpumask_var(cpumask_var_t mask) { kfree(mask); } EXPORT_SYMBOL(free_cpumask_var); +/** + * free_bootmem_cpumask_var - frees result of alloc_bootmem_cpumask_var + * @mask: cpumask to free + */ void __init free_bootmem_cpumask_var(cpumask_var_t mask) { free_bootmem((unsigned long)mask, cpumask_size()); -- cgit v1.2.3-59-g8ed1b From e9690a6e4b1615cb0102e425e04b7ce29e7858e2 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Dec 2008 16:45:50 +0800 Subject: cpumask: fix bogus kernel-doc Impact: fix kernel-doc alloc_bootmem_cpumask_var() returns avoid. Signed-off-by: Li Zefan Signed-off-by: Rusty Russell --- lib/cpumask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/cpumask.c b/lib/cpumask.c index a24edf137f41..8e1496cb63f7 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL(alloc_cpumask_var); * @mask: pointer to cpumask_var_t where the cpumask is returned * * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is - * a nop returning a constant 1 (in ) + * a nop (in ). * Either returns an allocated (zero-filled) cpumask, or causes the * system to panic. */ -- cgit v1.2.3-59-g8ed1b From ab53d472e785e51fdfc08fc1d66252c1153e6c0f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 1 Jan 2009 10:12:19 +1030 Subject: bitmap: find_last_bit() Impact: New API As the name suggests. For the moment everyone uses the generic one. Signed-off-by: Rusty Russell --- include/linux/bitops.h | 13 ++++++++++++- lib/Kconfig | 4 ++++ lib/Makefile | 1 + lib/find_last_bit.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 lib/find_last_bit.c (limited to 'lib') diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 024f2b027244..61829139795a 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -134,9 +134,20 @@ extern unsigned long find_first_bit(const unsigned long *addr, */ extern unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); - #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ +#ifdef CONFIG_GENERIC_FIND_LAST_BIT +/** + * find_last_bit - find the last set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit number of the first set bit, or size. + */ +extern unsigned long find_last_bit(const unsigned long *addr, + unsigned long size); +#endif /* CONFIG_GENERIC_FIND_LAST_BIT */ + #ifdef CONFIG_GENERIC_FIND_NEXT_BIT /** diff --git a/lib/Kconfig b/lib/Kconfig index 2ba43c4a5b07..fc5f5ee50bc2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -13,6 +13,10 @@ config GENERIC_FIND_FIRST_BIT config GENERIC_FIND_NEXT_BIT bool +config GENERIC_FIND_LAST_BIT + bool + default y + config CRC_CCITT tristate "CRC-CCITT functions" help diff --git a/lib/Makefile b/lib/Makefile index 80fe8a3ec12a..32b0e64ded27 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -37,6 +37,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o +lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o obj-$(CONFIG_PLIST) += plist.o diff --git a/lib/find_last_bit.c b/lib/find_last_bit.c new file mode 100644 index 000000000000..5d202e36bdd8 --- /dev/null +++ b/lib/find_last_bit.c @@ -0,0 +1,45 @@ +/* find_last_bit.c: fallback find next bit implementation + * + * Copyright (C) 2008 IBM Corporation + * Written by Rusty Russell + * (Inspired by David Howell's find_next_bit implementation) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +unsigned long find_last_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long words; + unsigned long tmp; + + /* Start at final word. */ + words = size / BITS_PER_LONG; + + /* Partial final word? */ + if (size & (BITS_PER_LONG-1)) { + tmp = (addr[words] & (~0UL >> (BITS_PER_LONG + - (size & (BITS_PER_LONG-1))))); + if (tmp) + goto found; + } + + while (words) { + tmp = addr[--words]; + if (tmp) { +found: + return words * BITS_PER_LONG + __fls(tmp); + } + } + + /* Not found */ + return size; +} +EXPORT_SYMBOL(find_last_bit); -- cgit v1.2.3-59-g8ed1b From 2a53008033189ed09bfe241c6b33811ba4ce980d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 1 Jan 2009 10:12:30 +1030 Subject: cpumask: zero extra bits in alloc_cpumask_var_node Impact: extra safety checks during transition When CONFIG_CPUMASKS_OFFSTACK is set, the new cpumask_ operators only use bits up to nr_cpu_ids, not NR_CPUS. Using the old cpus_ operators on these masks can mean accessing undefined bits. After some discussion, Mike and I decided to err on the side of caution; we zero the "undefined" bits in alloc_cpumask_var_node() until all the old cpumask functions are removed. Signed-off-by: Rusty Russell --- lib/cpumask.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/cpumask.c b/lib/cpumask.c index 8e1496cb63f7..3389e2440da0 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -107,6 +107,14 @@ bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) dump_stack(); } #endif + /* FIXME: Bandaid to save us from old primitives which go to NR_CPUS. */ + if (*mask) { + unsigned int tail; + tail = BITS_TO_LONGS(NR_CPUS - nr_cpumask_bits) * sizeof(long); + memset(cpumask_bits(*mask) + cpumask_size() - tail, + 0, tail); + } + return *mask != NULL; } EXPORT_SYMBOL(alloc_cpumask_var_node); -- cgit v1.2.3-59-g8ed1b From 8c384cdee3e04d6194a2c2b192b624754f990835 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 1 Jan 2009 10:12:30 +1030 Subject: cpumask: CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS Impact: new debug CONFIG options This helps find unconverted code. It currently breaks compile horribly, but we never wanted a flag day so that's expected. Signed-off-by: Rusty Russell --- include/linux/cpumask.h | 11 ++++++++++- lib/Kconfig | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 7c178a6baae3..9f315382610b 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -144,6 +144,7 @@ typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; extern cpumask_t _unused_cpumask_arg_; +#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS #define cpu_set(cpu, dst) __cpu_set((cpu), &(dst)) static inline void __cpu_set(int cpu, volatile cpumask_t *dstp) { @@ -267,6 +268,7 @@ static inline void __cpus_shift_left(cpumask_t *dstp, { bitmap_shift_left(dstp->bits, srcp->bits, n, nbits); } +#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */ /** * to_cpumask - convert an NR_CPUS bitmap to a struct cpumask * @@ -304,6 +306,7 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu) return to_cpumask(p); } +#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS /* * In cases where we take the address of the cpumask immediately, * gcc optimizes it out (it's a constant) and there's no huge stack @@ -389,19 +392,22 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp, { bitmap_fold(dstp->bits, origp->bits, sz, nbits); } +#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */ #if NR_CPUS == 1 #define nr_cpu_ids 1 +#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS #define first_cpu(src) ({ (void)(src); 0; }) #define next_cpu(n, src) ({ (void)(src); 1; }) #define any_online_cpu(mask) 0 #define for_each_cpu_mask(cpu, mask) \ for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) - +#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */ #else /* NR_CPUS > 1 */ extern int nr_cpu_ids; +#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS int __first_cpu(const cpumask_t *srcp); int __next_cpu(int n, const cpumask_t *srcp); int __any_online_cpu(const cpumask_t *mask); @@ -413,8 +419,10 @@ int __any_online_cpu(const cpumask_t *mask); for ((cpu) = -1; \ (cpu) = next_cpu((cpu), (mask)), \ (cpu) < NR_CPUS; ) +#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */ #endif +#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS #if NR_CPUS <= 64 #define next_cpu_nr(n, src) next_cpu(n, src) @@ -432,6 +440,7 @@ int __next_cpu_nr(int n, const cpumask_t *srcp); (cpu) < nr_cpu_ids; ) #endif /* NR_CPUS > 64 */ +#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */ /* * The following particular system cpumasks and operations manage diff --git a/lib/Kconfig b/lib/Kconfig index fc5f5ee50bc2..03c2c24b9083 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -170,4 +170,8 @@ config CPUMASK_OFFSTACK them on the stack. This is a bit more expensive, but avoids stack overflow. +config DISABLE_OBSOLETE_CPUMASK_FUNCTIONS + bool "Disable obsolete cpumask functions" if DEBUG_PER_CPU_MAPS + depends on EXPERIMENTAL && BROKEN + endmenu -- cgit v1.2.3-59-g8ed1b From d97106ab53f812910a62d18afb9dbe882819c1ba Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 3 Jan 2009 11:46:17 -0800 Subject: Make %p print '(null)' for NULL pointers Before, when we only ever printed out the pointer value itself, a NULL pointer would never cause issues and might as well be printed out as just its numeric value. However, with the extended %p formats, especially %pR, we might validly want to print out resources for debugging. And sometimes they don't even exist, and the resource pointer is just NULL. Print it out as such, rather than oopsing. This is a more generic version of a patch done by Trent Piepho (catching all %p cases rather than just %pR, and using "(null)" instead of "[NULL]" to match glibc). Requested-by: Trent Piepho Acked-by: Harvey Harrison Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b777025d876..98d632277ca8 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -661,6 +661,9 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, */ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) { + if (!ptr) + return string(buf, end, "(null)", field_width, precision, flags); + switch (*fmt) { case 'F': ptr = dereference_function_descriptor(ptr); -- cgit v1.2.3-59-g8ed1b