diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 5 | ||||
-rw-r--r-- | lib/bitmap.c | 10 | ||||
-rw-r--r-- | lib/idr.c | 15 | ||||
-rw-r--r-- | lib/kstrtox.c | 75 | ||||
-rw-r--r-- | lib/kstrtox.h | 8 | ||||
-rw-r--r-- | lib/percpu_counter.c | 2 | ||||
-rw-r--r-- | lib/radix-tree.c | 10 | ||||
-rw-r--r-- | lib/spinlock_debug.c | 19 | ||||
-rw-r--r-- | lib/string.c | 57 | ||||
-rw-r--r-- | lib/vsprintf.c | 47 |
10 files changed, 162 insertions, 86 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c583a57cddf..82928f5ea04 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -248,8 +248,9 @@ config DEFAULT_HUNG_TASK_TIMEOUT to determine when a task has become non-responsive and should be considered hung. - It can be adjusted at runtime via the kernel.hung_task_timeout - sysctl or by writing a value to /proc/sys/kernel/hung_task_timeout. + It can be adjusted at runtime via the kernel.hung_task_timeout_secs + sysctl or by writing a value to + /proc/sys/kernel/hung_task_timeout_secs. A timeout of 0 disables the check. The default is two minutes. Keeping the default should be fine in most cases. diff --git a/lib/bitmap.c b/lib/bitmap.c index 2f4412e4d07..0d4a127dd9b 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -419,7 +419,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen, { int c, old_c, totaldigits, ndigits, nchunks, nbits; u32 chunk; - const char __user *ubuf = buf; + const char __user __force *ubuf = (const char __user __force *)buf; bitmap_zero(maskp, nmaskbits); @@ -504,7 +504,9 @@ int bitmap_parse_user(const char __user *ubuf, { if (!access_ok(VERIFY_READ, ubuf, ulen)) return -EFAULT; - return __bitmap_parse((const char *)ubuf, ulen, 1, maskp, nmaskbits); + return __bitmap_parse((const char __force *)ubuf, + ulen, 1, maskp, nmaskbits); + } EXPORT_SYMBOL(bitmap_parse_user); @@ -594,7 +596,7 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, { unsigned a, b; int c, old_c, totaldigits; - const char __user *ubuf = buf; + const char __user __force *ubuf = (const char __user __force *)buf; int exp_digit, in_range; totaldigits = c = 0; @@ -694,7 +696,7 @@ int bitmap_parselist_user(const char __user *ubuf, { if (!access_ok(VERIFY_READ, ubuf, ulen)) return -EFAULT; - return __bitmap_parselist((const char *)ubuf, + return __bitmap_parselist((const char __force *)ubuf, ulen, 1, maskp, nmaskbits); } EXPORT_SYMBOL(bitmap_parselist_user); diff --git a/lib/idr.c b/lib/idr.c index 5acf9bb1096..ed055b297c8 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -767,8 +767,8 @@ EXPORT_SYMBOL(ida_pre_get); * @starting_id: id to start search at * @p_id: pointer to the allocated handle * - * Allocate new ID above or equal to @ida. It should be called with - * any required locks. + * Allocate new ID above or equal to @starting_id. It should be called + * with any required locks. * * If memory is required, it will return %-EAGAIN, you should unlock * and go back to the ida_pre_get() call. If the ida is full, it will @@ -944,6 +944,7 @@ int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, { int ret, id; unsigned int max; + unsigned long flags; BUG_ON((int)start < 0); BUG_ON((int)end < 0); @@ -959,7 +960,7 @@ again: if (!ida_pre_get(ida, gfp_mask)) return -ENOMEM; - spin_lock(&simple_ida_lock); + spin_lock_irqsave(&simple_ida_lock, flags); ret = ida_get_new_above(ida, start, &id); if (!ret) { if (id > max) { @@ -969,7 +970,7 @@ again: ret = id; } } - spin_unlock(&simple_ida_lock); + spin_unlock_irqrestore(&simple_ida_lock, flags); if (unlikely(ret == -EAGAIN)) goto again; @@ -985,10 +986,12 @@ EXPORT_SYMBOL(ida_simple_get); */ void ida_simple_remove(struct ida *ida, unsigned int id) { + unsigned long flags; + BUG_ON((int)id < 0); - spin_lock(&simple_ida_lock); + spin_lock_irqsave(&simple_ida_lock, flags); ida_remove(ida, id); - spin_unlock(&simple_ida_lock); + spin_unlock_irqrestore(&simple_ida_lock, flags); } EXPORT_SYMBOL(ida_simple_remove); diff --git a/lib/kstrtox.c b/lib/kstrtox.c index 5e066759f55..7a94c8f14e2 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -18,26 +18,40 @@ #include <linux/module.h> #include <linux/types.h> #include <asm/uaccess.h> +#include "kstrtox.h" -static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) +const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) { - unsigned long long acc; - int ok; - - if (base == 0) { + if (*base == 0) { if (s[0] == '0') { if (_tolower(s[1]) == 'x' && isxdigit(s[2])) - base = 16; + *base = 16; else - base = 8; + *base = 8; } else - base = 10; + *base = 10; } - if (base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') + if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') s += 2; + return s; +} - acc = 0; - ok = 0; +/* + * Convert non-negative integer string representation in explicitly given radix + * to an integer. + * Return number of characters consumed maybe or-ed with overflow bit. + * If overflow occurs, result integer (incorrect) is still returned. + * + * Don't you dare use this function. + */ +unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res) +{ + unsigned int rv; + int overflow; + + *res = 0; + rv = 0; + overflow = 0; while (*s) { unsigned int val; @@ -45,23 +59,40 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) val = *s - '0'; else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f') val = _tolower(*s) - 'a' + 10; - else if (*s == '\n' && *(s + 1) == '\0') - break; else - return -EINVAL; + break; if (val >= base) - return -EINVAL; - if (acc > div_u64(ULLONG_MAX - val, base)) - return -ERANGE; - acc = acc * base + val; - ok = 1; - + break; + if (*res > div_u64(ULLONG_MAX - val, base)) + overflow = 1; + *res = *res * base + val; + rv++; s++; } - if (!ok) + if (overflow) + rv |= KSTRTOX_OVERFLOW; + return rv; +} + +static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) +{ + unsigned long long _res; + unsigned int rv; + + s = _parse_integer_fixup_radix(s, &base); + rv = _parse_integer(s, base, &_res); + if (rv & KSTRTOX_OVERFLOW) + return -ERANGE; + rv &= ~KSTRTOX_OVERFLOW; + if (rv == 0) + return -EINVAL; + s += rv; + if (*s == '\n') + s++; + if (*s) return -EINVAL; - *res = acc; + *res = _res; return 0; } diff --git a/lib/kstrtox.h b/lib/kstrtox.h new file mode 100644 index 00000000000..f13eeeaf441 --- /dev/null +++ b/lib/kstrtox.h @@ -0,0 +1,8 @@ +#ifndef _LIB_KSTRTOX_H +#define _LIB_KSTRTOX_H + +#define KSTRTOX_OVERFLOW (1U << 31) +const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); +unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res); + +#endif diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index f087105ed91..f8a3f1a829b 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -10,8 +10,10 @@ #include <linux/module.h> #include <linux/debugobjects.h> +#ifdef CONFIG_HOTPLUG_CPU static LIST_HEAD(percpu_counters); static DEFINE_MUTEX(percpu_counters_lock); +#endif #ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER diff --git a/lib/radix-tree.c b/lib/radix-tree.c index a2f9da59c19..d9df7454519 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -576,7 +576,6 @@ int radix_tree_tag_get(struct radix_tree_root *root, { unsigned int height, shift; struct radix_tree_node *node; - int saw_unset_tag = 0; /* check the root's tag bit */ if (!root_tag_get(root, tag)) @@ -603,15 +602,10 @@ int radix_tree_tag_get(struct radix_tree_root *root, return 0; offset = (index >> shift) & RADIX_TREE_MAP_MASK; - - /* - * This is just a debug check. Later, we can bale as soon as - * we see an unset tag. - */ if (!tag_get(node, tag, offset)) - saw_unset_tag = 1; + return 0; if (height == 1) - return !!tag_get(node, tag, offset); + return 1; node = rcu_dereference_raw(node->slots[offset]); shift -= RADIX_TREE_MAP_SHIFT; height--; diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index 4755b98b6df..5f3eacdd617 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -49,13 +49,10 @@ void __rwlock_init(rwlock_t *lock, const char *name, EXPORT_SYMBOL(__rwlock_init); -static void spin_bug(raw_spinlock_t *lock, const char *msg) +static void spin_dump(raw_spinlock_t *lock, const char *msg) { struct task_struct *owner = NULL; - if (!debug_locks_off()) - return; - if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) owner = lock->owner; printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", @@ -70,6 +67,14 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg) dump_stack(); } +static void spin_bug(raw_spinlock_t *lock, const char *msg) +{ + if (!debug_locks_off()) + return; + + spin_dump(lock, msg); +} + #define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) static inline void @@ -113,11 +118,7 @@ static void __spin_lock_debug(raw_spinlock_t *lock) /* lockup suspected: */ if (print_once) { print_once = 0; - printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, " - "%s/%d, %p\n", - raw_smp_processor_id(), current->comm, - task_pid_nr(current), lock); - dump_stack(); + spin_dump(lock, "lockup"); #ifdef CONFIG_SMP trigger_all_cpu_backtrace(); #endif diff --git a/lib/string.c b/lib/string.c index 01fad9b203e..dc4a86341f9 100644 --- a/lib/string.c +++ b/lib/string.c @@ -360,7 +360,6 @@ char *strim(char *s) size_t size; char *end; - s = skip_spaces(s); size = strlen(s); if (!size) return s; @@ -370,7 +369,7 @@ char *strim(char *s) end--; *(end + 1) = '\0'; - return s; + return skip_spaces(s); } EXPORT_SYMBOL(strim); @@ -756,3 +755,57 @@ void *memchr(const void *s, int c, size_t n) } EXPORT_SYMBOL(memchr); #endif + +static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes) +{ + while (bytes) { + if (*start != value) + return (void *)start; + start++; + bytes--; + } + return NULL; +} + +/** + * memchr_inv - Find an unmatching character in an area of memory. + * @start: The memory area + * @c: Find a character other than c + * @bytes: The size of the area. + * + * returns the address of the first character other than @c, or %NULL + * if the whole buffer contains just @c. + */ +void *memchr_inv(const void *start, int c, size_t bytes) +{ + u8 value = c; + u64 value64; + unsigned int words, prefix; + + if (bytes <= 16) + return check_bytes8(start, value, bytes); + + value64 = value | value << 8 | value << 16 | value << 24; + value64 = (value64 & 0xffffffff) | value64 << 32; + prefix = 8 - ((unsigned long)start) % 8; + + if (prefix) { + u8 *r = check_bytes8(start, value, prefix); + if (r) + return r; + start += prefix; + bytes -= prefix; + } + + words = bytes / 8; + + while (words) { + if (*(u64 *)start != value64) + return check_bytes8(start, value, 8); + start += 8; + words--; + } + + return check_bytes8(start, value, bytes % 8); +} +EXPORT_SYMBOL(memchr_inv); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7222a9c826..993599e66e5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -31,17 +31,7 @@ #include <asm/div64.h> #include <asm/sections.h> /* for dereference_function_descriptor() */ -static unsigned int simple_guess_base(const char *cp) -{ - if (cp[0] == '0') { - if (_tolower(cp[1]) == 'x' && isxdigit(cp[2])) - return 16; - else - return 8; - } else { - return 10; - } -} +#include "kstrtox.h" /** * simple_strtoull - convert a string to an unsigned long long @@ -51,23 +41,14 @@ static unsigned int simple_guess_base(const char *cp) */ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { - unsigned long long result = 0; + unsigned long long result; + unsigned int rv; - if (!base) - base = simple_guess_base(cp); + cp = _parse_integer_fixup_radix(cp, &base); + rv = _parse_integer(cp, base, &result); + /* FIXME */ + cp += (rv & ~KSTRTOX_OVERFLOW); - if (base == 16 && cp[0] == '0' && _tolower(cp[1]) == 'x') - cp += 2; - - while (isxdigit(*cp)) { - unsigned int value; - - value = isdigit(*cp) ? *cp - '0' : _tolower(*cp) - 'a' + 10; - if (value >= base) - break; - result = result * base + value; - cp++; - } if (endp) *endp = (char *)cp; @@ -566,7 +547,7 @@ char *mac_address_string(char *buf, char *end, u8 *addr, } for (i = 0; i < 6; i++) { - p = pack_hex_byte(p, addr[i]); + p = hex_byte_pack(p, addr[i]); if (fmt[0] == 'M' && i != 5) *p++ = separator; } @@ -686,13 +667,13 @@ char *ip6_compressed_string(char *p, const char *addr) lo = word & 0xff; if (hi) { if (hi > 0x0f) - p = pack_hex_byte(p, hi); + p = hex_byte_pack(p, hi); else *p++ = hex_asc_lo(hi); - p = pack_hex_byte(p, lo); + p = hex_byte_pack(p, lo); } else if (lo > 0x0f) - p = pack_hex_byte(p, lo); + p = hex_byte_pack(p, lo); else *p++ = hex_asc_lo(lo); needcolon = true; @@ -714,8 +695,8 @@ char *ip6_string(char *p, const char *addr, const char *fmt) int i; for (i = 0; i < 8; i++) { - p = pack_hex_byte(p, *addr++); - p = pack_hex_byte(p, *addr++); + p = hex_byte_pack(p, *addr++); + p = hex_byte_pack(p, *addr++); if (fmt[0] == 'I' && i != 7) *p++ = ':'; } @@ -773,7 +754,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, } for (i = 0; i < 16; i++) { - p = pack_hex_byte(p, addr[index[i]]); + p = hex_byte_pack(p, addr[index[i]]); switch (i) { case 3: case 5: |