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:  |