[PATCH 32/35] cpumask: debug options for cpumasks From: Rusty Russell <rusty@rustcorp.com.au>

From: Mike Travis
Date: Wed Oct 22 2008 - 22:17:42 EST


It's useful to check that no one is accessing > nr_cpumask_bits for
cpumasks. This also allows you to turn on CONFIG_CPUMASKS_OFFSTACK
even for smaller CONFIG_NR_CPUS.

Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Signed-off-by: Mike Travis <travis@xxxxxxx>
---
include/linux/cpumask.h | 23 +++++++++++++++++------
lib/Kconfig.debug | 6 ++++++
lib/cpumask.c | 3 +++
3 files changed, 26 insertions(+), 6 deletions(-)

--- linux-2.6.28.orig/include/linux/cpumask.h
+++ linux-2.6.28/include/linux/cpumask.h
@@ -250,23 +250,34 @@ extern cpumask_t _unused_cpumask_arg_;
#define cpu_mask_all (*(cpumask_t *)cpu_all_mask)
/* End deprecated region. */

+/* verify cpu argument to cpumask_* operators */
+static inline unsigned int cpumask_check(unsigned int cpu)
+{
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+ /* This breaks at runtime. */
+ BUG_ON(cpu >= nr_cpumask_bits);
+#endif /* CONFIG_DEBUG_PER_CPU_MAPS */
+ return cpu;
+}
+
/* cpumask_* operators */
static inline void cpumask_set_cpu(int cpu, volatile struct cpumask *dstp)
{
- set_bit(cpu, cpumask_bits(dstp));
+ set_bit(cpumask_check(cpu), cpumask_bits(dstp));
}

static inline void cpumask_clear_cpu(int cpu, volatile struct cpumask *dstp)
{
- clear_bit(cpu, cpumask_bits(dstp));
+ clear_bit(cpumask_check(cpu), cpumask_bits(dstp));
}

/* No static inline type checking - see Subtlety (1) above. */
-#define cpumask_test_cpu(cpu, cpumask) test_bit((cpu), (cpumask)->bits)
+#define cpumask_test_cpu(cpu, cpumask) \
+ test_bit(cpumask_check(cpu), (cpumask)->bits)

static inline int cpumask_test_and_set_cpu(int cpu, struct cpumask *addr)
{
- return test_and_set_bit(cpu, cpumask_bits(addr));
+ return test_and_set_bit(cpumask_check(cpu), cpumask_bits(addr));
}

static inline void cpumask_setall(struct cpumask *dstp)
@@ -400,8 +411,8 @@ static inline int cpumask_cpuremap(int o
const struct cpumask *oldp,
const struct cpumask *newp)
{
- return bitmap_bitremap(oldbit, cpumask_bits(oldp), cpumask_bits(newp),
- nr_cpumask_bits);
+ return bitmap_bitremap(cpumask_check(oldbit), cpumask_bits(oldp),
+ cpumask_bits(newp), nr_cpumask_bits);
}

static inline void cpumask_remap(struct cpumask *dstp,
--- linux-2.6.28.orig/lib/Kconfig.debug
+++ linux-2.6.28/lib/Kconfig.debug
@@ -784,6 +784,12 @@ config SYSCTL_SYSCALL_CHECK
to properly maintain and use. This enables checks that help
you to keep things correct.

+config DEBUG_PER_CPU_MAPS
+ bool "Cpumask debug checks"
+ ---help---
+ Extra debugging for cpumasks.
+ eg. to make sure accesses to cpumasks are < nr_cpu_ids.
+
source kernel/trace/Kconfig

config PROVIDE_OHCI1394_DMA_INIT
--- linux-2.6.28.orig/lib/cpumask.c
+++ linux-2.6.28/lib/cpumask.c
@@ -11,6 +11,9 @@ EXPORT_SYMBOL(cpumask_first);

int cpumask_next(int n, const cpumask_t *srcp)
{
+ /* -1 is a legal arg here. */
+ if (n != -1)
+ cpumask_check(n);
return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
}
EXPORT_SYMBOL(cpumask_next);

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/