From 396ada68acefc4f90cf1f05d4275913834af5d93 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 16 Apr 2015 12:43:10 -0700 Subject: alpha: forward declare struct pt_regs in processor.h Removal of exec domains uncovered this new warning. processor.h re-used struct pt_regs from personality.h which is now gone. ./arch/alpha/include/asm/processor.h:47:33: warning: 'struct pt_regs' declared inside parameter list [enabled by default] Signed-off-by: Richard Weinberger Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h index b4cf036..43a7559 100644 --- a/arch/alpha/include/asm/processor.h +++ b/arch/alpha/include/asm/processor.h @@ -44,6 +44,7 @@ struct task_struct; extern unsigned long thread_saved_pc(struct task_struct *); /* Do necessary setup to start up a newly executed thread. */ +struct pt_regs; extern void start_thread(struct pt_regs *, unsigned long, unsigned long); /* Free all resources held by a thread. */ -- cgit v0.10.2 From 2c57a0e233d72f8c2e2404560dcf0188ac3cf5d7 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 16 Apr 2015 12:43:13 -0700 Subject: lib: find_*_bit reimplementation This patchset does rework to find_bit function family to achieve better performance, and decrease size of text. All rework is done in patch 1. Patches 2 and 3 are about code moving and renaming. It was boot-tested on x86_64 and MIPS (big-endian) machines. Performance tests were ran on userspace with code like this: /* addr[] is filled from /dev/urandom */ start = clock(); while (ret < nbits) ret = find_next_bit(addr, nbits, ret + 1); end = clock(); printf("%ld\t", (unsigned long) end - start); On Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz measurements are: (for find_next_bit, nbits is 8M, for find_first_bit - 80K) find_next_bit: find_first_bit: new current new current 26932 43151 14777 14925 26947 43182 14521 15423 26507 43824 15053 14705 27329 43759 14473 14777 26895 43367 14847 15023 26990 43693 15103 15163 26775 43299 15067 15232 27282 42752 14544 15121 27504 43088 14644 14858 26761 43856 14699 15193 26692 43075 14781 14681 27137 42969 14451 15061 ... ... find_next_bit performance gain is 35-40%; find_first_bit - no measurable difference. On ARM machine, there is arch-specific implementation for find_bit. Thanks a lot to George Spelvin and Rasmus Villemoes for hints and helpful discussions. This patch (of 3): New implementations takes less space in source file (see diffstat) and in object. For me it's 710 vs 453 bytes of text. It also shows better performance. find_last_bit description fixed due to obvious typo. [akpm@linux-foundation.org: include linux/bitmap.h, per Rasmus] Signed-off-by: Yury Norov Reviewed-by: Rasmus Villemoes Reviewed-by: George Spelvin Cc: Alexey Klimov Cc: David S. Miller Cc: Daniel Borkmann Cc: Hannes Frederic Sowa Cc: Lai Jiangshan Cc: Mark Salter Cc: AKASHI Takahiro Cc: Thomas Graf Cc: Valentin Rothberg Cc: Chris Wilson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 5d858e0..297f5bd 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -218,9 +218,9 @@ static inline unsigned long __ffs64(u64 word) /** * 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 + * @size: The number of bits to search * - * Returns the bit number of the first set bit, or size. + * Returns the bit number of the last set bit, or size. */ extern unsigned long find_last_bit(const unsigned long *addr, unsigned long size); diff --git a/lib/find_last_bit.c b/lib/find_last_bit.c index 91ca09f..3e3be40 100644 --- a/lib/find_last_bit.c +++ b/lib/find_last_bit.c @@ -4,6 +4,9 @@ * Written by Rusty Russell * (Inspired by David Howell's find_next_bit implementation) * + * Rewritten by Yury Norov to decrease + * size and improve performance, 2015. + * * 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 @@ -11,37 +14,26 @@ */ #include +#include #include -#include -#include +#include #ifndef find_last_bit 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; + if (size) { + unsigned long val = BITMAP_LAST_WORD_MASK(size); + unsigned long idx = (size-1) / 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; - } + do { + val &= addr[idx]; + if (val) + return idx * BITS_PER_LONG + __fls(val); - while (words) { - tmp = addr[--words]; - if (tmp) { -found: - return words * BITS_PER_LONG + __fls(tmp); - } + val = ~0ul; + } while (idx--); } - - /* Not found */ return size; } EXPORT_SYMBOL(find_last_bit); diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c index 0cbfc0b..cbea5ef 100644 --- a/lib/find_next_bit.c +++ b/lib/find_next_bit.c @@ -3,6 +3,9 @@ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * + * Rewritten by Yury Norov to decrease + * size and improve performance, 2015. + * * 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 @@ -11,98 +14,58 @@ #include #include -#include -#include +#include -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) +#if !defined(find_next_bit) || !defined(find_next_zero_bit) -#ifndef find_next_bit /* - * Find the next set bit in a memory region. + * This is a common helper function for find_next_bit and + * find_next_zero_bit. The difference is the "invert" argument, which + * is XORed with each fetched word before searching it for one bits. */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) +static unsigned long _find_next_bit(const unsigned long *addr, + unsigned long nbits, unsigned long start, unsigned long invert) { - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + + /* Handle 1st word. */ + tmp &= BITMAP_FIRST_WORD_MASK(start); + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; } - if (!size) - return result; - tmp = *p; -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); + return min(start + __ffs(tmp), nbits); } -EXPORT_SYMBOL(find_next_bit); #endif -#ifndef find_next_zero_bit +#ifndef find_next_bit /* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. + * Find the next set bit in a memory region. */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, size, offset, 0UL); +} +EXPORT_SYMBOL(find_next_bit); +#endif + +#ifndef find_next_zero_bit unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (BITS_PER_LONG - offset); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if (~(tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); + return _find_next_bit(addr, size, offset, ~0UL); } EXPORT_SYMBOL(find_next_zero_bit); #endif @@ -113,24 +76,14 @@ EXPORT_SYMBOL(find_next_zero_bit); */ unsigned long find_first_bit(const unsigned long *addr, unsigned long size) { - const unsigned long *p = addr; - unsigned long result = 0; - unsigned long tmp; + unsigned long idx; - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx]) + return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); } - if (!size) - return result; - tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found: - return result + __ffs(tmp); + return size; } EXPORT_SYMBOL(find_first_bit); #endif @@ -141,24 +94,14 @@ EXPORT_SYMBOL(find_first_bit); */ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) { - const unsigned long *p = addr; - unsigned long result = 0; - unsigned long tmp; + unsigned long idx; - while (size & ~(BITS_PER_LONG-1)) { - if (~(tmp = *(p++))) - goto found; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx] != ~0UL) + return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); } - if (!size) - return result; - tmp = (*p) | (~0UL << size); - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found: - return result + ffz(tmp); + return size; } EXPORT_SYMBOL(find_first_zero_bit); #endif @@ -166,18 +109,6 @@ EXPORT_SYMBOL(find_first_zero_bit); #ifdef __BIG_ENDIAN /* include/linux/byteorder does not support "unsigned long" type */ -static inline unsigned long ext2_swabp(const unsigned long * x) -{ -#if BITS_PER_LONG == 64 - return (unsigned long) __swab64p((u64 *) x); -#elif BITS_PER_LONG == 32 - return (unsigned long) __swab32p((u32 *) x); -#else -#error BITS_PER_LONG not defined -#endif -} - -/* include/linux/byteorder doesn't support "unsigned long" type */ static inline unsigned long ext2_swab(const unsigned long y) { #if BITS_PER_LONG == 64 @@ -189,48 +120,38 @@ static inline unsigned long ext2_swab(const unsigned long y) #endif } -#ifndef find_next_zero_bit_le -unsigned long find_next_zero_bit_le(const void *addr, unsigned - long size, unsigned long offset) +#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) +static unsigned long _find_next_bit_le(const unsigned long *addr, + unsigned long nbits, unsigned long start, unsigned long invert) { - const unsigned long *p = addr; - unsigned long result = offset & ~(BITS_PER_LONG - 1); unsigned long tmp; - if (offset >= size) - return size; - p += BITOP_WORD(offset); - size -= result; - offset &= (BITS_PER_LONG - 1UL); - if (offset) { - tmp = ext2_swabp(p++); - tmp |= (~0UL >> (BITS_PER_LONG - offset)); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + + /* Handle 1st word. */ + tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); + start = round_down(start, BITS_PER_LONG); - while (size & ~(BITS_PER_LONG - 1)) { - if (~(tmp = *(p++))) - goto found_middle_swap; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; } - if (!size) - return result; - tmp = ext2_swabp(p); -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. Skip ffz */ -found_middle: - return result + ffz(tmp); -found_middle_swap: - return result + ffz(ext2_swab(tmp)); + return min(start + __ffs(ext2_swab(tmp)), nbits); +} +#endif + +#ifndef find_next_zero_bit_le +unsigned long find_next_zero_bit_le(const void *addr, unsigned + long size, unsigned long offset) +{ + return _find_next_bit_le(addr, size, offset, ~0UL); } EXPORT_SYMBOL(find_next_zero_bit_le); #endif @@ -239,45 +160,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le); unsigned long find_next_bit_le(const void *addr, unsigned long size, unsigned long offset) { - const unsigned long *p = addr; - unsigned long result = offset & ~(BITS_PER_LONG - 1); - unsigned long tmp; - - if (offset >= size) - return size; - p += BITOP_WORD(offset); - size -= result; - offset &= (BITS_PER_LONG - 1UL); - if (offset) { - tmp = ext2_swabp(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - - while (size & ~(BITS_PER_LONG - 1)) { - tmp = *(p++); - if (tmp) - goto found_middle_swap; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = ext2_swabp(p); -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); - -found_middle_swap: - return result + __ffs(ext2_swab(tmp)); + return _find_next_bit_le(addr, size, offset, 0UL); } EXPORT_SYMBOL(find_next_bit_le); #endif -- cgit v0.10.2 From 8f6f19dd5143aa59139deeb885a8ed5e2d937e21 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 16 Apr 2015 12:43:16 -0700 Subject: lib: move find_last_bit to lib/find_next_bit.c Currently all 'find_*_bit' family is located in lib/find_next_bit.c, except 'find_last_bit', which is in lib/find_last_bit.c. It seems, there's no major benefit to have it separated. Signed-off-by: Yury Norov Reviewed-by: Rasmus Villemoes Reviewed-by: George Spelvin Cc: Alexey Klimov Cc: David S. Miller Cc: Daniel Borkmann Cc: Hannes Frederic Sowa Cc: Lai Jiangshan Cc: Mark Salter Cc: AKASHI Takahiro Cc: Thomas Graf Cc: Valentin Rothberg Cc: Chris Wilson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/Makefile b/lib/Makefile index 58f74d2..05f8fa5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -25,7 +25,7 @@ obj-y += lockref.o obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ - bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \ + bsearch.o find_next_bit.o llist.o memweight.o kfifo.o \ percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o obj-y += string_helpers.o obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c index cbea5ef..18072ea 100644 --- a/lib/find_next_bit.c +++ b/lib/find_next_bit.c @@ -1,8 +1,12 @@ -/* find_next_bit.c: fallback find next bit implementation +/* bit search implementation * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * + * Copyright (C) 2008 IBM Corporation + * 'find_last_bit' is written by Rusty Russell + * (Inspired by David Howell's find_next_bit implementation) + * * Rewritten by Yury Norov to decrease * size and improve performance, 2015. * @@ -13,6 +17,7 @@ */ #include +#include #include #include @@ -106,6 +111,26 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) EXPORT_SYMBOL(find_first_zero_bit); #endif +#ifndef find_last_bit +unsigned long find_last_bit(const unsigned long *addr, unsigned long size) +{ + if (size) { + unsigned long val = BITMAP_LAST_WORD_MASK(size); + unsigned long idx = (size-1) / BITS_PER_LONG; + + do { + val &= addr[idx]; + if (val) + return idx * BITS_PER_LONG + __fls(val); + + val = ~0ul; + } while (idx--); + } + return size; +} +EXPORT_SYMBOL(find_last_bit); +#endif + #ifdef __BIG_ENDIAN /* include/linux/byteorder does not support "unsigned long" type */ -- cgit v0.10.2 From 840620a1596a90636a44d6a593db4041bb28d52e Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 16 Apr 2015 12:43:19 -0700 Subject: lib: rename lib/find_next_bit.c to lib/find_bit.c This file contains implementation for all find_*_bit{,_le} So giving it more generic name looks reasonable. Signed-off-by: Yury Norov Reviewed-by: Rasmus Villemoes Reviewed-by: George Spelvin Cc: Alexey Klimov Cc: David S. Miller Cc: Daniel Borkmann Cc: Hannes Frederic Sowa Cc: Lai Jiangshan Cc: Mark Salter Cc: AKASHI Takahiro Cc: Thomas Graf Cc: Valentin Rothberg Cc: Chris Wilson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/Makefile b/lib/Makefile index 05f8fa5..da6116b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -25,7 +25,7 @@ obj-y += lockref.o obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ - bsearch.o find_next_bit.o llist.o memweight.o kfifo.o \ + bsearch.o find_bit.o llist.o memweight.o kfifo.o \ percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o obj-y += string_helpers.o obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o diff --git a/lib/find_bit.c b/lib/find_bit.c new file mode 100644 index 0000000..18072ea --- /dev/null +++ b/lib/find_bit.c @@ -0,0 +1,193 @@ +/* bit search implementation + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * Copyright (C) 2008 IBM Corporation + * 'find_last_bit' is written by Rusty Russell + * (Inspired by David Howell's find_next_bit implementation) + * + * Rewritten by Yury Norov to decrease + * size and improve performance, 2015. + * + * 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 + +#if !defined(find_next_bit) || !defined(find_next_zero_bit) + +/* + * This is a common helper function for find_next_bit and + * find_next_zero_bit. The difference is the "invert" argument, which + * is XORed with each fetched word before searching it for one bits. + */ +static unsigned long _find_next_bit(const unsigned long *addr, + unsigned long nbits, unsigned long start, unsigned long invert) +{ + unsigned long tmp; + + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + + /* Handle 1st word. */ + tmp &= BITMAP_FIRST_WORD_MASK(start); + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + } + + return min(start + __ffs(tmp), nbits); +} +#endif + +#ifndef find_next_bit +/* + * Find the next set bit in a memory region. + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, size, offset, 0UL); +} +EXPORT_SYMBOL(find_next_bit); +#endif + +#ifndef find_next_zero_bit +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit(addr, size, offset, ~0UL); +} +EXPORT_SYMBOL(find_next_zero_bit); +#endif + +#ifndef find_first_bit +/* + * Find the first set bit in a memory region. + */ +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long idx; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx]) + return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); + } + + return size; +} +EXPORT_SYMBOL(find_first_bit); +#endif + +#ifndef find_first_zero_bit +/* + * Find the first cleared bit in a memory region. + */ +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long idx; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + if (addr[idx] != ~0UL) + return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); + } + + return size; +} +EXPORT_SYMBOL(find_first_zero_bit); +#endif + +#ifndef find_last_bit +unsigned long find_last_bit(const unsigned long *addr, unsigned long size) +{ + if (size) { + unsigned long val = BITMAP_LAST_WORD_MASK(size); + unsigned long idx = (size-1) / BITS_PER_LONG; + + do { + val &= addr[idx]; + if (val) + return idx * BITS_PER_LONG + __fls(val); + + val = ~0ul; + } while (idx--); + } + return size; +} +EXPORT_SYMBOL(find_last_bit); +#endif + +#ifdef __BIG_ENDIAN + +/* include/linux/byteorder does not support "unsigned long" type */ +static inline unsigned long ext2_swab(const unsigned long y) +{ +#if BITS_PER_LONG == 64 + return (unsigned long) __swab64((u64) y); +#elif BITS_PER_LONG == 32 + return (unsigned long) __swab32((u32) y); +#else +#error BITS_PER_LONG not defined +#endif +} + +#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) +static unsigned long _find_next_bit_le(const unsigned long *addr, + unsigned long nbits, unsigned long start, unsigned long invert) +{ + unsigned long tmp; + + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + + /* Handle 1st word. */ + tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); + start = round_down(start, BITS_PER_LONG); + + while (!tmp) { + start += BITS_PER_LONG; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_LONG] ^ invert; + } + + return min(start + __ffs(ext2_swab(tmp)), nbits); +} +#endif + +#ifndef find_next_zero_bit_le +unsigned long find_next_zero_bit_le(const void *addr, unsigned + long size, unsigned long offset) +{ + return _find_next_bit_le(addr, size, offset, ~0UL); +} +EXPORT_SYMBOL(find_next_zero_bit_le); +#endif + +#ifndef find_next_bit_le +unsigned long find_next_bit_le(const void *addr, unsigned + long size, unsigned long offset) +{ + return _find_next_bit_le(addr, size, offset, 0UL); +} +EXPORT_SYMBOL(find_next_bit_le); +#endif + +#endif /* __BIG_ENDIAN */ diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c deleted file mode 100644 index 18072ea..0000000 --- a/lib/find_next_bit.c +++ /dev/null @@ -1,193 +0,0 @@ -/* bit search implementation - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * Copyright (C) 2008 IBM Corporation - * 'find_last_bit' is written by Rusty Russell - * (Inspired by David Howell's find_next_bit implementation) - * - * Rewritten by Yury Norov to decrease - * size and improve performance, 2015. - * - * 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 - -#if !defined(find_next_bit) || !defined(find_next_zero_bit) - -/* - * This is a common helper function for find_next_bit and - * find_next_zero_bit. The difference is the "invert" argument, which - * is XORed with each fetched word before searching it for one bits. - */ -static unsigned long _find_next_bit(const unsigned long *addr, - unsigned long nbits, unsigned long start, unsigned long invert) -{ - unsigned long tmp; - - if (!nbits || start >= nbits) - return nbits; - - tmp = addr[start / BITS_PER_LONG] ^ invert; - - /* Handle 1st word. */ - tmp &= BITMAP_FIRST_WORD_MASK(start); - start = round_down(start, BITS_PER_LONG); - - while (!tmp) { - start += BITS_PER_LONG; - if (start >= nbits) - return nbits; - - tmp = addr[start / BITS_PER_LONG] ^ invert; - } - - return min(start + __ffs(tmp), nbits); -} -#endif - -#ifndef find_next_bit -/* - * Find the next set bit in a memory region. - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - return _find_next_bit(addr, size, offset, 0UL); -} -EXPORT_SYMBOL(find_next_bit); -#endif - -#ifndef find_next_zero_bit -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - return _find_next_bit(addr, size, offset, ~0UL); -} -EXPORT_SYMBOL(find_next_zero_bit); -#endif - -#ifndef find_first_bit -/* - * Find the first set bit in a memory region. - */ -unsigned long find_first_bit(const unsigned long *addr, unsigned long size) -{ - unsigned long idx; - - for (idx = 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx]) - return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); - } - - return size; -} -EXPORT_SYMBOL(find_first_bit); -#endif - -#ifndef find_first_zero_bit -/* - * Find the first cleared bit in a memory region. - */ -unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) -{ - unsigned long idx; - - for (idx = 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx] != ~0UL) - return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); - } - - return size; -} -EXPORT_SYMBOL(find_first_zero_bit); -#endif - -#ifndef find_last_bit -unsigned long find_last_bit(const unsigned long *addr, unsigned long size) -{ - if (size) { - unsigned long val = BITMAP_LAST_WORD_MASK(size); - unsigned long idx = (size-1) / BITS_PER_LONG; - - do { - val &= addr[idx]; - if (val) - return idx * BITS_PER_LONG + __fls(val); - - val = ~0ul; - } while (idx--); - } - return size; -} -EXPORT_SYMBOL(find_last_bit); -#endif - -#ifdef __BIG_ENDIAN - -/* include/linux/byteorder does not support "unsigned long" type */ -static inline unsigned long ext2_swab(const unsigned long y) -{ -#if BITS_PER_LONG == 64 - return (unsigned long) __swab64((u64) y); -#elif BITS_PER_LONG == 32 - return (unsigned long) __swab32((u32) y); -#else -#error BITS_PER_LONG not defined -#endif -} - -#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) -static unsigned long _find_next_bit_le(const unsigned long *addr, - unsigned long nbits, unsigned long start, unsigned long invert) -{ - unsigned long tmp; - - if (!nbits || start >= nbits) - return nbits; - - tmp = addr[start / BITS_PER_LONG] ^ invert; - - /* Handle 1st word. */ - tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); - start = round_down(start, BITS_PER_LONG); - - while (!tmp) { - start += BITS_PER_LONG; - if (start >= nbits) - return nbits; - - tmp = addr[start / BITS_PER_LONG] ^ invert; - } - - return min(start + __ffs(ext2_swab(tmp)), nbits); -} -#endif - -#ifndef find_next_zero_bit_le -unsigned long find_next_zero_bit_le(const void *addr, unsigned - long size, unsigned long offset) -{ - return _find_next_bit_le(addr, size, offset, ~0UL); -} -EXPORT_SYMBOL(find_next_zero_bit_le); -#endif - -#ifndef find_next_bit_le -unsigned long find_next_bit_le(const void *addr, unsigned - long size, unsigned long offset) -{ - return _find_next_bit_le(addr, size, offset, 0UL); -} -EXPORT_SYMBOL(find_next_bit_le); -#endif - -#endif /* __BIG_ENDIAN */ -- cgit v0.10.2 From 7c43d9a30c527d9e06e2c55f82b56f28df43caed Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 16 Apr 2015 12:43:22 -0700 Subject: lib/vsprintf.c: even faster binary to decimal conversion The most expensive part of decimal conversion is the divisions by 10 (albeit done using reciprocal multiplication with appropriately chosen constants). I decided to see if one could eliminate around half of these multiplications by emitting two digits at a time, at the cost of a 200 byte lookup table, and it does indeed seem like there is something to be gained, especially on 64 bits. Microbenchmarking shows improvements ranging from -50% (for numbers uniformly distributed in [0, 2^64-1]) to -25% (for numbers heavily biased toward the smaller end, a more realistic distribution). On a larger scale, perf shows that top, one of the big consumers of /proc data, uses 0.5-1.0% fewer cpu cycles. I had to jump through some hoops to get the 32 bit code to compile and run on my 64 bit machine, so I'm not sure how relevant these numbers are, but just for comparison the microbenchmark showed improvements between -30% and -10%. The bloat-o-meter costs are around 150 bytes (the generated code is a little smaller, so it's not the full 200 bytes) on both 32 and 64 bit. I'm aware that extra cache misses won't show up in a microbenchmark as used above, but on the other hand decimal conversions often happen in bulk (for example in the case of top). I have of course tested that the new code generates the same output as the old, for both the first and last 1e10 numbers in [0,2^64-1] and 4e9 'random' numbers in-between. Test and verification code on github: https://github.com/Villemoes/dec. Signed-off-by: Rasmus Villemoes Tested-by: Jeff Epler Cc: "Peter Zijlstra (Intel)" Cc: Tejun Heo Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3a1e084..c93ec8a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -33,6 +33,7 @@ #include /* for PAGE_SIZE */ #include /* for dereference_function_descriptor() */ +#include /* cpu_to_le16 */ #include #include "kstrtox.h" @@ -122,142 +123,147 @@ int skip_atoi(const char **s) return i; } -/* Decimal conversion is by far the most typical, and is used - * for /proc and /sys data. This directly impacts e.g. top performance - * with many processes running. We optimize it for speed - * using ideas described at - * (with permission from the author, Douglas W. Jones). +/* + * Decimal conversion is by far the most typical, and is used for + * /proc and /sys data. This directly impacts e.g. top performance + * with many processes running. We optimize it for speed by emitting + * two characters at a time, using a 200 byte lookup table. This + * roughly halves the number of multiplications compared to computing + * the digits one at a time. Implementation strongly inspired by the + * previous version, which in turn used ideas described at + * (with permission + * from the author, Douglas W. Jones). + * + * It turns out there is precisely one 26 bit fixed-point + * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32 + * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual + * range happens to be somewhat larger (x <= 1073741898), but that's + * irrelevant for our purpose. + * + * For dividing a number in the range [10^4, 10^6-1] by 100, we still + * need a 32x32->64 bit multiply, so we simply use the same constant. + * + * For dividing a number in the range [100, 10^4-1] by 100, there are + * several options. The simplest is (x * 0x147b) >> 19, which is valid + * for all x <= 43698. */ -#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64 -/* Formats correctly any integer in [0, 999999999] */ +static const u16 decpair[100] = { +#define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030) + _( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9), + _(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19), + _(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29), + _(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39), + _(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49), + _(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59), + _(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69), + _(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79), + _(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89), + _(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99), +#undef _ +}; + +/* + * This will print a single '0' even if r == 0, since we would + * immediately jump to out_r where two 0s would be written and one of + * them then discarded. This is needed by ip4_string below. All other + * callers pass a non-zero value of r. +*/ static noinline_for_stack -char *put_dec_full9(char *buf, unsigned q) +char *put_dec_trunc8(char *buf, unsigned r) { - unsigned r; + unsigned q; - /* - * Possible ways to approx. divide by 10 - * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit) - * (x * 0xcccd) >> 19 x < 81920 (x < 262149 when 64-bit mul) - * (x * 0x6667) >> 18 x < 43699 - * (x * 0x3334) >> 17 x < 16389 - * (x * 0x199a) >> 16 x < 16389 - * (x * 0x0ccd) >> 15 x < 16389 - * (x * 0x0667) >> 14 x < 2739 - * (x * 0x0334) >> 13 x < 1029 - * (x * 0x019a) >> 12 x < 1029 - * (x * 0x00cd) >> 11 x < 1029 shorter code than * 0x67 (on i386) - * (x * 0x0067) >> 10 x < 179 - * (x * 0x0034) >> 9 x < 69 same - * (x * 0x001a) >> 8 x < 69 same - * (x * 0x000d) >> 7 x < 69 same, shortest code (on i386) - * (x * 0x0007) >> 6 x < 19 - * See - */ - r = (q * (uint64_t)0x1999999a) >> 32; - *buf++ = (q - 10 * r) + '0'; /* 1 */ - q = (r * (uint64_t)0x1999999a) >> 32; - *buf++ = (r - 10 * q) + '0'; /* 2 */ - r = (q * (uint64_t)0x1999999a) >> 32; - *buf++ = (q - 10 * r) + '0'; /* 3 */ - q = (r * (uint64_t)0x1999999a) >> 32; - *buf++ = (r - 10 * q) + '0'; /* 4 */ - r = (q * (uint64_t)0x1999999a) >> 32; - *buf++ = (q - 10 * r) + '0'; /* 5 */ - /* Now value is under 10000, can avoid 64-bit multiply */ - q = (r * 0x199a) >> 16; - *buf++ = (r - 10 * q) + '0'; /* 6 */ - r = (q * 0xcd) >> 11; - *buf++ = (q - 10 * r) + '0'; /* 7 */ - q = (r * 0xcd) >> 11; - *buf++ = (r - 10 * q) + '0'; /* 8 */ - *buf++ = q + '0'; /* 9 */ + /* 1 <= r < 10^8 */ + if (r < 100) + goto out_r; + + /* 100 <= r < 10^8 */ + q = (r * (u64)0x28f5c29) >> 32; + *((u16 *)buf) = decpair[r - 100*q]; + buf += 2; + + /* 1 <= q < 10^6 */ + if (q < 100) + goto out_q; + + /* 100 <= q < 10^6 */ + r = (q * (u64)0x28f5c29) >> 32; + *((u16 *)buf) = decpair[q - 100*r]; + buf += 2; + + /* 1 <= r < 10^4 */ + if (r < 100) + goto out_r; + + /* 100 <= r < 10^4 */ + q = (r * 0x147b) >> 19; + *((u16 *)buf) = decpair[r - 100*q]; + buf += 2; +out_q: + /* 1 <= q < 100 */ + r = q; +out_r: + /* 1 <= r < 100 */ + *((u16 *)buf) = decpair[r]; + buf += 2; + if (buf[-1] == '0') + buf--; return buf; } -#endif -/* Similar to above but do not pad with zeros. - * Code can be easily arranged to print 9 digits too, but our callers - * always call put_dec_full9() instead when the number has 9 decimal digits. - */ +#if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64 static noinline_for_stack -char *put_dec_trunc8(char *buf, unsigned r) +char *put_dec_full8(char *buf, unsigned r) { unsigned q; - /* Copy of previous function's body with added early returns */ - while (r >= 10000) { - q = r + '0'; - r = (r * (uint64_t)0x1999999a) >> 32; - *buf++ = q - 10*r; - } + /* 0 <= r < 10^8 */ + q = (r * (u64)0x28f5c29) >> 32; + *((u16 *)buf) = decpair[r - 100*q]; + buf += 2; - q = (r * 0x199a) >> 16; /* r <= 9999 */ - *buf++ = (r - 10 * q) + '0'; - if (q == 0) - return buf; - r = (q * 0xcd) >> 11; /* q <= 999 */ - *buf++ = (q - 10 * r) + '0'; - if (r == 0) - return buf; - q = (r * 0xcd) >> 11; /* r <= 99 */ - *buf++ = (r - 10 * q) + '0'; - if (q == 0) - return buf; - *buf++ = q + '0'; /* q <= 9 */ - return buf; -} + /* 0 <= q < 10^6 */ + r = (q * (u64)0x28f5c29) >> 32; + *((u16 *)buf) = decpair[q - 100*r]; + buf += 2; -/* There are two algorithms to print larger numbers. - * One is generic: divide by 1000000000 and repeatedly print - * groups of (up to) 9 digits. It's conceptually simple, - * but requires a (unsigned long long) / 1000000000 division. - * - * Second algorithm splits 64-bit unsigned long long into 16-bit chunks, - * manipulates them cleverly and generates groups of 4 decimal digits. - * It so happens that it does NOT require long long division. - * - * If long is > 32 bits, division of 64-bit values is relatively easy, - * and we will use the first algorithm. - * If long long is > 64 bits (strange architecture with VERY large long long), - * second algorithm can't be used, and we again use the first one. - * - * Else (if long is 32 bits and long long is 64 bits) we use second one. - */ + /* 0 <= r < 10^4 */ + q = (r * 0x147b) >> 19; + *((u16 *)buf) = decpair[r - 100*q]; + buf += 2; -#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64 - -/* First algorithm: generic */ + /* 0 <= q < 100 */ + *((u16 *)buf) = decpair[q]; + buf += 2; + return buf; +} -static +static noinline_for_stack char *put_dec(char *buf, unsigned long long n) { - if (n >= 100*1000*1000) { - while (n >= 1000*1000*1000) - buf = put_dec_full9(buf, do_div(n, 1000*1000*1000)); - if (n >= 100*1000*1000) - return put_dec_full9(buf, n); - } + if (n >= 100*1000*1000) + buf = put_dec_full8(buf, do_div(n, 100*1000*1000)); + /* 1 <= n <= 1.6e11 */ + if (n >= 100*1000*1000) + buf = put_dec_full8(buf, do_div(n, 100*1000*1000)); + /* 1 <= n < 1e8 */ return put_dec_trunc8(buf, n); } -#else +#elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64 -/* Second algorithm: valid only for 64-bit long longs */ - -/* See comment in put_dec_full9 for choice of constants */ -static noinline_for_stack -void put_dec_full4(char *buf, unsigned q) +static void +put_dec_full4(char *buf, unsigned r) { - unsigned r; - r = (q * 0xccd) >> 15; - buf[0] = (q - 10 * r) + '0'; - q = (r * 0xcd) >> 11; - buf[1] = (r - 10 * q) + '0'; - r = (q * 0xcd) >> 11; - buf[2] = (q - 10 * r) + '0'; - buf[3] = r + '0'; + unsigned q; + + /* 0 <= r < 10^4 */ + q = (r * 0x147b) >> 19; + *((u16 *)buf) = decpair[r - 100*q]; + buf += 2; + /* 0 <= q < 100 */ + *((u16 *)buf) = decpair[q]; } /* @@ -265,9 +271,9 @@ void put_dec_full4(char *buf, unsigned q) * The approximation x/10000 == (x * 0x346DC5D7) >> 43 * holds for all x < 1,128,869,999. The largest value this * helper will ever be asked to convert is 1,125,520,955. - * (d1 in the put_dec code, assuming n is all-ones). + * (second call in the put_dec code, assuming n is all-ones). */ -static +static noinline_for_stack unsigned put_dec_helper4(char *buf, unsigned x) { uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43; @@ -294,6 +300,8 @@ char *put_dec(char *buf, unsigned long long n) d2 = (h ) & 0xffff; d3 = (h >> 16); /* implicit "& 0xffff" */ + /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0 + = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */ q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff); q = put_dec_helper4(buf, q); @@ -323,7 +331,8 @@ char *put_dec(char *buf, unsigned long long n) */ int num_to_str(char *buf, int size, unsigned long long num) { - char tmp[sizeof(num) * 3]; + /* put_dec requires 2-byte alignment of the buffer. */ + char tmp[sizeof(num) * 3] __aligned(2); int idx, len; /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */ @@ -384,7 +393,8 @@ static noinline_for_stack char *number(char *buf, char *end, unsigned long long num, struct printf_spec spec) { - char tmp[3 * sizeof(num)]; + /* put_dec requires 2-byte alignment of the buffer. */ + char tmp[3 * sizeof(num)] __aligned(2); char sign; char locase; int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); @@ -944,7 +954,7 @@ char *ip4_string(char *p, const u8 *addr, const char *fmt) break; } for (i = 0; i < 4; i++) { - char temp[3]; /* hold each IP quad in reverse order */ + char temp[4] __aligned(2); /* hold each IP quad in reverse order */ int digits = put_dec_trunc8(temp, addr[index]) - temp; if (leading_zeros) { if (digits < 3) -- cgit v0.10.2 From a7a2c02a40151811609ad8cd3bf5c4fc516fece5 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 16 Apr 2015 12:43:25 -0700 Subject: lib/dma-debug: fix bucket_find_contain() bucket_find_contain() will search the bucket list for a dma_debug_entry. When the entry isn't found it needs to search other buckets too, since only the start address of a dma range is hashed (which might be in a different bucket). A copy of the dma_debug_entry is used to get the previous hash bucket but when its list is searched the original dma_debug_entry is to be used not its modified copy. This fixes false "device driver tries to sync DMA memory it has not allocated" warnings. Signed-off-by: Sebastian Ott Cc: Florian Fainelli Cc: Horia Geanta Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 9722bd2..ae4b65e 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -361,7 +361,7 @@ static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket, unsigned int range = 0; while (range <= max_range) { - entry = __hash_bucket_find(*bucket, &index, containing_match); + entry = __hash_bucket_find(*bucket, ref, containing_match); if (entry) return entry; -- cgit v0.10.2 From 95d119528b0b8440a63bc13904e9873fc3a70503 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:28 -0700 Subject: util_macros.h: add find_closest() macro This series unduplicates the code used to find the member in an array closest to 'x'. The first patch adds a macro implementing the algorithm in two flavors - for arrays sorted in ascending and descending order. The second updates Documentation/CodingStyle on the naming convention for local variables in macros resembling functions. Other three patches replace duplicated code with calls to one of these macros in some hwmon drivers. This patch (of 5): Searching for the member of an array closest to 'x' is duplicated in several places. Add a new include - util_macros.h - and two macros that implement this algorithm for arrays sorted both in ascending and descending order. Uses linear search. Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h new file mode 100644 index 0000000..d5f4fb6 --- /dev/null +++ b/include/linux/util_macros.h @@ -0,0 +1,40 @@ +#ifndef _LINUX_HELPER_MACROS_H_ +#define _LINUX_HELPER_MACROS_H_ + +#define __find_closest(x, a, as, op) \ +({ \ + typeof(as) __fc_i, __fc_as = (as) - 1; \ + typeof(x) __fc_x = (x); \ + typeof(*a) *__fc_a = (a); \ + for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ + if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \ + __fc_a[__fc_i + 1], 2)) \ + break; \ + } \ + (__fc_i); \ +}) + +/** + * find_closest - locate the closest element in a sorted array + * @x: The reference value. + * @a: The array in which to look for the closest element. Must be sorted + * in ascending order. + * @as: Size of 'a'. + * + * Returns the index of the element closest to 'x'. + */ +#define find_closest(x, a, as) __find_closest(x, a, as, <=) + +/** + * find_closest_descending - locate the closest element in a sorted array + * @x: The reference value. + * @a: The array in which to look for the closest element. Must be sorted + * in descending order. + * @as: Size of 'a'. + * + * Similar to find_closest() but 'a' is expected to be sorted in descending + * order. + */ +#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=) + +#endif -- cgit v0.10.2 From f2027543b9cb47e1853d8c34fe931e2fcee5cb65 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:31 -0700 Subject: documentation: update CodingStyle on local variables naming in macros Describe proper naming convention for local variables in macros resembling functions. Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 449a8a1..4d4f06d 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -659,6 +659,19 @@ macros using parameters. #define CONSTANT 0x4000 #define CONSTEXP (CONSTANT | 3) +5) namespace collisions when defining local variables in macros resembling +functions: + +#define FOO(x) \ +({ \ + typeof(x) ret; \ + ret = calc_ret(x); \ + (ret); \ +)} + +ret is a common name for a local variable - __foo_ret is less likely +to collide with an existing variable. + The cpp manual deals with macros exhaustively. The gcc internals manual also covers RTL which is used frequently with assembly language in the kernel. -- cgit v0.10.2 From d38df34e3f0ea1e65c7db5d33d132dc14da0009a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:34 -0700 Subject: hwmon: (ina2xx) replace ina226_avg_bits() with find_closest() Use find_closest() to locate the closest average in ina226_avg_tab. Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index d1542b7..4d28150 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -141,19 +142,6 @@ static const struct ina2xx_config ina2xx_config[] = { */ static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; -static int ina226_avg_bits(int avg) -{ - int i; - - /* Get the closest average from the tab. */ - for (i = 0; i < ARRAY_SIZE(ina226_avg_tab) - 1; i++) { - if (avg <= (ina226_avg_tab[i] + ina226_avg_tab[i + 1]) / 2) - break; - } - - return i; /* Return 0b0111 for values greater than 1024. */ -} - static int ina226_reg_to_interval(u16 config) { int avg = ina226_avg_tab[INA226_READ_AVG(config)]; @@ -171,7 +159,8 @@ static u16 ina226_interval_to_reg(int interval, u16 config) avg = DIV_ROUND_CLOSEST(interval * 1000, INA226_TOTAL_CONV_TIME_DEFAULT); - avg_bits = ina226_avg_bits(avg); + avg_bits = find_closest(avg, ina226_avg_tab, + ARRAY_SIZE(ina226_avg_tab)); return (config & ~INA226_AVG_RD_MASK) | INA226_SHIFT_AVG(avg_bits); } -- cgit v0.10.2 From 0f3721c51ec5643e00f07dd3bbc5712c72fc62b2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:36 -0700 Subject: hwmon: (lm85) use find_closest() in x_TO_REG() functions Replace RANGE_TO_REG() and FREQ_TO_REG() implementations with calls to find_closest(). Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 2b4b419..6ff773f 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -34,6 +34,7 @@ #include #include #include +#include /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -190,15 +191,7 @@ static const int lm85_range_map[] = { static int RANGE_TO_REG(long range) { - int i; - - /* Find the closest match */ - for (i = 0; i < 15; ++i) { - if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2) - break; - } - - return i; + return find_closest(range, lm85_range_map, ARRAY_SIZE(lm85_range_map)); } #define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] @@ -209,16 +202,12 @@ static const int lm85_freq_map[8] = { /* 1 Hz */ static const int adm1027_freq_map[8] = { /* 1 Hz */ 11, 15, 22, 29, 35, 44, 59, 88 }; +#define FREQ_MAP_LEN 8 -static int FREQ_TO_REG(const int *map, unsigned long freq) +static int FREQ_TO_REG(const int *map, + unsigned int map_size, unsigned long freq) { - int i; - - /* Find the closest match */ - for (i = 0; i < 7; ++i) - if (freq <= (map[i] + map[i + 1]) / 2) - break; - return i; + return find_closest(freq, map, map_size); } static int FREQ_FROM_REG(const int *map, u8 reg) @@ -828,7 +817,8 @@ static ssize_t set_pwm_freq(struct device *dev, data->cfg5 &= ~ADT7468_HFPWM; lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); } else { /* Low freq. mode */ - data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); + data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, + FREQ_MAP_LEN, val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->pwm_freq[nr]); -- cgit v0.10.2 From cdb1dc3f1ca5c5899e5fa186afe20390bd8c00dc Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:39 -0700 Subject: hwmon: (w83795) use find_closest_descending() in pwm_freq_to_reg() Replace the loop iterating over pwm_freq_cksel0 with a call to find_closest_descending(). Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 2189413..49276bb 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -35,6 +35,7 @@ #include #include #include +#include /* Addresses to scan */ static const unsigned short normal_i2c[] = { @@ -308,11 +309,8 @@ static u8 pwm_freq_to_reg(unsigned long val, u16 clkin) unsigned long best0, best1; /* Best fit for cksel = 0 */ - for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) { - if (val > (pwm_freq_cksel0[reg0] + - pwm_freq_cksel0[reg0 + 1]) / 2) - break; - } + reg0 = find_closest_descending(val, pwm_freq_cksel0, + ARRAY_SIZE(pwm_freq_cksel0)); if (val < 375) /* cksel = 1 can't beat this */ return reg0; best0 = pwm_freq_cksel0[reg0]; -- cgit v0.10.2 From 675cf53c1deaffadc7b6a0b4afe6cdafec86bedb Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 16 Apr 2015 12:43:42 -0700 Subject: lib/vsprintf.c: improve put_dec_trunc8 slightly I hadn't had enough coffee when I wrote this. Currently, the final increment of buf depends on the value loaded from the table, and causes gcc to emit a cmov immediately before the return. It is smarter to let it depend on r, since the increment can then be computed in parallel with the final load/store pair. It also shaves 16 bytes of .text. Signed-off-by: Rasmus Villemoes Cc: Tejun Heo Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c93ec8a..da39c60 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -165,9 +165,9 @@ static const u16 decpair[100] = { /* * This will print a single '0' even if r == 0, since we would - * immediately jump to out_r where two 0s would be written and one of - * them then discarded. This is needed by ip4_string below. All other - * callers pass a non-zero value of r. + * immediately jump to out_r where two 0s would be written but only + * one of them accounted for in buf. This is needed by ip4_string + * below. All other callers pass a non-zero value of r. */ static noinline_for_stack char *put_dec_trunc8(char *buf, unsigned r) @@ -206,9 +206,7 @@ out_q: out_r: /* 1 <= r < 100 */ *((u16 *)buf) = decpair[r]; - buf += 2; - if (buf[-1] == '0') - buf--; + buf += r < 10 ? 1 : 2; return buf; } -- cgit v0.10.2 From f766093ecb647f5a87bfa456715abbbccee547ce Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:45 -0700 Subject: kernel.h: implement DIV_ROUND_CLOSEST_ULL We have grown a number of different implementations of DIV_ROUND_CLOSEST_ULL throughout the kernel. Move the i915 one to kernel.h so that it can be reused. Signed-off-by: Javi Merino Reviewed-by: Jeff Epler Cc: Jani Nikula Cc: David Airlie Cc: Guenter Roeck Acked-by: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Alex Elder Cc: Antti Palosaari Cc: Javi Merino Cc: Mauro Carvalho Chehab Cc: Mel Gorman Cc: Mike Turquette Cc: Stephen Boyd Cc: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index eef79cc..ba243db 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -36,9 +36,6 @@ #include #include -#define DIV_ROUND_CLOSEST_ULL(ll, d) \ -({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) - /** * _wait_for - magic (register) wait macro * diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d8686ce..08532d4 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -30,6 +30,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include "intel_drv.h" diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d6d630d..3a5b48e 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -103,6 +103,18 @@ (((__x) - ((__d) / 2)) / (__d)); \ } \ ) +/* + * Same as above but for u64 dividends. divisor must be a 32-bit + * number. + */ +#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ +{ \ + typeof(divisor) __d = divisor; \ + unsigned long long _tmp = (x) + (__d) / 2; \ + do_div(_tmp, __d); \ + _tmp; \ +} \ +) /* * Multiplies an integer by a fraction, while avoiding unnecessary -- cgit v0.10.2 From aa7762010a4340a12a87a54b7a402adcdce8cfa9 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:48 -0700 Subject: clk: bcm/kona: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Cc: Mike Turquette Cc: Stephen Boyd Acked-by: Alex Elder Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index 05abae8..a0ef4f7 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c @@ -15,6 +15,7 @@ #include "clk-kona.h" #include +#include /* * "Policies" affect the frequencies of bus clocks provided by a @@ -51,21 +52,6 @@ static inline u32 bitfield_replace(u32 reg_val, u32 shift, u32 width, u32 val) /* Divider and scaling helpers */ -/* - * Implement DIV_ROUND_CLOSEST() for 64-bit dividend and both values - * unsigned. Note that unlike do_div(), the remainder is discarded - * and the return value is the quotient (not the remainder). - */ -u64 do_div_round_closest(u64 dividend, unsigned long divisor) -{ - u64 result; - - result = dividend + ((u64)divisor >> 1); - (void)do_div(result, divisor); - - return result; -} - /* Convert a divider into the scaled divisor value it represents. */ static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) { @@ -87,7 +73,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths) combined = (u64)div_value * BILLION + billionths; combined <<= div->u.s.frac_width; - return do_div_round_closest(combined, BILLION); + return DIV_ROUND_CLOSEST_ULL(combined, BILLION); } /* The scaled minimum divisor representable by a divider */ @@ -731,7 +717,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu, scaled_rate = scale_rate(pre_div, parent_rate); scaled_rate = scale_rate(div, scaled_rate); scaled_div = divider_read_scaled(ccu, pre_div); - scaled_parent_rate = do_div_round_closest(scaled_rate, + scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate, scaled_div); } else { scaled_parent_rate = scale_rate(div, parent_rate); @@ -743,7 +729,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu, * rate. */ scaled_div = divider_read_scaled(ccu, div); - result = do_div_round_closest(scaled_parent_rate, scaled_div); + result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, scaled_div); return (unsigned long)result; } @@ -790,7 +776,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, scaled_rate = scale_rate(pre_div, parent_rate); scaled_rate = scale_rate(div, scaled_rate); scaled_pre_div = divider_read_scaled(ccu, pre_div); - scaled_parent_rate = do_div_round_closest(scaled_rate, + scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate, scaled_pre_div); } else { scaled_parent_rate = scale_rate(div, parent_rate); @@ -802,7 +788,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, * the best we can do. */ if (!divider_is_fixed(div)) { - best_scaled_div = do_div_round_closest(scaled_parent_rate, + best_scaled_div = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, rate); min_scaled_div = scaled_div_min(div); max_scaled_div = scaled_div_max(div); @@ -815,7 +801,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, } /* OK, figure out the resulting rate */ - result = do_div_round_closest(scaled_parent_rate, best_scaled_div); + result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, best_scaled_div); if (scaled_div) *scaled_div = best_scaled_div; diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h index 2537b30..6849a64 100644 --- a/drivers/clk/bcm/clk-kona.h +++ b/drivers/clk/bcm/clk-kona.h @@ -503,7 +503,6 @@ extern struct clk_ops kona_peri_clk_ops; /* Externally visible functions */ -extern u64 do_div_round_closest(u64 dividend, unsigned long divisor); extern u64 scaled_div_max(struct bcm_clk_div *div); extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths); -- cgit v0.10.2 From ee3c86f356b4dfc130442d0bd68ff2da2bd60538 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:51 -0700 Subject: cpuidle: menu: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Acked-by: Rafael J. Wysocki Cc: Mel Gorman Cc: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 4058079..b8a5fa1 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -190,12 +190,6 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices); static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); -/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ -static u64 div_round64(u64 dividend, u32 divisor) -{ - return div_u64(dividend + (divisor / 2), divisor); -} - /* * Try detecting repeating patterns by keeping track of the last 8 * intervals, and checking if the standard deviation of that set @@ -317,7 +311,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * operands are 32 bits. * Make sure to round up for half microseconds. */ - data->predicted_us = div_round64((uint64_t)data->next_timer_us * + data->predicted_us = DIV_ROUND_CLOSEST_ULL((uint64_t)data->next_timer_us * data->correction_factor[data->bucket], RESOLUTION * DECAY); -- cgit v0.10.2 From 512eb720c9892261d68f86ba880a55cdbb74710d Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:54 -0700 Subject: media: cxd2820r: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Cc: Mauro Carvalho Chehab Acked-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 149fdca..72b0e2db 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -79,7 +79,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x4000; - if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = 0x4000 - DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = (if_ctl >> 8) & 0x3f; buf[1] = (if_ctl >> 0) & 0xff; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 422e84b..490e090 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -244,12 +244,6 @@ error: return ret; } -/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */ -u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor) -{ - return div_u64(dividend + (divisor / 2), divisor); -} - static int cxd2820r_set_frontend(struct dvb_frontend *fe) { struct cxd2820r_priv *priv = fe->demodulator_priv; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index 7ff5f60..4b42895 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -64,8 +64,6 @@ int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, int len); -u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor); - int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, int len); diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 51401d0..008cb2a 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -103,7 +103,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; - if_ctl = cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); buf[1] = ((if_ctl >> 8) & 0xff); buf[2] = ((if_ctl >> 0) & 0xff); diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 9c0c4f4..35fe364 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -120,7 +120,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; - if_ctl = cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); buf[1] = ((if_ctl >> 8) & 0xff); buf[2] = ((if_ctl >> 0) & 0xff); -- cgit v0.10.2 From d48502eacd8934b79c3e62f7858c79fa6422398b Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:57 -0700 Subject: ASoC: pcm512x: use DIV_ROUND_CLOSEST_ULL() from kernel.h Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Reported-by: kbuild test robot Cc: Peter Rosin Acked-by: Mark Brown Cc: Liam Girdwood Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 5a30fdd..e12764d 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,6 @@ #define DIV_ROUND_DOWN_ULL(ll, d) \ ({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; }) -#define DIV_ROUND_CLOSEST_ULL(ll, d) \ - ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) #define PCM512x_NUM_SUPPLIES 3 static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { -- cgit v0.10.2 From 2afe27c718b669b551895595873611ac39cc31e3 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 16 Apr 2015 12:44:00 -0700 Subject: lib/bitmap.c: bitmap_[empty,full]: remove code duplication bitmap_empty() has its own implementation. But it's clearly as simple as: find_first_bit(src, nbits) == nbits The same is true for 'bitmap_full'. Signed-off-by: Yury Norov Cc: George Spelvin Cc: Alexey Klimov Cc: Rasmus Villemoes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index be4fa5d..ea17cca 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -283,16 +283,16 @@ static inline int bitmap_empty(const unsigned long *src, unsigned nbits) { if (small_const_nbits(nbits)) return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); - else - return __bitmap_empty(src, nbits); + + return find_first_bit(src, nbits) == nbits; } static inline int bitmap_full(const unsigned long *src, unsigned int nbits) { if (small_const_nbits(nbits)) return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); - else - return __bitmap_full(src, nbits); + + return find_first_zero_bit(src, nbits) == nbits; } static inline int bitmap_weight(const unsigned long *src, unsigned int nbits) diff --git a/lib/bitmap.c b/lib/bitmap.c index d456f4c1..64c0926 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -42,36 +42,6 @@ * for the best explanations of this ordering. */ -int __bitmap_empty(const unsigned long *bitmap, unsigned int bits) -{ - unsigned int k, lim = bits/BITS_PER_LONG; - for (k = 0; k < lim; ++k) - if (bitmap[k]) - return 0; - - if (bits % BITS_PER_LONG) - if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) - return 0; - - return 1; -} -EXPORT_SYMBOL(__bitmap_empty); - -int __bitmap_full(const unsigned long *bitmap, unsigned int bits) -{ - unsigned int k, lim = bits/BITS_PER_LONG; - for (k = 0; k < lim; ++k) - if (~bitmap[k]) - return 0; - - if (bits % BITS_PER_LONG) - if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) - return 0; - - return 1; -} -EXPORT_SYMBOL(__bitmap_full); - int __bitmap_equal(const unsigned long *bitmap1, const unsigned long *bitmap2, unsigned int bits) { -- cgit v0.10.2 From d43698e8abb58a6ac47d16e0f47bb55f452e4fc4 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Thu, 16 Apr 2015 12:44:02 -0700 Subject: firmware/ihex2fw.c: restore missing default in switch statement Commit 2473238eac95 ("ihex: add support for CS:IP/EIP records") removes the "default:" statement in the switch block, making the "return usage();" line dead code and ihex2fw silently ignoring unknown options. Restore this statement. This bug was found by building with HOSTCC=clang and adding -Wunreachable-code-return to HOSTCFLAGS. Fixes: 2473238eac95 ("ihex: add support for CS:IP/EIP records") Signed-off-by: Nicolas Iooss Cc: Mark Brown Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/firmware/ihex2fw.c b/firmware/ihex2fw.c index cf38e15..08d90e2 100644 --- a/firmware/ihex2fw.c +++ b/firmware/ihex2fw.c @@ -86,6 +86,7 @@ int main(int argc, char **argv) case 'j': include_jump = 1; break; + default: return usage(); } } -- cgit v0.10.2 From 6ab3a9701e00c2a085bac6a7a9bdcf8fc5eca6c5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:05 -0700 Subject: checkpatch: improve "no space is necessary after a cast" test The "no space is necessary after a cast" sizeof exclusion doesn't work properly. The test reports a false positive for code like: BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6); Make it work, simplify the exclusions, and add some comments. Signed-off-by: Joe Perches Reported-by: Marek Lindner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d124359..421bbb4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2552,8 +2552,15 @@ sub process { } } - if ($line =~ /^\+.*(\w+\s*)?\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|[,;:\?\(\{\}\[\<\>]|&&|\|\||\\$)/ && - (!defined($1) || $1 !~ /sizeof\s*/)) { +# check for space after cast like "(int) foo" or "(struct foo) bar" +# avoid checking a few false positives: +# "sizeof()" or "__alignof__()" +# function pointer declarations like "(*foo)(int) = bar;" +# structure definitions like "(struct foo) { 0 };" +# multiline macros that define functions +# known attributes or the __attribute__ keyword + if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && + (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { if (CHK("SPACING", "No space is necessary after a cast\n" . $herecurr) && $fix) { -- cgit v0.10.2 From 66d7a382cb5d2d40b468e68b665bbf6f9bc3400e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:08 -0700 Subject: checkpatch: add spell checking of email subject line Only commit log and patch additions are checked for typos and spelling errors currently. Add a check of the email subject line too. Signed-off-by: Joe Perches Suggested-by: Jani Nikula Tested-by: Jani Nikula Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 421bbb4..c061a63 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2303,7 +2303,8 @@ sub process { } # Check for various typo / spelling mistakes - if (defined($misspellings) && ($in_commit_log || $line =~ /^\+/)) { + if (defined($misspellings) && + ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:$|[^a-z@])/gi) { my $typo = $1; my $typo_fix = $spelling_fix{lc($typo)}; -- cgit v0.10.2 From b3e9a677fc0875c7cc26d4edf6742a1436e86c52 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 16 Apr 2015 12:44:11 -0700 Subject: checkpatch: spell check reudce References: http://mid.gmane.org/1424977312-24902-1-git-send-email-ville.syrjala@linux.intel.com Signed-off-by: Jani Nikula Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/spelling.txt b/scripts/spelling.txt index fc7fd52..bb8e4d0 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -825,6 +825,7 @@ retreived||retrieved retreive||retrieve retrive||retrieve retuned||returned +reudce||reduce reuest||request reuqest||request reutnred||returned -- cgit v0.10.2 From ebfd7d62375316ff532b6b9bae9d88a29f434ba7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:14 -0700 Subject: checkpatch: add optional --codespell dictionary to find more typos If a codespell dictionary exists, use it if desired. default is off, maybe it could be turned on later. codespell's dictionary format allows multiple possible corrections, ignore that for now and only use the first suggestion. Also add \b to spelling test so that consecutive misspelled words are found properly. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Kees Cook Cc: Masanari Iida Cc: Lucas De Marchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c061a63..6b79beb 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -47,6 +47,8 @@ my $ignore_perl_version = 0; my $minimum_perl_version = 5.10.0; my $min_conf_desc_length = 4; my $spelling_file = "$D/spelling.txt"; +my $codespell = 0; +my $codespellfile = "/usr/local/share/codespell/dictionary.txt"; sub help { my ($exitcode) = @_; @@ -88,6 +90,9 @@ Options: file. It's your fault if there's no backup or git --ignore-perl-version override checking of perl version. expect runtime errors. + --codespell Use the codespell dictionary for spelling/typos + (default:/usr/local/share/codespell/dictionary.txt) + --codespellfile Use this codespell dictionary -h, --help, --version display this help and exit When FILE is - read standard input. @@ -146,6 +151,8 @@ GetOptions( 'ignore-perl-version!' => \$ignore_perl_version, 'debug=s' => \%debug, 'test-only=s' => \$tst_only, + 'codespell!' => \$codespell, + 'codespellfile=s' => \$codespellfile, 'h|help' => \$help, 'version' => \$help ) or help(1); @@ -449,7 +456,6 @@ my $misspellings; my %spelling_fix; if (open(my $spelling, '<', $spelling_file)) { - my @spelling_list; while (<$spelling>) { my $line = $_; @@ -461,15 +467,39 @@ if (open(my $spelling, '<', $spelling_file)) { my ($suspect, $fix) = split(/\|\|/, $line); - push(@spelling_list, $suspect); $spelling_fix{$suspect} = $fix; } close($spelling); - $misspellings = join("|", @spelling_list); } else { warn "No typos will be found - file '$spelling_file': $!\n"; } +if ($codespell) { + if (open(my $spelling, '<', $codespellfile)) { + while (<$spelling>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + next if ($line =~ m/, disabled/i); + + $line =~ s/,.*$//; + + my ($suspect, $fix) = split(/->/, $line); + + $spelling_fix{$suspect} = $fix; + } + close($spelling); + } else { + warn "No codespell typos will be found - file '$codespellfile': $!\n"; + } +} + +$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; + sub build_types { my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; @@ -2305,7 +2335,7 @@ sub process { # Check for various typo / spelling mistakes if (defined($misspellings) && ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { - while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:$|[^a-z@])/gi) { + while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { my $typo = $1; my $typo_fix = $spelling_fix{lc($typo)}; $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); -- cgit v0.10.2 From b392c64f59d7b088aefb4e86d208cd6d3b93eefb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:16 -0700 Subject: checkpatch: match more world writable permissions Currently checkpatch will fuss if one uses world writable settings in debugfs files and DEVICE_ATTR uses by testing S_IWUGO but not testing S_IWOTH, S_IRWXUGO or S_IALLUGO. Extend the check to catch all cases exporting world writable permissions including octal values. [akpm@linux-foundation.org: remove stray $] Signed-off-by: Joe Perches Original-patch-by: Nicholas Mc Guire Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 6b79beb..5748c35 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -443,6 +443,14 @@ foreach my $entry (@mode_permission_funcs) { $mode_perms_search .= $entry->[0]; } +our $mode_perms_world_writable = qr{ + S_IWUGO | + S_IWOTH | + S_IRWXUGO | + S_IALLUGO | + 0[0-7][0-7][2367] +}x; + our $allowed_asm_includes = qr{(?x: irq| memory| @@ -5356,8 +5364,8 @@ sub process { } } - if ($line =~ /debugfs_create_file.*S_IWUGO/ || - $line =~ /DEVICE_ATTR.*S_IWUGO/ ) { + if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || + $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { WARN("EXPORTED_WORLD_WRITABLE", "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); } -- cgit v0.10.2 From f34e4a4f979c0d39f741bc809127fcf2167a7389 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:19 -0700 Subject: checkpatch: improve return negative errno check Add a few conditions to the test to find return (ERRNO); Make the output message a bit less cryptic too. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 5748c35..45babf2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4009,12 +4009,12 @@ sub process { } } -# Return of what appears to be an errno should normally be -'ve - if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { +# Return of what appears to be an errno should normally be negative + if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { my $name = $1; if ($name ne 'EOF' && $name ne 'ERROR') { WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be -ve (return -$1)\n" . $herecurr); + "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); } } -- cgit v0.10.2 From ab7e23f3448e55f4808f443a7b98ded6707701bb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:22 -0700 Subject: checkpatch: add test for repeated const uses Using 'const const *' is generally meant to be written 'const * const'. Add a test for the miswritten form. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 45babf2..d54a814 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -323,6 +323,7 @@ our $Operators = qr{ our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; +our $BasicType; our $NonptrType; our $NonptrTypeMisordered; our $NonptrTypeWithAttr; @@ -514,6 +515,11 @@ sub build_types { my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; + $BasicType = qr{ + (?:$typeOtherOSTypedefs\b)| + (?:$typeTypedefs\b)| + (?:${all}\b) + }x; $NonptrType = qr{ (?:$Modifier\s+|const\s+)* (?: @@ -3192,6 +3198,18 @@ sub process { $herecurr); } +# check for const const where is not a pointer or array type + if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { + my $found = $1; + if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { + WARN("CONST_CONST", + "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); + } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { + WARN("CONST_CONST", + "'const $found const' should probably be 'const $found'\n" . $herecurr); + } + } + # check for non-global char *foo[] = {"bar", ...} declarations. if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { WARN("STATIC_CONST_CHAR_ARRAY", -- cgit v0.10.2 From 0e212e0a720601fabda102f7998d27625f9e144a Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:44:25 -0700 Subject: checkpatch: don't ask for asm/file.h to linux/file.h unconditionally Currently checkpatch warns when asm/file.h is included and linux/file.h exists. That conversion can be made when linux/file.h includes asm/file.h which is not always the case.(See signal.h) Signed-off-by: Fabian Frederick Cc: Andy Whitcroft Acked-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d54a814..c72e7ee 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4242,7 +4242,8 @@ sub process { } } -#warn if is #included and is available (uses RAW line) +# warn if is #included and is available and includes +# itself (uses RAW line) if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\}) { my $file = "$1.h"; my $checkfile = "include/linux/$file"; @@ -4250,12 +4251,15 @@ sub process { $realfile ne $checkfile && $1 !~ /$allowed_asm_includes/) { - if ($realfile =~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include instead of \n" . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include instead of \n" . $herecurr); + my $asminclude = `grep -Ec "#include\\s+" $root/$checkfile`; + if ($asminclude > 0) { + if ($realfile =~ m{^arch/}) { + CHK("ARCH_INCLUDE_LINUX", + "Consider using #include instead of \n" . $herecurr); + } else { + WARN("INCLUDE_LINUX", + "Use #include instead of \n" . $herecurr); + } } } } -- cgit v0.10.2 From 2a076f40d8c9be95bee7bcf18436655e1140447f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:28 -0700 Subject: checkpatch, SubmittingPatches: suggest line wrapping commit messages at 75 columns Commit messages lines are sometimes overly long. Suggest line wrapping at 75 columns so the default git commit log indentation of 4 plus the commit message text still fits on an 80 column screen. Add a checkpatch test for long commit messages lines too. Signed-off-by: Joe Perches Cc: David Miller Cc: Jonathan Corbet Cc: Ian Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 447671b..b03a832 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -614,8 +614,8 @@ The canonical patch message body contains the following: - An empty line. - - The body of the explanation, which will be copied to the - permanent changelog to describe this patch. + - The body of the explanation, line wrapped at 75 columns, which will + be copied to the permanent changelog to describe this patch. - The "Signed-off-by:" lines, described above, which will also go in the changelog. diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c72e7ee..9a8b2bd 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1898,6 +1898,7 @@ sub process { my $in_header_lines = $file ? 0 : 1; my $in_commit_log = 0; #Scanning lines before patch + my $commit_log_long_line = 0; my $reported_maintainer_file = 0; my $non_utf8_charset = 0; @@ -2233,6 +2234,14 @@ sub process { "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); } +# Check for line lengths > 75 in commit log, warn once + if ($in_commit_log && !$commit_log_long_line && + length($line) > 75) { + WARN("COMMIT_LOG_LONG_LINE", + "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); + $commit_log_long_line = 1; + } + # Check for git id commit length and improperly formed commit descriptions if ($in_commit_log && $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i) { my $init_char = $1; -- cgit v0.10.2 From 29a3c46673a5e3ee22feaba7020a280486c78f0a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:30 -0700 Subject: checkpatch: add #define foo "string" long line exception There are #defines with long string constants like: #define foo "some really long string > 80 columns" Add a long line exception for them. Miscellanea: Use the $String variable for slightly better readability Signed-off-by: Joe Perches Reported-by: Madalin-Cristian Bucur Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9a8b2bd..36d7e70 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2513,8 +2513,9 @@ sub process { #line length limit if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ && $rawline !~ /^.\s*\*\s*\@$Ident\s/ && - !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:|,|\)\s*;)\s*$/ || - $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) && + !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?$String\s*(?:|,|\)\s*;)\s*$/ || + $line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || + $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) && $length > $max_line_length) { WARN("LONG_LINE", -- cgit v0.10.2 From 6d07d01b62b2d81500803058f736b46677ec873a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:33 -0700 Subject: checkpatch: add uart_ops to normally const structs Add another struct to the list of normally const struct types Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Maxime Coquelin Cc: Greg Kroah-Hartman Cc: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 36d7e70..ea628eb 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5339,6 +5339,7 @@ sub process { stacktrace_ops| sysfs_ops| tty_operations| + uart_ops| usb_mon_operations| wd_ops}x; if ($line !~ /\bconst\b/ && -- cgit v0.10.2 From b598b67060f14eb8c34d0cef1db4727dab56ef91 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:36 -0700 Subject: checkpatch: add 'Prefer ARRAY_SIZE" test Add a test for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo). Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ea628eb..6c11cb6 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3227,6 +3227,19 @@ sub process { $herecurr); } +# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) + if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { + my $array = $1; + if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { + my $array_div = $1; + if (WARN("ARRAY_SIZE", + "Prefer ARRAY_SIZE($array)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; + } + } + } + # check for function declarations without arguments like "int foo()" if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { if (ERROR("FUNCTION_WITHOUT_ARGS", -- cgit v0.10.2 From d7fe8065ad891a2ad38b73ff10b97d08f0fb3b0b Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Thu, 16 Apr 2015 12:44:39 -0700 Subject: checkpatch: improve operator spacing check Code such as: x = timercmp(&now, &end, <); Will currently trigger a checkpatch error. e.g. ERROR: spaces required around that '<' This is because the "Ignore operators passed as parameters" check looks only for a comma following the operator. Improve the check by also looking for a close parenthesis. Signed-off-by: Sam Bobroff Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 6c11cb6..78a951f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3652,7 +3652,7 @@ sub process { # Ignore operators passed as parameters. if ($op_type ne 'V' && - $ca =~ /\s$/ && $cc =~ /^\s*,/) { + $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { # # Ignore comments # } elsif ($op =~ /^$;+$/) { -- cgit v0.10.2 From c17893c7407fbe988f5901596c3e5e75c0dc0f67 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:42 -0700 Subject: checkpatch: add a test for const with __read_mostly uses const objects shouldn't be __read_mostly. They are read-only. Marking these objects as __read_mostly causes section conflicts with LTO linking. So add a test to try to avoid this issue. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 78a951f..2851658 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4791,6 +4791,16 @@ sub process { } } +# check for __read_mostly with const non-pointer (should just be const) + if ($line =~ /\b__read_mostly\b/ && + $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { + if (ERROR("CONST_READ_MOSTLY", + "Invalid use of __read_mostly with const type\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; + } + } + # don't use __constant_ functions outside of include/uapi/ if ($realfile !~ m@^include/uapi/@ && $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { -- cgit v0.10.2 From 91c9afaf97ee554d2cd3042a5ad01ad21c99e8c4 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 16 Apr 2015 12:44:44 -0700 Subject: checkpatch.pl: new instances of ENOSYS are errors ENOSYS means that a nonexistent system call was called. We have a bad habit of using it for things like invalid operations on otherwise valid syscalls. We should avoid this in new code. Pervasive incorrect usage of ENOSYS came up at the kernel summit ABI review discussion. Let's see if checkpatch can help. I'll submit a separate patch for include/uapi/asm-generic/errno.h. Signed-off-by: Andy Lutomirski Cc: Pavel Machek Cc: Michael Kerrisk Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 2851658..561f41e 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3396,6 +3396,14 @@ sub process { "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); } +# ENOSYS means "bad syscall nr" and nothing else. This will have a small +# number of false positives, but assembly files are not checked, so at +# least the arch entry code will not trigger this warning. + if ($line =~ /\bENOSYS\b/) { + WARN("ENOSYS", + "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); + } + # function brace can't be on same line, except for #defines of do while, # or if closed on same line if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and -- cgit v0.10.2 From e15f431fe2d53cd4673510736da7d4fa1090e096 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 16 Apr 2015 12:44:47 -0700 Subject: errno.h: Improve ENOSYS's comment ENOSYS is the mechanism used by user code to detect whether the running kernel implements a given system call. It should not be returned by anything except an unimplemented system call. Unfortunately, it is rather frequently used in the kernel to indicate that various new functions of existing system calls are not implemented. This should be discouraged. Improve the comment in errno.h to help clarify ENOSYS's purpose. Signed-off-by: Andy Lutomirski Cc: Pavel Machek Cc: Michael Kerrisk Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/uapi/asm-generic/errno.h b/include/uapi/asm-generic/errno.h index 1e1ea6e..88e0914c 100644 --- a/include/uapi/asm-generic/errno.h +++ b/include/uapi/asm-generic/errno.h @@ -6,7 +6,16 @@ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ + +/* + * This error code is special: arch syscall entry code will return + * -ENOSYS if users try to call a syscall that doesn't exist. To keep + * failures of syscalls that really do exist distinguishable from + * failures due to attempts to use a nonexistent syscall, syscall + * implementations should refrain from returning -ENOSYS. + */ +#define ENOSYS 38 /* Invalid system call number */ + #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ -- cgit v0.10.2 From 323b267faff4db5f2424b6c09ab78a272393b69e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:50 -0700 Subject: checkpatch: fix --fix use with a patch of multiple files If a patch touches multiple files, the --fix and --fix-inplace option doesn't keep the proper line count and makes the new patch file not able to be applied via bad offset line numbers when lines are added or deleted by the --fix option. Dunno how that extra backslash snuck in there. Signed-off-by: Joe Perches Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 561f41e..35aecb3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1690,7 +1690,7 @@ sub fix_inserted_deleted_lines { foreach my $old_line (@{$linesRef}) { my $save_line = 1; my $line = $old_line; #don't modify the array - if ($line =~ /^(?:\+\+\+\|\-\-\-)\s+\S+/) { #new filename + if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename $delta_offset = 0; } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk $range_last_linenr = $new_linenr; -- cgit v0.10.2 From e0df7e1faebad9a7ac0931d03f86fcd5c0d1896e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:44:53 -0700 Subject: checkpatch: avoid "spaces required around that ':'" false positive Since commit 1f65f947a6a8 ("checkpatch: add checks for question mark and colon spacing") back in 2008, checkpatch has reported false positive for asm volatile uses of "::" checkpatch thinks colons should always have spaces around it. Add an exception for colons with colons on either side for this valid asm volatile (and c++) use. Signed-off-by: Joe Perches Reported-by: Yehuda Yitschak Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 35aecb3..89b1df4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3845,6 +3845,14 @@ sub process { $ok = 1; } + # for asm volatile statements + # ignore a colon with another + # colon immediately before or after + if (($op eq ':') && + ($ca =~ /:$/ || $cc =~ /^:/)) { + $ok = 1; + } + # messages are ERROR, but ?: are CHK if ($ok == 0) { my $msg_type = \&ERROR; -- cgit v0.10.2 From 6ceafb880c218a14e0cf8d08499138a1a9775fb2 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 16 Apr 2015 12:44:56 -0700 Subject: fs/binfmt_misc.c: simplify entry_status() sprintf() reliably returns the number of characters printed, so we don't need to ask strlen() where we are. Also replace calling sprintf("%02x") in a loop with the much simpler bin2hex(). [akpm@linux-foundation.org: it's odd to include kernel.h after everything else] Signed-off-by: Rasmus Villemoes Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 97aff28..9dcb054 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -521,9 +522,8 @@ static int parse_command(const char __user *buffer, size_t count) static void entry_status(Node *e, char *page) { - char *dp; - char *status = "disabled"; - const char *flags = "flags: "; + char *dp = page; + const char *status = "disabled"; if (test_bit(Enabled, &e->flags)) status = "enabled"; @@ -533,12 +533,10 @@ static void entry_status(Node *e, char *page) return; } - sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter); - dp = page + strlen(page); + dp += sprintf(dp, "%s\ninterpreter %s\n", status, e->interpreter); /* print the special flags */ - sprintf(dp, "%s", flags); - dp += strlen(flags); + dp += sprintf(dp, "flags: "); if (e->flags & MISC_FMT_PRESERVE_ARGV0) *dp++ = 'P'; if (e->flags & MISC_FMT_OPEN_BINARY) @@ -550,21 +548,11 @@ static void entry_status(Node *e, char *page) if (!test_bit(Magic, &e->flags)) { sprintf(dp, "extension .%s\n", e->magic); } else { - int i; - - sprintf(dp, "offset %i\nmagic ", e->offset); - dp = page + strlen(page); - for (i = 0; i < e->size; i++) { - sprintf(dp, "%02x", 0xff & (int) (e->magic[i])); - dp += 2; - } + dp += sprintf(dp, "offset %i\nmagic ", e->offset); + dp = bin2hex(dp, e->magic, e->size); if (e->mask) { - sprintf(dp, "\nmask "); - dp += 6; - for (i = 0; i < e->size; i++) { - sprintf(dp, "%02x", 0xff & (int) (e->mask[i])); - dp += 2; - } + dp += sprintf(dp, "\nmask "); + dp = bin2hex(dp, e->mask, e->size); } *dp++ = '\n'; *dp = '\0'; -- cgit v0.10.2 From 6e54abac1b8e0b7febffdbad37b605daef1cfcff Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Thu, 16 Apr 2015 12:44:58 -0700 Subject: kasan: Makefile: shut up warnings if CONFIG_COMPILE_TEST=y It might be annoying to constantly see this: scripts/Makefile.kasan:16: Cannot use CONFIG_KASAN: -fsanitize=kernel-address is not supported by compiler while performing allmodconfig/allyesconfig build tests. Disable this warning if CONFIG_COMPILE_TEST=y. Signed-off-by: Andrey Ryabinin Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 631619b..3f874d2 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -13,12 +13,16 @@ CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \ --param asan-instrumentation-with-call-threshold=$(call_threshold)) ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),) + ifneq ($(CONFIG_COMPILE_TEST),y) $(warning Cannot use CONFIG_KASAN: \ -fsanitize=kernel-address is not supported by compiler) + endif else ifeq ($(CFLAGS_KASAN),) - $(warning CONFIG_KASAN: compiler does not support all options.\ - Trying minimal configuration) + ifneq ($(CONFIG_COMPILE_TEST),y) + $(warning CONFIG_KASAN: compiler does not support all options.\ + Trying minimal configuration) + endif CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL) endif endif -- cgit v0.10.2 From b0c57b5941c4a42698d845ada6a76feeba2d1be9 Mon Sep 17 00:00:00 2001 From: Robert Kmiec Date: Thu, 16 Apr 2015 12:45:01 -0700 Subject: drivers/rtc/rtc-pcf8563.c: simplify return from function This commit does not change any logic here. It just makes the code easier to read. This is how it looked like: If err != 0 return err; else return 0; Signed-off-by: Robert Kmiec Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 96fb32e..0ba7e59 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -246,7 +246,6 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) { struct pcf8563 *pcf8563 = i2c_get_clientdata(client); - int err; unsigned char buf[9]; dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " @@ -272,12 +271,8 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; - err = pcf8563_write_block_data(client, PCF8563_REG_SC, + return pcf8563_write_block_data(client, PCF8563_REG_SC, 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC); - if (err) - return err; - - return 0; } #ifdef CONFIG_RTC_INTF_DEV -- cgit v0.10.2 From 7f48b21bdfede2c06e966258317a3bb4be3e4f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 16 Apr 2015 12:45:04 -0700 Subject: rtc: stmp3xxx: use optional crystal in low power states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rtc's status register allows to determine if a 32k crystal is connected to keep the rtc running in low power states provided the corresponding fuse bits were blown correctly during production. (In case they were not, the right frequency can be stated in the device tree.) If there is no such crystal available force the 24 MHz XTAL clock to keep running to retain the right date and time. Otherwise use the crystal to save some power. It would be nice to only switch to the crystal when the XTAL clock is about to be disabled and keep the crystal off when unneeded because XTAL is always on while the chip is powered on. But as sudden power loss isn't detectable this is not save. Signed-off-by: Uwe Kleine-König Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt index b800070..fa6a942 100644 --- a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt @@ -7,6 +7,11 @@ Required properties: region. - interrupts: rtc alarm interrupt +Optional properties: +- stmp,crystal-freq: override crystal frequency as determined from fuse bits. + Only <32000> and <32768> are possible for the hardware. Use <0> for + "no crystal". + Example: rtc@80056000 { diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 2939cdc..eb09edd 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -42,6 +42,8 @@ #define STMP3XXX_RTC_STAT 0x10 #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 +#define STMP3XXX_RTC_STAT_XTAL32000_PRESENT 0x10000000 +#define STMP3XXX_RTC_STAT_XTAL32768_PRESENT 0x08000000 #define STMP3XXX_RTC_SECONDS 0x30 @@ -52,9 +54,13 @@ #define STMP3XXX_RTC_PERSISTENT0 0x60 #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 +#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2) +#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ (1 << 6) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE (1 << 7) #define STMP3XXX_RTC_PERSISTENT1 0x70 /* missing bitmask in headers */ @@ -248,6 +254,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) { struct stmp3xxx_rtc_data *rtc_data; struct resource *r; + u32 rtc_stat; + u32 pers0_set, pers0_clr; + u32 crystalfreq = 0; int err; rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL); @@ -268,8 +277,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) rtc_data->irq_alarm = platform_get_irq(pdev, 0); - if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & - STMP3XXX_RTC_STAT_RTC_PRESENT)) { + rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT); + if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) { dev_err(&pdev->dev, "no device onboard\n"); return -ENODEV; } @@ -282,9 +291,54 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) return err; } + /* + * Obviously the rtc needs a clock input to be able to run. + * This clock can be provided by an external 32k crystal. If that one is + * missing XTAL must not be disabled in suspend which consumes a + * lot of power. Normally the presence and exact frequency (supported + * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality + * proves these fuses are not blown correctly on all machines, so the + * frequency can be overridden in the device tree. + */ + if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT) + crystalfreq = 32000; + else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT) + crystalfreq = 32768; + + of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq", + &crystalfreq); + + switch (crystalfreq) { + case 32000: + /* keep 32kHz crystal running in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | + STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; + break; + case 32768: + /* keep 32.768kHz crystal running in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ; + break; + default: + dev_warn(&pdev->dev, + "invalid crystal-freq specified in device-tree. Assuming no crystal\n"); + /* fall-through */ + case 0: + /* keep XTAL on in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + } + + writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | - STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, + STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | -- cgit v0.10.2 From e706974dc3e2f44891e736f4a96eb88b60356178 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 16 Apr 2015 12:45:07 -0700 Subject: drivers/rtc/rtc-em3027.c: add device tree support Set the of_match_table for this driver so that devices can be described in the device tree. This device is used in the Trimslice and is already defined in the Trimslice device tree. Signed-off-by: Peter Robinson Cc: Mike Rapoport Cc: Alessandro Zummo Cc: Grant Likely Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index fccf366..4f4930a 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Registers */ #define EM3027_REG_ON_OFF_CTRL 0x00 @@ -135,10 +136,20 @@ static struct i2c_device_id em3027_id[] = { { "em3027", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, em3027_id); + +#ifdef CONFIG_OF +static const struct of_device_id em3027_of_match[] = { + { .compatible = "emmicro,em3027", }, + {} +}; +MODULE_DEVICE_TABLE(of, em3027_of_match); +#endif static struct i2c_driver em3027_driver = { .driver = { .name = "rtc-em3027", + .of_match_table = of_match_ptr(em3027_of_match), }, .probe = &em3027_probe, .id_table = em3027_id, -- cgit v0.10.2 From 86e66604fca053e5ecb2427538aa233637119409 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 16 Apr 2015 12:45:09 -0700 Subject: drivers/rtc/rtc-x1205.c: use sign_extend32() for sign extension Despite its name, sign_extend32() is safe to use for 8 bit types too. (See https://lkml.org/lkml/2015/1/18/289). Signed-off-by: Martin Kepplinger Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index b1de58e..5638b7b 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -22,6 +22,7 @@ #include #include #include +#include #define DRV_VERSION "1.0.8" @@ -366,8 +367,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim) * perform sign extension. The formula is * Catr = (atr * 0.25pF) + 11.00pF. */ - if (atr & 0x20) - atr |= 0xC0; + atr = sign_extend32(atr, 5); dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr); -- cgit v0.10.2 From aed98b9a1be6fcf1685dfd37f0a3e78e92a21f7d Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Thu, 16 Apr 2015 12:45:12 -0700 Subject: rtc: hctosys: do not treat lack of RTC device as error When using device trees on the ARM platform, it is not certain at compile time whether or not the system will have a RTC. If one enables CONFIG_HCTOSYS just in case the system booted has a RTC, and it turns out not to be, this will result in a big fat "unable to open rtc device" error being printed to console, even when "quiet" is set in the kernel cmdline. Fix this by outputting the message with loglevel info instead. Signed-off-by: Floris Bos Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 6c719f2..fb4251d 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -32,7 +32,7 @@ static int __init rtc_hctosys(void) struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { - pr_err("%s: unable to open rtc device (%s)\n", + pr_info("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } -- cgit v0.10.2 From 24e1455493dae5ce4b15f83d6ad549befd15f980 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 16 Apr 2015 12:45:15 -0700 Subject: drivers/rtc/rtc-s3c.c: delete duplicate clock control The current functions in s3c-rtc driver execute clk_enable/disable() to control clocks and some functions execute s3c_rtc_alarm_clk_enable() unnecessarily. So this patch deletes the duplicate clock control and spilts s3c_rtc_alarm_clk_enable() out as s3c_rtc_enable_clk()/s3c_rtc_disable_clk() to improve readability. Signed-off-by: Chanwoo Choi Cc: Alessandro Zummo Cc: Kukjin Kim Cc: Inki Dae Cc: Kyungmin Park Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f4cf685..fb0c569 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -39,7 +39,6 @@ struct s3c_rtc { void __iomem *base; struct clk *rtc_clk; struct clk *rtc_src_clk; - bool enabled; struct s3c_rtc_data *data; @@ -67,26 +66,25 @@ struct s3c_rtc_data { void (*disable) (struct s3c_rtc *info); }; -static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) +static void s3c_rtc_enable_clk(struct s3c_rtc *info) { unsigned long irq_flags; spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); - if (enable) { - if (!info->enabled) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - info->enabled = true; - } - } else { - if (info->enabled) { - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - info->enabled = false; - } - } + clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); + spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); +} + +static void s3c_rtc_disable_clk(struct s3c_rtc *info) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); + clk_disable(info->rtc_clk); spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); } @@ -119,20 +117,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); + tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; if (enabled) tmp |= S3C2410_RTCALM_ALMEN; writeb(tmp, info->base + S3C2410_RTCALM); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - s3c_rtc_alarm_clk_enable(info, enabled); + s3c_rtc_disable_clk(info); return 0; } @@ -143,18 +137,12 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) if (!is_power_of_2(freq)) return -EINVAL; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); spin_lock_irq(&info->pie_lock); if (info->data->set_freq) info->data->set_freq(info, freq); spin_unlock_irq(&info->pie_lock); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); return 0; } @@ -165,9 +153,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int have_retried = 0; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); retry_get_time: rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); @@ -194,6 +180,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); + s3c_rtc_disable_clk(info); + rtc_tm->tm_year += 100; dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n", @@ -202,10 +190,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon -= 1; - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return rtc_valid_tm(rtc_tm); } @@ -225,9 +209,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) return -EINVAL; } - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); @@ -236,9 +218,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; } @@ -249,9 +229,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *alm_tm = &alrm->time; unsigned int alm_en; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); @@ -262,6 +240,8 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) alm_en = readb(info->base + S3C2410_RTCALM); + s3c_rtc_disable_clk(info); + alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", @@ -269,9 +249,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); - /* decode the alarm enable field */ - if (alm_en & S3C2410_RTCALM_SECEN) alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); else @@ -304,10 +282,6 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) else alm_tm->tm_year = -1; - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } @@ -317,15 +291,13 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; unsigned int alrm_en; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", alrm->enabled, 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + s3c_rtc_enable_clk(info); + alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; writeb(0x00, info->base + S3C2410_RTCALM); @@ -348,11 +320,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) writeb(alrm_en, info->base + S3C2410_RTCALM); - s3c_rtc_setaie(dev, alrm->enabled); + s3c_rtc_disable_clk(info); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_setaie(dev, alrm->enabled); return 0; } @@ -361,16 +331,12 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); if (info->data->enable_tick) info->data->enable_tick(info, seq); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; } @@ -388,10 +354,6 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) { unsigned int con, tmp; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); /* re-enable the device, and check it is ok */ if ((con & S3C2410_RTCCON_RTCEN) == 0) { @@ -417,20 +379,12 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) writew(tmp & ~S3C2410_RTCCON_CLKRST, info->base + S3C2410_RTCCON); } - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static void s3c24xx_rtc_disable(struct s3c_rtc *info) { unsigned int con; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); con &= ~S3C2410_RTCCON_RTCEN; writew(con, info->base + S3C2410_RTCCON); @@ -438,28 +392,16 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info) con = readb(info->base + S3C2410_TICNT); con &= ~S3C2410_TICNT_ENABLE; writeb(con, info->base + S3C2410_TICNT); - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static void s3c6410_rtc_disable(struct s3c_rtc *info) { unsigned int con; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); con &= ~S3C64XX_RTCCON_TICEN; con &= ~S3C2410_RTCCON_RTCEN; writew(con, info->base + S3C2410_RTCCON); - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static int s3c_rtc_remove(struct platform_device *pdev) @@ -598,15 +540,16 @@ static int s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(info, 1); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; err_nortc: if (info->data->disable) info->data->disable(info); + + if (info->data->needs_src_clk) + clk_disable_unprepare(info->rtc_src_clk); clk_disable_unprepare(info->rtc_clk); return ret; @@ -618,9 +561,7 @@ static int s3c_rtc_suspend(struct device *dev) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); /* save TICNT for anyone using periodic interrupts */ if (info->data->save_tick_cnt) @@ -636,10 +577,6 @@ static int s3c_rtc_suspend(struct device *dev) dev_err(dev, "enable_irq_wake failed\n"); } - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } @@ -647,25 +584,19 @@ static int s3c_rtc_resume(struct device *dev) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - if (info->data->enable) info->data->enable(info); if (info->data->restore_tick_cnt) info->data->restore_tick_cnt(info); + s3c_rtc_disable_clk(info); + if (device_may_wakeup(dev) && info->wake_en) { disable_irq_wake(info->irq_alarm); info->wake_en = false; } - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } #endif @@ -673,29 +604,13 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - - s3c_rtc_alarm_clk_enable(info, false); } static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); writeb(mask, info->base + S3C2410_INTP); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - - s3c_rtc_alarm_clk_enable(info, false); } static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq) -- cgit v0.10.2 From ac2a2726661a8f8f74af0d499cb16b3adf90d764 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:18 -0700 Subject: drivers/rtc/rtc-ab-b5ze-s3.c: constify struct regmap_config The regmap_config struct may be const because it is not modified by the driver and regmap_init() accepts pointer to const. Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index cfc2ef9..b5cbc1b 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -881,7 +881,7 @@ static const struct rtc_class_ops rtc_ops = { .alarm_irq_enable = abb5zes3_rtc_alarm_irq_enable, }; -static struct regmap_config abb5zes3_rtc_regmap_config = { +static const struct regmap_config abb5zes3_rtc_regmap_config = { .reg_bits = 8, .val_bits = 8, }; -- cgit v0.10.2 From 269812de8b1c28cd477a3f9cc9793047f0de530e Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Thu, 16 Apr 2015 12:45:21 -0700 Subject: drivers/rtc/rtc-ds1685.c: remove .owner assignment from platform_driver The rtc driver core now sets the platform_driver 'owner' property, so remove the assignment from the DS1685 driver. Fixes: aaaf5fbf56f1: "rtc: add driver for DS1685 family of real time clocks" Signed-off-by: Joshua Kinard Reported-by: kbuild test robot Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 803869c..7a7c8de 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -2139,7 +2139,6 @@ ds1685_rtc_remove(struct platform_device *pdev) static struct platform_driver ds1685_rtc_driver = { .driver = { .name = "rtc-ds1685", - .owner = THIS_MODULE, }, .probe = ds1685_rtc_probe, .remove = ds1685_rtc_remove, -- cgit v0.10.2 From 52ef84d566dc145b4d469f06667c5fa3118fdd44 Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Thu, 16 Apr 2015 12:45:23 -0700 Subject: drivers/rtc/rtc-ds1685.c: fix sparse warnings Fix two minor sparse warnings: CHECK drivers/rtc/rtc-ds1685.c drivers/rtc/rtc-ds1685.c:2178:1: warning: function 'ds1685_rtc_poweroff' with external linkage has definition drivers/rtc/rtc-ds1685.c:802:23: warning: Using plain integer as NULL pointer Fixes: aaaf5fbf56f1 ("rtc: add driver for DS1685 family of real time clocks") Signed-off-by: Joshua Kinard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 7a7c8de..7020209 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -799,7 +799,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) struct platform_device *pdev = to_platform_device(dev); struct ds1685_priv *rtc = platform_get_drvdata(pdev); u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8]; - char *model = '\0'; + char *model; #ifdef CONFIG_RTC_DS1685_PROC_REGS char bits[NUM_REGS][(NUM_BITS * NUM_SPACES) + NUM_BITS + 1]; #endif @@ -2174,7 +2174,7 @@ module_exit(ds1685_rtc_exit); * ds1685_rtc_poweroff - uses the RTC chip to power the system off. * @pdev: pointer to platform_device structure. */ -extern void __noreturn +void __noreturn ds1685_rtc_poweroff(struct platform_device *pdev) { u8 ctrla, ctrl4a, ctrl4b; -- cgit v0.10.2 From 03cc1625e1f2e9fc6910af4174c942d56292f556 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:26 -0700 Subject: drivers/rtc/rtc-da9052.c: add extra reads with timeouts to avoid returning partially updated values The RTC is in a different clock domain so a quick read after write can retrieve a mangled value of the old/new values Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 613c43b..ead02fa 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,8 @@ #define rtc_err(rtc, fmt, ...) \ dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) +#define DA9052_GET_TIME_RETRIES 5 + struct da9052_rtc { struct rtc_device *rtc; struct da9052 *da9052; @@ -58,22 +61,43 @@ static irqreturn_t da9052_rtc_irq(int irq, void *data) static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) { int ret; - uint8_t v[5]; + uint8_t v[2][5]; + int idx = 1; + int timeout = DA9052_GET_TIME_RETRIES; - ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v); - if (ret != 0) { + ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, &v[0][0]); + if (ret) { rtc_err(rtc, "Failed to group read ALM: %d\n", ret); return ret; } - rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100; - rtc_tm->tm_mon = (v[3] & DA9052_RTC_MONTH) - 1; - rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY; - rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR; - rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; + do { + ret = da9052_group_read(rtc->da9052, + DA9052_ALARM_MI_REG, 5, &v[idx][0]); + if (ret) { + rtc_err(rtc, "Failed to group read ALM: %d\n", ret); + return ret; + } - ret = rtc_valid_tm(rtc_tm); - return ret; + if (memcmp(&v[0][0], &v[1][0], 5) == 0) { + rtc_tm->tm_year = (v[0][4] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[0][3] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN; + + ret = rtc_valid_tm(rtc_tm); + return ret; + } + + idx = (1-idx); + msleep(20); + + } while (timeout--); + + rtc_err(rtc, "Timed out reading alarm time\n"); + + return -EIO; } static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) @@ -135,24 +159,45 @@ static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc) static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) { struct da9052_rtc *rtc = dev_get_drvdata(dev); - uint8_t v[6]; int ret; + uint8_t v[2][6]; + int idx = 1; + int timeout = DA9052_GET_TIME_RETRIES; - ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); - if (ret < 0) { + ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, &v[0][0]); + if (ret) { rtc_err(rtc, "Failed to read RTC time : %d\n", ret); return ret; } - rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100; - rtc_tm->tm_mon = (v[4] & DA9052_RTC_MONTH) - 1; - rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY; - rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR; - rtc_tm->tm_min = v[1] & DA9052_RTC_MIN; - rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; + do { + ret = da9052_group_read(rtc->da9052, + DA9052_COUNT_S_REG, 6, &v[idx][0]); + if (ret) { + rtc_err(rtc, "Failed to read RTC time : %d\n", ret); + return ret; + } - ret = rtc_valid_tm(rtc_tm); - return ret; + if (memcmp(&v[0][0], &v[1][0], 6) == 0) { + rtc_tm->tm_year = (v[0][5] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[0][4] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[0][3] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[0][2] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN; + rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC; + + ret = rtc_valid_tm(rtc_tm); + return ret; + } + + idx = (1-idx); + msleep(20); + + } while (timeout--); + + rtc_err(rtc, "Timed out reading time\n"); + + return -EIO; } static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) -- cgit v0.10.2 From ae824c484c85d77e3f272515aafb410bbade13fa Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:29 -0700 Subject: drivers/rtc/rtc-da9052.c: add constraints to set valid year Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index ead02fa..acc3e5a 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -206,6 +206,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) uint8_t v[6]; int ret; + /* DA9052 only has 6 bits for year - to represent 2000-2063 */ + if ((tm->tm_year < 100) || (tm->tm_year > 163)) + return -EINVAL; + rtc = dev_get_drvdata(dev); v[0] = tm->tm_sec; @@ -243,6 +247,10 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; struct da9052_rtc *rtc = dev_get_drvdata(dev); + /* DA9052 only has 6 bits for year - to represent 2000-2063 */ + if ((tm->tm_year < 100) || (tm->tm_year > 163)) + return -EINVAL; + ret = da9052_rtc_enable_alarm(rtc, 0); if (ret < 0) return ret; -- cgit v0.10.2 From d174a024007dd543fd066cffd8eb727806a62da6 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:32 -0700 Subject: drivers/rtc/rtc-da9052.c: register ability of alarm to wake device from suspend Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index acc3e5a..1ba4371 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -309,6 +309,8 @@ static int da9052_rtc_probe(struct platform_device *pdev) return ret; } + device_init_wakeup(&pdev->dev, true); + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &da9052_rtc_ops, THIS_MODULE); return PTR_ERR_OR_ZERO(rtc->rtc); -- cgit v0.10.2 From b3288a43b4dacd2b4d2b24726d7b469d8ade5120 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 16 Apr 2015 12:45:34 -0700 Subject: drivers/rtc/rtc-hym8563.c: return clock rate even when clock is disabled When the clock is disabled, do not return a rate of 0 but instead return the rate the clock will be running at after it gets enabled. This prevents problems when the core clock code is trying to determine a suitable rate, while the clock is still off. Signed-off-by: Heiko Stuebner Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index b936bb4..d4a6561 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -309,7 +309,7 @@ static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw, struct i2c_client *client = hym8563->client; int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); - if (ret < 0 || ret & HYM8563_CLKOUT_DISABLE) + if (ret < 0) return 0; ret &= HYM8563_CLKOUT_MASK; -- cgit v0.10.2 From 71b800b628570ce315a3f820b79969e460cd297f Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 16 Apr 2015 12:45:37 -0700 Subject: rtc: digicolor: document device tree binding Add a device tree binding documentation to the Real Time Clock hardware block on the Conexant CX92755 SoC. The CX92755 is from the Digicolor SoCs series. Other SoCs in that series may share the same hardware block. Signed-off-by: Baruch Siach Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/devicetree/bindings/rtc/digicolor-rtc.txt b/Documentation/devicetree/bindings/rtc/digicolor-rtc.txt new file mode 100644 index 0000000..d464986 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/digicolor-rtc.txt @@ -0,0 +1,17 @@ +Conexant Digicolor Real Time Clock controller + +This binding currently supports the CX92755 SoC. + +Required properties: +- compatible: should be "cnxt,cx92755-rtc" +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: rtc alarm interrupt + +Example: + + rtc@f0000c30 { + compatible = "cnxt,cx92755-rtc"; + reg = <0xf0000c30 0x18>; + interrupts = <25>; + }; -- cgit v0.10.2 From ba17220878bf74b95ea24de568939e7b9e1b02db Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 16 Apr 2015 12:45:40 -0700 Subject: rtc: driver for Conexant Digicolor CX92755 on-chip RTC Add driver for the RTC hardware block on the Conexant CX92755 SoC, from the Digicolor series of SoCs. Tested on the Equinox evaluation board for the CX92755 chip. [akpm@linux-foundation.org: build command arrays at compile-time] Signed-off-by: Baruch Siach Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b5b5c3d..faeee2d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1111,6 +1111,16 @@ config RTC_DRV_DAVINCI This driver can also be built as a module. If so, the module will be called rtc-davinci. +config RTC_DRV_DIGICOLOR + tristate "Conexant Digicolor RTC" + depends on ARCH_DIGICOLOR + help + If you say yes here you get support for the RTC on Conexant + Digicolor platforms. This currently includes the CX92755 SoC. + + This driver can also be built as a module. If so, the module + will be called rtc-digicolor. + config RTC_DRV_IMXDI tristate "Freescale IMX DryIce Real Time Clock" depends on ARCH_MXC diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 69c8706..c31731c 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o +obj-$(CONFIG_RTC_DRV_DIGICOLOR) += rtc-digicolor.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o diff --git a/drivers/rtc/rtc-digicolor.c b/drivers/rtc/rtc-digicolor.c new file mode 100644 index 0000000..8d05596 --- /dev/null +++ b/drivers/rtc/rtc-digicolor.c @@ -0,0 +1,227 @@ +/* + * Real Time Clock driver for Conexant Digicolor + * + * Copyright (C) 2015 Paradox Innovation Ltd. + * + * Author: Baruch Siach + * + * 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 +#include +#include +#include + +#define DC_RTC_CONTROL 0x0 +#define DC_RTC_TIME 0x8 +#define DC_RTC_REFERENCE 0xc +#define DC_RTC_ALARM 0x10 +#define DC_RTC_INTFLAG_CLEAR 0x14 +#define DC_RTC_INTENABLE 0x16 + +#define DC_RTC_CMD_MASK 0xf +#define DC_RTC_GO_BUSY BIT(7) + +#define CMD_NOP 0 +#define CMD_RESET 1 +#define CMD_WRITE 3 +#define CMD_READ 4 + +#define CMD_DELAY_US (10*1000) +#define CMD_TIMEOUT_US (500*CMD_DELAY_US) + +struct dc_rtc { + struct rtc_device *rtc_dev; + void __iomem *regs; +}; + +static int dc_rtc_cmds(struct dc_rtc *rtc, const u8 *cmds, int len) +{ + u8 val; + int i, ret; + + for (i = 0; i < len; i++) { + writeb_relaxed((cmds[i] & DC_RTC_CMD_MASK) | DC_RTC_GO_BUSY, + rtc->regs + DC_RTC_CONTROL); + ret = readb_relaxed_poll_timeout( + rtc->regs + DC_RTC_CONTROL, val, + !(val & DC_RTC_GO_BUSY), CMD_DELAY_US, CMD_TIMEOUT_US); + if (ret < 0) + return ret; + } + + return 0; +} + +static int dc_rtc_read(struct dc_rtc *rtc, unsigned long *val) +{ + static const u8 read_cmds[] = {CMD_READ, CMD_NOP}; + u32 reference, time1, time2; + int ret; + + ret = dc_rtc_cmds(rtc, read_cmds, ARRAY_SIZE(read_cmds)); + if (ret < 0) + return ret; + + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + time1 = readl_relaxed(rtc->regs + DC_RTC_TIME); + /* Read twice to ensure consistency */ + while (1) { + time2 = readl_relaxed(rtc->regs + DC_RTC_TIME); + if (time1 == time2) + break; + time1 = time2; + } + + *val = reference + time1; + return 0; +} + +static int dc_rtc_write(struct dc_rtc *rtc, u32 val) +{ + static const u8 write_cmds[] = {CMD_WRITE, CMD_NOP, CMD_RESET, CMD_NOP}; + + writel_relaxed(val, rtc->regs + DC_RTC_REFERENCE); + return dc_rtc_cmds(rtc, write_cmds, ARRAY_SIZE(write_cmds)); +} + +static int dc_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + unsigned long now; + int ret; + + ret = dc_rtc_read(rtc, &now); + if (ret < 0) + return ret; + rtc_time64_to_tm(now, tm); + + return 0; +} + +static int dc_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + + return dc_rtc_write(rtc, secs); +} + +static int dc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + u32 alarm_reg, reference; + unsigned long now; + int ret; + + alarm_reg = readl_relaxed(rtc->regs + DC_RTC_ALARM); + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + rtc_time64_to_tm(reference + alarm_reg, &alarm->time); + + ret = dc_rtc_read(rtc, &now); + if (ret < 0) + return ret; + + alarm->pending = alarm_reg + reference > now; + alarm->enabled = readl_relaxed(rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static int dc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + time64_t alarm_time; + u32 reference; + + alarm_time = rtc_tm_to_time64(&alarm->time); + + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + writel_relaxed(alarm_time - reference, rtc->regs + DC_RTC_ALARM); + + writeb_relaxed(!!alarm->enabled, rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static int dc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + + writeb_relaxed(!!enabled, rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static struct rtc_class_ops dc_rtc_ops = { + .read_time = dc_rtc_read_time, + .set_mmss = dc_rtc_set_mmss, + .read_alarm = dc_rtc_read_alarm, + .set_alarm = dc_rtc_set_alarm, + .alarm_irq_enable = dc_rtc_alarm_irq_enable, +}; + +static irqreturn_t dc_rtc_irq(int irq, void *dev_id) +{ + struct dc_rtc *rtc = dev_id; + + writeb_relaxed(1, rtc->regs + DC_RTC_INTFLAG_CLEAR); + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; +} + +static int __init dc_rtc_probe(struct platform_device *pdev) +{ + struct resource *res; + struct dc_rtc *rtc; + int irq, ret; + + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rtc->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rtc->regs)) + return PTR_ERR(rtc->regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + ret = devm_request_irq(&pdev->dev, irq, dc_rtc_irq, 0, pdev->name, rtc); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, rtc); + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, + &dc_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + + return 0; +} + +static const struct of_device_id dc_dt_ids[] = { + { .compatible = "cnxt,cx92755-rtc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_dt_ids); + +static struct platform_driver dc_rtc_driver = { + .driver = { + .name = "digicolor_rtc", + .of_match_table = of_match_ptr(dc_dt_ids), + }, +}; +module_platform_driver_probe(dc_rtc_driver, dc_rtc_probe); + +MODULE_AUTHOR("Baruch Siach "); +MODULE_DESCRIPTION("Conexant Digicolor Realtime Clock Driver (RTC)"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 7c6f84f8df02a17ad3da5e38abc8b8abff122d39 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 16 Apr 2015 12:45:43 -0700 Subject: MAINTAINERS: Add Alexandre Belloni as an RTC maintainer I've noticed that most of the patches for the RTC subsystem are currently either taken directly by Andrew or going through another maintainer's tree, quite often without an Acked-by or Reviewed-by tag. I'd like to propose myself as the RTC subsystem co-maintainer, to mainly help Alessandro reviewing incoming patches and maintain a subsystem tree to avoid having the RTC patches going through trees when they have no particular dependencies. Signed-off-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 56a432d..8b0a0c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8183,6 +8183,7 @@ X: kernel/torture.c REAL TIME CLOCK (RTC) SUBSYSTEM M: Alessandro Zummo +M: Alexandre Belloni L: rtc-linux@googlegroups.com Q: http://patchwork.ozlabs.org/project/rtc-linux/list/ S: Maintained -- cgit v0.10.2 From 5281f94ae7f54d2d1a48dbc10223fd12d2aea716 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:45 -0700 Subject: drivers/rtc/rtc-s5m.c: add support for S2MPS13 RTC The S2MPS13 RTC is almost the same as S2MPS14. The differences when updating alarm are: 1. Set WUDR+AUDR field instead of WUDR+RUDR. 2. Clear the AUDR field later (it is not auto-cleared). Signed-off-by: Krzysztof Kozlowski Cc: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 4008b84..f0cb0ec 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -187,6 +187,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, val &= S5M_ALARM0_STATUS; break; case S2MPS14X: + case S2MPS13X: ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, &val); val &= S2MPS_ALARM0_STATUS; @@ -252,6 +253,9 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) case S2MPS14X: data |= S2MPS_RTC_RUDR_MASK; break; + case S2MPS13X: + data |= S2MPS13_RTC_AUDR_MASK; + break; default: return -EINVAL; } @@ -265,6 +269,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) ret = s5m8767_wait_for_udr_update(info); + /* On S2MPS13 the AUDR is not auto-cleared */ + if (info->device_type == S2MPS13X) + regmap_update_bits(info->regmap, info->regs->rtc_udr_update, + S2MPS13_RTC_AUDR_MASK, 0); + return ret; } @@ -306,7 +315,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 data[info->regs->regs_count]; int ret; - if (info->device_type == S2MPS14X) { + if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) { ret = regmap_update_bits(info->regmap, info->regs->rtc_udr_update, S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK); @@ -329,6 +338,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); break; @@ -355,6 +365,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) break; case S5M8767X: case S2MPS14X: + case S2MPS13X: ret = s5m8767_tm_to_data(tm, data); break; default: @@ -402,6 +413,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); alrm->enabled = 0; for (i = 0; i < info->regs->regs_count; i++) { @@ -450,6 +462,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) case S5M8767X: case S2MPS14X: + case S2MPS13X: for (i = 0; i < info->regs->regs_count; i++) data[i] &= ~ALARM_ENABLE_MASK; @@ -494,6 +507,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) case S5M8767X: case S2MPS14X: + case S2MPS13X: data[RTC_SEC] |= ALARM_ENABLE_MASK; data[RTC_MIN] |= ALARM_ENABLE_MASK; data[RTC_HOUR] |= ALARM_ENABLE_MASK; @@ -533,6 +547,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_tm_to_data(&alrm->time, data); break; @@ -615,6 +630,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) break; case S2MPS14X: + case S2MPS13X: data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); ret = regmap_write(info->regmap, info->regs->ctrl, data[0]); break; @@ -652,6 +668,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) switch (pdata->device_type) { case S2MPS14X: + case S2MPS13X: regmap_cfg = &s2mps14_rtc_regmap_config; info->regs = &s2mps_rtc_regs; alarm_irq = S2MPS14_IRQ_RTCA0; @@ -772,6 +789,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); static const struct platform_device_id s5m_rtc_id[] = { { "s5m-rtc", S5M8767X }, + { "s2mps13-rtc", S2MPS13X }, { "s2mps14-rtc", S2MPS14X }, { }, }; diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index b6401e7..29c30ac 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -105,6 +105,8 @@ enum s2mps_rtc_reg { #define S5M_RTC_UDR_MASK (1 << S5M_RTC_UDR_SHIFT) #define S2MPS_RTC_WUDR_SHIFT 4 #define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) +#define S2MPS13_RTC_AUDR_SHIFT 1 +#define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT) #define S2MPS_RTC_RUDR_SHIFT 0 #define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) #define RTC_TCON_SHIFT 1 -- cgit v0.10.2 From 182683e955af4dd2324427129f3b90558d644066 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:48 -0700 Subject: drivers/rtc/class.c: initialize rtc name early In some error cases RTC name is used before it is initialized: rtc-rs5c372 0-0032: clock needs to be set rtc-rs5c372 0-0032: rs5c372b found, 24hr, driver version 0.6 rtc (null): read_time: fail to read rtc-rs5c372 0-0032: rtc core: registered rtc-rs5c372 as rtc0 Fix by initializing the name early. Signed-off-by: Aaro Koskinen Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index c29ba7e..ea2a315 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -221,15 +221,15 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, rtc->pie_timer.function = rtc_pie_update_irq; rtc->pie_enabled = 0; + strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); + dev_set_name(&rtc->dev, "rtc%d", id); + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); if (!err && !rtc_valid_tm(&alrm.time)) rtc_initialize_alarm(rtc, &alrm); - strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); - dev_set_name(&rtc->dev, "rtc%d", id); - rtc_dev_prepare(rtc); err = device_register(&rtc->dev); -- cgit v0.10.2 From d0bddb512d9c8e1adefc7416ef6c71cba05d62c8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:51 -0700 Subject: drivers/rtc/interface.c: __rtc_read_time: reduce log level __rtc_read_time logs should be debug logs instead of error logs. For example, when the RTC clock is not set, it's not really useful to print a kernel error log every time someone tries to read the clock: ~ # hwclock -r [ 604.508263] rtc rtc0: read_time: fail to read hwclock: RTC_RD_TIME: Invalid argument If there's a real error, it's likely that lower level or higher level code will tell it anyway. Make these logs debug logs, and also print the error code for the read failure. Signed-off-by: Aaro Koskinen Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index d43ee40..166fc60 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -31,13 +31,14 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) memset(tm, 0, sizeof(struct rtc_time)); err = rtc->ops->read_time(rtc->dev.parent, tm); if (err < 0) { - dev_err(&rtc->dev, "read_time: fail to read\n"); + dev_dbg(&rtc->dev, "read_time: fail to read: %d\n", + err); return err; } err = rtc_valid_tm(tm); if (err < 0) - dev_err(&rtc->dev, "read_time: rtc_time isn't valid\n"); + dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n"); } return err; } -- cgit v0.10.2 From 521fca18e828cddc94535a1ea5ac33460f1de679 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:54 -0700 Subject: rtc: hctosys: use function name in the error log Use function name in the error log instead of __FILE__. Signed-off-by: Aaro Koskinen Cc: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index fb4251d..91fb5f3 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -33,7 +33,7 @@ static int __init rtc_hctosys(void) if (rtc == NULL) { pr_info("%s: unable to open rtc device (%s)\n", - __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); + __func__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } -- cgit v0.10.2 From 202fe4c27f427c48ca5660277d743ee8b43fc200 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:57 -0700 Subject: drivers/rtc/rtc-s3c.c: fix failed first read of RTC time Initialize the device time (if it is wrong) before registering RTC device to fix following error message during rtc-s3c probe: [ 2.215414] rtc (null): read_time: fail to read [ 2.216322] s3c-rtc 10070000.rtc: rtc core: registered s3c as rtc1 Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: Marek Szyprowski Reviewed-by: Chanwoo Choi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fb0c569..a313b9b 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -496,6 +496,22 @@ static int s3c_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); + /* Check RTC Time */ + s3c_rtc_gettime(&pdev->dev, &rtc_tm); + + if (rtc_valid_tm(&rtc_tm)) { + rtc_tm.tm_year = 100; + rtc_tm.tm_mon = 0; + rtc_tm.tm_mday = 1; + rtc_tm.tm_hour = 0; + rtc_tm.tm_min = 0; + rtc_tm.tm_sec = 0; + + s3c_rtc_settime(&pdev->dev, &rtc_tm); + + dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); + } + /* register RTC and exit */ info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, THIS_MODULE); @@ -519,22 +535,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) goto err_nortc; } - /* Check RTC Time */ - s3c_rtc_gettime(&pdev->dev, &rtc_tm); - - if (rtc_valid_tm(&rtc_tm)) { - rtc_tm.tm_year = 100; - rtc_tm.tm_mon = 0; - rtc_tm.tm_mday = 1; - rtc_tm.tm_hour = 0; - rtc_tm.tm_min = 0; - rtc_tm.tm_sec = 0; - - s3c_rtc_settime(&pdev->dev, &rtc_tm); - - dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); - } - if (info->data->select_tick_clk) info->data->select_tick_clk(info); -- cgit v0.10.2 From 9c28bd07c20776cc04aecf04ba5be53fa5fa6dd2 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:00 -0700 Subject: drivers/rtc/rtc-omap.c: unlock and lock rtc registers before and after register writes RTC module contains a kicker mechanism to prevent any spurious writes from changing the register values. This mechanism requires two MMR writes to the KICK0 and KICK1 registers with exact data values before the kicker lock mechanism is released. Currently the driver release the lock in the probe and leaves it enabled until the rtc driver removal. This eliminates the idea of preventing spurious writes when RTC driver is loaded. So implement rtc lock and unlock functions before and after register writes. This is as advised by Paul to implement lock and unlock functions in the driver and not to unlock and leave it in probe. The same discussion can be seen here: http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg111588.html Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 8e5851a..a5ff009 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -118,12 +118,15 @@ #define KICK0_VALUE 0x83e70b13 #define KICK1_VALUE 0x95a4f1e0 +struct omap_rtc; + struct omap_rtc_device_type { bool has_32kclk_en; - bool has_kicker; bool has_irqwakeen; bool has_pmic_mode; bool has_power_up_reset; + void (*lock)(struct omap_rtc *rtc); + void (*unlock)(struct omap_rtc *rtc); }; struct omap_rtc { @@ -156,6 +159,26 @@ static inline void rtc_writel(struct omap_rtc *rtc, unsigned int reg, u32 val) writel(val, rtc->base + reg); } +static void am3352_rtc_unlock(struct omap_rtc *rtc) +{ + rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); + rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); +} + +static void am3352_rtc_lock(struct omap_rtc *rtc) +{ + rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc_writel(rtc, OMAP_RTC_KICK1_REG, 0); +} + +static void default_rtc_unlock(struct omap_rtc *rtc) +{ +} + +static void default_rtc_lock(struct omap_rtc *rtc) +{ +} + /* * We rely on the rtc framework to handle locking (rtc->ops_lock), * so the only other requirement is that register accesses which @@ -186,7 +209,9 @@ static irqreturn_t rtc_irq(int irq, void *dev_id) /* alarm irq? */ if (irq_data & OMAP_RTC_STATUS_ALARM) { + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM); + rtc->type->lock(rtc); events |= RTC_IRQF | RTC_AF; } @@ -218,9 +243,11 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; } rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); if (rtc->type->has_irqwakeen) rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); + rtc->type->lock(rtc); local_irq_enable(); return 0; @@ -293,12 +320,14 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm) local_irq_disable(); rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year); rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon); rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday); rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour); rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min); rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec); + rtc->type->lock(rtc); local_irq_enable(); @@ -341,6 +370,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) local_irq_disable(); rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year); rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon); rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday); @@ -362,6 +392,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); if (rtc->type->has_irqwakeen) rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); + rtc->type->lock(rtc); local_irq_enable(); @@ -391,6 +422,7 @@ static void omap_rtc_power_off(void) unsigned long now; u32 val; + rtc->type->unlock(rtc); /* enable pmic_power_en control */ val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); @@ -423,6 +455,7 @@ static void omap_rtc_power_off(void) val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, val | OMAP_RTC_INTERRUPTS_IT_ALARM2); + rtc->type->lock(rtc); /* * Wait for alarm to trigger (within two seconds) and external PMIC to @@ -442,17 +475,21 @@ static struct rtc_class_ops omap_rtc_ops = { static const struct omap_rtc_device_type omap_rtc_default_type = { .has_power_up_reset = true, + .lock = default_rtc_lock, + .unlock = default_rtc_unlock, }; static const struct omap_rtc_device_type omap_rtc_am3352_type = { .has_32kclk_en = true, - .has_kicker = true, .has_irqwakeen = true, .has_pmic_mode = true, + .lock = am3352_rtc_lock, + .unlock = am3352_rtc_unlock, }; static const struct omap_rtc_device_type omap_rtc_da830_type = { - .has_kicker = true, + .lock = am3352_rtc_lock, + .unlock = am3352_rtc_unlock, }; static const struct platform_device_id omap_rtc_id_table[] = { @@ -527,10 +564,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - if (rtc->type->has_kicker) { - rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); - rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); - } + rtc->type->unlock(rtc); /* * disable interrupts @@ -593,6 +627,8 @@ static int __init omap_rtc_probe(struct platform_device *pdev) if (reg != new_ctrl) rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); + rtc->type->lock(rtc); + device_init_wakeup(&pdev->dev, true); rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, @@ -626,8 +662,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) err: device_init_wakeup(&pdev->dev, false); - if (rtc->type->has_kicker) - rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc->type->lock(rtc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -646,11 +681,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); + rtc->type->unlock(rtc); /* leave rtc running, but disable irqs */ rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); - if (rtc->type->has_kicker) - rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc->type->lock(rtc); /* Disable the clock/module */ pm_runtime_put_sync(&pdev->dev); @@ -666,6 +701,7 @@ static int omap_rtc_suspend(struct device *dev) rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); + rtc->type->unlock(rtc); /* * FIXME: the RTC alarm is not currently acting as a wakeup event * source on some platforms, and in fact this enable() call is just @@ -675,6 +711,7 @@ static int omap_rtc_suspend(struct device *dev) enable_irq_wake(rtc->irq_alarm); else rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); + rtc->type->lock(rtc); /* Disable the clock/module */ pm_runtime_put_sync(dev); @@ -689,10 +726,12 @@ static int omap_rtc_resume(struct device *dev) /* Enable the clock/module so that we can access the registers */ pm_runtime_get_sync(dev); + rtc->type->unlock(rtc); if (device_may_wakeup(dev)) disable_irq_wake(rtc->irq_alarm); else rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); + rtc->type->lock(rtc); return 0; } @@ -709,9 +748,11 @@ static void omap_rtc_shutdown(struct platform_device *pdev) * Keep the ALARM interrupt enabled to allow the system to power up on * alarm events. */ + rtc->type->unlock(rtc); mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); mask &= OMAP_RTC_INTERRUPTS_IT_ALARM; rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask); + rtc->type->lock(rtc); } static struct platform_driver omap_rtc_driver = { -- cgit v0.10.2 From 8608976e2bc9c1df090e1b346c65ec1405e9d03d Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:03 -0700 Subject: drivers/rtc/Kconfig: update Kconfig for OMAP RTC RTC is present in AM43xx and DRA7xx also. Updating the Kconfig to depend on ARCH_OMAP or ARCH_DAVINCI Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index faeee2d..6149ae0 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1131,11 +1131,11 @@ config RTC_DRV_IMXDI will be called "rtc-imxdi". config RTC_DRV_OMAP - tristate "TI OMAP1" - depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX + tristate "TI OMAP Real Time Clock" + depends on ARCH_OMAP || ARCH_DAVINCI help Say "yes" here to support the on chip real time clock - present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x. + present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx. This driver can also be built as a module, if so, module will be called rtc-omap. -- cgit v0.10.2 From 5d9094b6c7fc87d1909143540c1e2fddde9129b3 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:05 -0700 Subject: drivers/rtc/rtc-omap.c: use module_platform_driver module_platform_driver_probe() prevents driver from requesting probe deferral. So using module_platform_drive() to support probe deferral. Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index a5ff009..8b6355f 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -521,7 +521,7 @@ static const struct of_device_id omap_rtc_of_match[] = { }; MODULE_DEVICE_TABLE(of, omap_rtc_of_match); -static int __init omap_rtc_probe(struct platform_device *pdev) +static int omap_rtc_probe(struct platform_device *pdev) { struct omap_rtc *rtc; struct resource *res; @@ -756,6 +756,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev) } static struct platform_driver omap_rtc_driver = { + .probe = omap_rtc_probe, .remove = __exit_p(omap_rtc_remove), .shutdown = omap_rtc_shutdown, .driver = { @@ -766,7 +767,7 @@ static struct platform_driver omap_rtc_driver = { .id_table = omap_rtc_id_table, }; -module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); +module_platform_driver(omap_rtc_driver); MODULE_ALIAS("platform:omap_rtc"); MODULE_AUTHOR("George G. Davis (and others)"); -- cgit v0.10.2 From 492da68c8c3babc573208e057a9011d9489f2b5a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:46:08 -0700 Subject: drivers/rtc/rtc-s3c.c: remove one superfluous rtc_valid_tm() check s3c_rtc_gettime() already returns the result of rtc_valid_tm() on the obtained time so get rid of another call to rtc_valid_tm(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Cc: Alexandre Belloni Cc: Alessandro Zummo Cc: Marek Szyprowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a313b9b..76cbad7 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -497,9 +497,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); /* Check RTC Time */ - s3c_rtc_gettime(&pdev->dev, &rtc_tm); - - if (rtc_valid_tm(&rtc_tm)) { + if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) { rtc_tm.tm_year = 100; rtc_tm.tm_mon = 0; rtc_tm.tm_mday = 1; -- cgit v0.10.2 From f539a8acf1070557aef9c5df682751ba2af1005f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Thu, 16 Apr 2015 12:46:11 -0700 Subject: drivers/rtc/rtc-hym8563.c: fix swapped enable/disable of clockout control bit The hym8563 datasheet describes the clock output control-bit as "when set to logic 0, the square wave output is enable, when set to logic 1, the CLKOUT output is inhibited". But in reality the setting is exactly opposite. Before now, the clock output was not really used, but on the rk3288 soc this generated clock is used to supply the temperature sensor block and the swapped bit value prevented it from working. With the corrected value, the tsadc now reports correct values. Signed-off-by: Heiko Stuebner Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index d4a6561..0f710e9 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -66,7 +66,7 @@ #define HYM8563_ALM_BIT_DISABLE BIT(7) #define HYM8563_CLKOUT 0x0d -#define HYM8563_CLKOUT_DISABLE BIT(7) +#define HYM8563_CLKOUT_ENABLE BIT(7) #define HYM8563_CLKOUT_32768 0 #define HYM8563_CLKOUT_1024 1 #define HYM8563_CLKOUT_32 2 @@ -360,9 +360,9 @@ static int hym8563_clkout_control(struct clk_hw *hw, bool enable) return ret; if (enable) - ret &= ~HYM8563_CLKOUT_DISABLE; + ret |= HYM8563_CLKOUT_ENABLE; else - ret |= HYM8563_CLKOUT_DISABLE; + ret &= ~HYM8563_CLKOUT_ENABLE; return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret); } @@ -386,7 +386,7 @@ static int hym8563_clkout_is_prepared(struct clk_hw *hw) if (ret < 0) return ret; - return !(ret & HYM8563_CLKOUT_DISABLE); + return !!(ret & HYM8563_CLKOUT_ENABLE); } static const struct clk_ops hym8563_clkout_ops = { @@ -407,7 +407,7 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563) int ret; ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, - HYM8563_CLKOUT_DISABLE); + 0); if (ret < 0) return ERR_PTR(ret); -- cgit v0.10.2 From a737e835e5769ef22897179ed7f82b1fc50bfa58 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:46:14 -0700 Subject: rtc: use more standard kernel logging styles Neaten the logging a bit by adding #define pr_fmt Miscellanea: o Remove __FILE__/__func__ uses o Coalesce formats adding missing spaces o Align arguments o (rtc-cmos) Integrated 2 consecutive messages Signed-off-by: Joe Perches Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Joshua Kinard Cc: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Cc: Aaro Koskinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 91fb5f3..e1cfa06 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -9,6 +9,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary @@ -32,8 +34,8 @@ static int __init rtc_hctosys(void) struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { - pr_info("%s: unable to open rtc device (%s)\n", - __func__, CONFIG_RTC_HCTOSYS_DEVICE); + pr_info("unable to open rtc device (%s)\n", + CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 87647f4..a82556a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -28,6 +28,9 @@ * interrupts disabled, holding the global rtc_lock, to exclude those * other drivers and utilities on correctly configured systems. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -385,8 +388,7 @@ static bool alarm_disable_quirk; static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) { alarm_disable_quirk = true; - pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); - pr_info("RTC alarms disabled\n"); + pr_info("BIOS has alarm-disable quirk - RTC alarms disabled\n"); return 0; } diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 8605fde..167783f 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -18,6 +18,8 @@ * "Sending and receiving", using SMBus level communication is preferred. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -406,7 +408,7 @@ static int ds1374_wdt_settimeout(unsigned int timeout) /* Set new watchdog time */ ret = ds1374_write_rtc(save_client, timeout, DS1374_REG_WDALM0, 3); if (ret) { - pr_info("rtc-ds1374 - couldn't set new watchdog time\n"); + pr_info("couldn't set new watchdog time\n"); goto out; } @@ -539,12 +541,12 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - pr_info("rtc-ds1374: disable watchdog\n"); + pr_info("disable watchdog\n"); ds1374_wdt_disable(); } if (options & WDIOS_ENABLECARD) { - pr_info("rtc-ds1374: enable watchdog\n"); + pr_info("enable watchdog\n"); ds1374_wdt_settimeout(wdt_margin); ds1374_wdt_ping(); } diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 7020209..818a363 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -16,6 +16,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -2182,7 +2184,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev) /* Check for valid RTC data, else, spin forever. */ if (unlikely(!pdev)) { - pr_emerg("rtc-ds1685: platform device data not available, spinning forever ...\n"); + pr_emerg("platform device data not available, spinning forever ...\n"); unreachable(); } else { /* Get the rtc data. */ diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index adaf06c..7e48e53 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -15,6 +15,8 @@ * "Sending and receiving", using SMBus level communication is preferred. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -373,8 +375,8 @@ static void ds3232_work(struct work_struct *work) if (stat & DS3232_REG_SR_A1F) { control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); if (control < 0) { - pr_warn("Read DS3232 Control Register error." - "Disable IRQ%d.\n", client->irq); + pr_warn("Read Control Register error - Disable IRQ%d\n", + client->irq); } else { /* disable alarm1 interrupt */ control &= ~(DS3232_REG_CR_A1IE); diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c index b40fbe3..1a7f1d1 100644 --- a/drivers/rtc/rtc-efi-platform.c +++ b/drivers/rtc/rtc-efi-platform.c @@ -8,6 +8,9 @@ * Copyright (C) 1999-2000 VA Linux Systems * Copyright (C) 1999-2000 Walt Drummond */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 7ff7427..a82937e 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -13,6 +13,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -513,12 +515,12 @@ static int wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (rv & WDIOS_DISABLECARD) { - pr_info("rtc-m41t80: disable watchdog\n"); + pr_info("disable watchdog\n"); wdt_disable(); } if (rv & WDIOS_ENABLECARD) { - pr_info("rtc-m41t80: enable watchdog\n"); + pr_info("enable watchdog\n"); wdt_ping(); } diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 9d71328..7632a87 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -12,6 +12,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -103,8 +105,8 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("%s: MAX77686 RTC cannot handle the year %d." - "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); + pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + 1900 + tm->tm_year); return -EINVAL; } return 0; diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index 67fbe55..9e02bcd 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -12,6 +12,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -107,8 +109,8 @@ static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("%s: MAX8997 RTC cannot handle the year %d." - "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); + pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + 1900 + tm->tm_year); return -EINVAL; } return 0; @@ -424,7 +426,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable) val = 0; max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val); - pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); + pr_info("WTSR_SMPL(0x%02x)\n", val); } static int max8997_rtc_init_reg(struct max8997_rtc_info *info) diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index 9bf877b..c1c5c4e 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c @@ -7,6 +7,8 @@ * Copyright (C) 1993 Hamish Macdonald */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -111,7 +113,7 @@ static void msm6242_lock(struct msm6242_priv *priv) } if (!cnt) - pr_warn("msm6242: timed out waiting for RTC (0x%x)\n", + pr_warn("timed out waiting for RTC (0x%x)\n", msm6242_read(priv, MSM6242_CD)); } diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c index 95f6521..7061dca 100644 --- a/drivers/rtc/rtc-opal.c +++ b/drivers/rtc/rtc-opal.c @@ -16,8 +16,9 @@ * along with this program. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRVNAME "rtc-opal" -#define pr_fmt(fmt) DRVNAME ": " fmt #include #include diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index f0cb0ec..64baad3 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -15,6 +15,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -146,7 +148,7 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR1] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_err("s5m8767 RTC cannot handle the year %d.\n", + pr_err("RTC cannot handle the year %d\n", 1900 + tm->tm_year); return -EINVAL; } else { diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 5baea3f..2dc787d 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -18,6 +18,8 @@ * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -145,8 +147,7 @@ static int twl_rtc_read_u8(u8 *data, u8 reg) ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl_rtc: Could not read TWL" - "register %X - error %d\n", reg, ret); + pr_err("Could not read TWL register %X - error %d\n", reg, ret); return ret; } @@ -159,8 +160,8 @@ static int twl_rtc_write_u8(u8 data, u8 reg) ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl_rtc: Could not write TWL" - "register %X - error %d\n", reg, ret); + pr_err("Could not write TWL register %X - error %d\n", + reg, ret); return ret; } -- cgit v0.10.2 From 09ad0eae5ed0f354df892b1cfb868338dc578c5c Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:46:17 -0700 Subject: befs: replace typedef befs_mount_options by structure See Documentation/CodingStyle Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/befs/befs.h b/fs/befs/befs.h index 3a7813a..d4751af 100644 --- a/fs/befs/befs.h +++ b/fs/befs/befs.h @@ -19,14 +19,14 @@ typedef u64 befs_blocknr_t; * BeFS in memory structures */ -typedef struct befs_mount_options { +struct befs_mount_options { kgid_t gid; kuid_t uid; int use_gid; int use_uid; int debug; char *iocharset; -} befs_mount_options; +}; typedef struct befs_sb_info { u32 magic1; @@ -52,7 +52,7 @@ typedef struct befs_sb_info { befs_inode_addr indices; u32 magic3; - befs_mount_options mount_opts; + struct befs_mount_options mount_opts; struct nls_table *nls; } befs_sb_info; diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index e089f19..126fb6c 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -51,7 +51,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, static void befs_put_super(struct super_block *); static int befs_remount(struct super_block *, int *, char *); static int befs_statfs(struct dentry *, struct kstatfs *); -static int parse_options(char *, befs_mount_options *); +static int parse_options(char *, struct befs_mount_options *); static const struct super_operations befs_sops = { .alloc_inode = befs_alloc_inode, /* allocate a new inode */ @@ -669,7 +669,7 @@ static const match_table_t befs_tokens = { }; static int -parse_options(char *options, befs_mount_options * opts) +parse_options(char *options, struct befs_mount_options *opts) { char *p; substring_t args[MAX_OPT_ARGS]; -- cgit v0.10.2 From 038428fcf7f05e5da46de617831a8230e1a2551d Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:46:20 -0700 Subject: befs: replace typedef befs_sb_info by structure See Documenation/CodingStyle Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/befs/befs.h b/fs/befs/befs.h index d4751af..11461ab 100644 --- a/fs/befs/befs.h +++ b/fs/befs/befs.h @@ -28,7 +28,7 @@ struct befs_mount_options { char *iocharset; }; -typedef struct befs_sb_info { +struct befs_sb_info { u32 magic1; u32 block_size; u32 block_shift; @@ -54,8 +54,7 @@ typedef struct befs_sb_info { struct befs_mount_options mount_opts; struct nls_table *nls; - -} befs_sb_info; +}; typedef struct befs_inode_info { u32 i_flags; @@ -105,10 +104,10 @@ void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *); /* Gets a pointer to the private portion of the super_block * structure from the public part */ -static inline befs_sb_info * +static inline struct befs_sb_info * BEFS_SB(const struct super_block *super) { - return (befs_sb_info *) super->s_fs_info; + return (struct befs_sb_info *) super->s_fs_info; } static inline befs_inode_info * diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c index 1e8e0b8..ebd5071 100644 --- a/fs/befs/datastream.c +++ b/fs/befs/datastream.c @@ -168,7 +168,7 @@ befs_count_blocks(struct super_block * sb, befs_data_stream * ds) befs_blocknr_t blocks; befs_blocknr_t datablocks; /* File data blocks */ befs_blocknr_t metablocks; /* FS metadata blocks */ - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); befs_debug(sb, "---> %s", __func__); @@ -428,7 +428,7 @@ befs_find_brun_dblindirect(struct super_block *sb, struct buffer_head *indir_block; befs_block_run indir_run; befs_disk_inode_addr *iaddr_array = NULL; - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); befs_blocknr_t indir_start_blk = data->max_indirect_range >> befs_sb->block_shift; diff --git a/fs/befs/io.c b/fs/befs/io.c index 0408a3d..7a5b4ec 100644 --- a/fs/befs/io.c +++ b/fs/befs/io.c @@ -28,7 +28,7 @@ befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr) { struct buffer_head *bh = NULL; befs_blocknr_t block = 0; - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); befs_debug(sb, "---> Enter %s " "[%u, %hu, %hu]", __func__, iaddr.allocation_group, diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 126fb6c..9978db4 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -304,8 +304,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) { struct buffer_head *bh = NULL; befs_inode *raw_inode = NULL; - - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); befs_inode_info *befs_ino = NULL; struct inode *inode; long ret = -EIO; @@ -769,7 +768,7 @@ static int befs_fill_super(struct super_block *sb, void *data, int silent) { struct buffer_head *bh; - befs_sb_info *befs_sb; + struct befs_sb_info *befs_sb; befs_super_block *disk_sb; struct inode *root; long ret = -EINVAL; diff --git a/fs/befs/super.c b/fs/befs/super.c index ca40f82..aeafc4d 100644 --- a/fs/befs/super.c +++ b/fs/befs/super.c @@ -24,7 +24,7 @@ int befs_load_sb(struct super_block *sb, befs_super_block * disk_sb) { - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); /* Check the byte order of the filesystem */ if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE) @@ -59,7 +59,7 @@ befs_load_sb(struct super_block *sb, befs_super_block * disk_sb) int befs_check_sb(struct super_block *sb) { - befs_sb_info *befs_sb = BEFS_SB(sb); + struct befs_sb_info *befs_sb = BEFS_SB(sb); /* Check magic headers of super block */ if ((befs_sb->magic1 != BEFS_SUPER_MAGIC1) -- cgit v0.10.2 From f8ccad2164d406e60c0fa91206258f608fdb0148 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:46:23 -0700 Subject: befs: replace typedef befs_inode_info by structure See Documentation/CodingStyle Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/befs/befs.h b/fs/befs/befs.h index 11461ab..1fead8d 100644 --- a/fs/befs/befs.h +++ b/fs/befs/befs.h @@ -56,7 +56,7 @@ struct befs_sb_info { struct nls_table *nls; }; -typedef struct befs_inode_info { +struct befs_inode_info { u32 i_flags; u32 i_type; @@ -70,8 +70,7 @@ typedef struct befs_inode_info { } i_data; struct inode vfs_inode; - -} befs_inode_info; +}; enum befs_err { BEFS_OK, @@ -110,7 +109,7 @@ BEFS_SB(const struct super_block *super) return (struct befs_sb_info *) super->s_fs_info; } -static inline befs_inode_info * +static inline struct befs_inode_info * BEFS_I(const struct inode *inode) { return list_entry(inode, struct befs_inode_info, vfs_inode); diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 9978db4..16e0a48 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -305,7 +305,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) struct buffer_head *bh = NULL; befs_inode *raw_inode = NULL; struct befs_sb_info *befs_sb = BEFS_SB(sb); - befs_inode_info *befs_ino = NULL; + struct befs_inode_info *befs_ino = NULL; struct inode *inode; long ret = -EIO; @@ -471,7 +471,7 @@ static void * befs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct super_block *sb = dentry->d_sb; - befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); + struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); befs_data_stream *data = &befs_ino->i_data.ds; befs_off_t len = data->size; char *link; @@ -501,7 +501,8 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) static void * befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd) { - befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); + struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); + nd_set_link(nd, befs_ino->i_data.symlink); return NULL; } -- cgit v0.10.2 From 6fb7a61e98ac311a65bc652a12611d9899994f49 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:25 -0700 Subject: nilfs2: do not use async write flag for segment summary buffers The async write flag is introduced to nilfs2 in the commit 7f42ec394156 ("nilfs2: fix issue with race condition of competition between segments for dirty blocks"), but the flag only makes sense for data buffers and btree node buffers. It is not needed for segment summary buffers. This gets rid of the latter uses as part of refactoring of atomic bit operations on buffer state bitmap. Signed-off-by: Ryusuke Konishi Cc: Vyacheslav Dubeyko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 0c3f303..c9a4e60 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1588,7 +1588,6 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci) list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { - set_buffer_async_write(bh); if (bh->b_page != bd_page) { if (bd_page) { lock_page(bd_page); @@ -1688,7 +1687,6 @@ static void nilfs_abort_logs(struct list_head *logs, int err) list_for_each_entry(segbuf, logs, sb_list) { list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { - clear_buffer_async_write(bh); if (bh->b_page != bd_page) { if (bd_page) end_page_writeback(bd_page); @@ -1768,7 +1766,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) b_assoc_buffers) { set_buffer_uptodate(bh); clear_buffer_dirty(bh); - clear_buffer_async_write(bh); if (bh->b_page != bd_page) { if (bd_page) end_page_writeback(bd_page); -- cgit v0.10.2 From ead8ecffa3e180202c1096a39f14bbecffb139a1 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:28 -0700 Subject: nilfs2: use set_mask_bits() for operations on buffer state bitmap nilfs_forget_buffer(), nilfs_clear_dirty_page(), and nilfs_segctor_complete_write() are using a bunch of atomic bit operations against buffer state bitmap. This reduces the number of them by utilizing set_mask_bits() macro. Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 700ecbc..45d650a 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -89,18 +89,16 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, void nilfs_forget_buffer(struct buffer_head *bh) { struct page *page = bh->b_page; + const unsigned long clear_bits = + (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped | + 1 << BH_Async_Write | 1 << BH_NILFS_Volatile | + 1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected); lock_buffer(bh); - clear_buffer_nilfs_volatile(bh); - clear_buffer_nilfs_checked(bh); - clear_buffer_nilfs_redirected(bh); - clear_buffer_async_write(bh); - clear_buffer_dirty(bh); + set_mask_bits(&bh->b_state, clear_bits, 0); if (nilfs_page_buffers_clean(page)) __nilfs_clear_page_dirty(page); - clear_buffer_uptodate(bh); - clear_buffer_mapped(bh); bh->b_blocknr = -1; ClearPageUptodate(page); ClearPageMappedToDisk(page); @@ -421,6 +419,10 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) if (page_has_buffers(page)) { struct buffer_head *bh, *head; + const unsigned long clear_bits = + (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped | + 1 << BH_Async_Write | 1 << BH_NILFS_Volatile | + 1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected); bh = head = page_buffers(page); do { @@ -430,13 +432,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) "discard block %llu, size %zu", (u64)bh->b_blocknr, bh->b_size); } - clear_buffer_async_write(bh); - clear_buffer_dirty(bh); - clear_buffer_nilfs_volatile(bh); - clear_buffer_nilfs_checked(bh); - clear_buffer_nilfs_redirected(bh); - clear_buffer_uptodate(bh); - clear_buffer_mapped(bh); + set_mask_bits(&bh->b_state, clear_bits, 0); unlock_buffer(bh); } while (bh = bh->b_this_page, bh != head); } diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index c9a4e60..c6abbad9 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1785,12 +1786,13 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) */ list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - set_buffer_uptodate(bh); - clear_buffer_dirty(bh); - clear_buffer_async_write(bh); - clear_buffer_delay(bh); - clear_buffer_nilfs_volatile(bh); - clear_buffer_nilfs_redirected(bh); + const unsigned long set_bits = (1 << BH_Uptodate); + const unsigned long clear_bits = + (1 << BH_Dirty | 1 << BH_Async_Write | + 1 << BH_Delay | 1 << BH_NILFS_Volatile | + 1 << BH_NILFS_Redirected); + + set_mask_bits(&bh->b_state, clear_bits, set_bits); if (bh == segbuf->sb_super_root) { if (bh->b_page != bd_page) { end_page_writeback(bd_page); -- cgit v0.10.2 From 0de6d6b9a2ba21ae28b2420f6684021904833f68 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:31 -0700 Subject: nilfs2: use bgl_lock_ptr() Simplify nilfs_mdt_bgl_lock() by utilizing bgl_lock_ptr() helper in . Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index ab172e8..a294ea3 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -111,7 +111,10 @@ static inline __u64 nilfs_mdt_cno(struct inode *inode) return ((struct the_nilfs *)inode->i_sb->s_fs_info)->ns_cno; } -#define nilfs_mdt_bgl_lock(inode, bg) \ - (&NILFS_MDT(inode)->mi_bgl->locks[(bg) & (NR_BG_LOCKS-1)].lock) +static inline spinlock_t * +nilfs_mdt_bgl_lock(struct inode *inode, unsigned int block_group) +{ + return bgl_lock_ptr(NILFS_MDT(inode)->mi_bgl, block_group); +} #endif /* _NILFS_MDT_H */ -- cgit v0.10.2 From 3568a13f4089aac90b3763a2b6c293cd2b638ec1 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:34 -0700 Subject: nilfs2: unify type of key arguments in bmap interface The type of key arguments in block mapping interface varies depending on function. For instance, nilfs_bmap_lookup_at_level() takes "__u64" for its key argument whereas nilfs_bmap_lookup() takes "unsigned long". This fits them to "__u64" to eliminate the variation. Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index 741fd02..8df0f3b 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c @@ -405,13 +405,14 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, static int nilfs_palloc_count_desc_blocks(struct inode *inode, unsigned long *desc_blocks) { - unsigned long blknum; + __u64 blknum; int ret; ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum); if (likely(!ret)) *desc_blocks = DIV_ROUND_UP( - blknum, NILFS_MDT(inode)->mi_blocks_per_desc_block); + (unsigned long)blknum, + NILFS_MDT(inode)->mi_blocks_per_desc_block); return ret; } diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index aadbd0b..c82f436 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -152,9 +152,7 @@ static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) * * %-EEXIST - A record associated with @key already exist. */ -int nilfs_bmap_insert(struct nilfs_bmap *bmap, - unsigned long key, - unsigned long rec) +int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec) { int ret; @@ -191,19 +189,16 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) return bmap->b_ops->bop_delete(bmap, key); } -int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key) +int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) { - __u64 lastkey; int ret; down_read(&bmap->b_sem); - ret = bmap->b_ops->bop_last_key(bmap, &lastkey); + ret = bmap->b_ops->bop_last_key(bmap, keyp); up_read(&bmap->b_sem); if (ret < 0) ret = nilfs_bmap_convert_error(bmap, __func__, ret); - else - *key = lastkey; return ret; } @@ -224,7 +219,7 @@ int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key) * * %-ENOENT - A record associated with @key does not exist. */ -int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key) +int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key) { int ret; @@ -235,7 +230,7 @@ int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key) return nilfs_bmap_convert_error(bmap, __func__, ret); } -static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) +static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key) { __u64 lastkey; int ret; @@ -276,7 +271,7 @@ static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) * * %-ENOMEM - Insufficient amount of memory available. */ -int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key) +int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key) { int ret; diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index b89e680..9230d33 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -153,10 +153,10 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); -int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); -int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); -int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *); -int nilfs_bmap_truncate(struct nilfs_bmap *, unsigned long); +int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); +int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); +int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); +int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); void nilfs_bmap_clear(struct nilfs_bmap *); int nilfs_bmap_propagate(struct nilfs_bmap *, struct buffer_head *); void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *, struct list_head *); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index ab4987b..07577cb 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -106,7 +106,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, err = nilfs_transaction_begin(inode->i_sb, &ti, 1); if (unlikely(err)) goto out; - err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff, + err = nilfs_bmap_insert(ii->i_bmap, blkoff, (unsigned long)bh_result); if (unlikely(err != 0)) { if (err == -EEXIST) { @@ -714,7 +714,7 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags) static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, unsigned long from) { - unsigned long b; + __u64 b; int ret; if (!test_bit(NILFS_I_BMAP, &ii->i_state)) @@ -729,7 +729,7 @@ repeat: if (b < from) return; - b -= min_t(unsigned long, NILFS_MAX_TRUNCATE_BLOCKS, b - from); + b -= min_t(__u64, NILFS_MAX_TRUNCATE_BLOCKS, b - from); ret = nilfs_bmap_truncate(ii->i_bmap, b); nilfs_relax_pressure_in_lock(ii->vfs_inode.i_sb); if (!ret || (ret == -ENOMEM && -- cgit v0.10.2 From 5b20384fb32cc3f93857f44fb84736d6d62a9917 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:36 -0700 Subject: nilfs2: add bmap function to seek a valid key Add a new bmap function, nilfs_bmap_seek_key(), which seeks a valid entry and returns its key starting from a given key. This function can be used to skip hole blocks efficiently. Signed-off-by: Ryusuke Konishi Cc: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index c82f436..27f75bc 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -189,6 +189,37 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) return bmap->b_ops->bop_delete(bmap, key); } +/** + * nilfs_bmap_seek_key - seek a valid entry and return its key + * @bmap: bmap struct + * @start: start key number + * @keyp: place to store valid key + * + * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap + * starting from @start, and stores it to @keyp if found. + * + * Return Value: On success, 0 is returned. On error, one of the following + * negative error codes is returned. + * + * %-EIO - I/O error. + * + * %-ENOMEM - Insufficient amount of memory available. + * + * %-ENOENT - No valid entry was found + */ +int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp) +{ + int ret; + + down_read(&bmap->b_sem); + ret = bmap->b_ops->bop_seek_key(bmap, start, keyp); + up_read(&bmap->b_sem); + + if (ret < 0) + ret = nilfs_bmap_convert_error(bmap, __func__, ret); + return ret; +} + int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) { int ret; diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 9230d33..bfa817c 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -76,8 +76,10 @@ struct nilfs_bmap_operations { union nilfs_binfo *); int (*bop_mark)(struct nilfs_bmap *, __u64, int); - /* The following functions are internal use only. */ + int (*bop_seek_key)(const struct nilfs_bmap *, __u64, __u64 *); int (*bop_last_key)(const struct nilfs_bmap *, __u64 *); + + /* The following functions are internal use only. */ int (*bop_check_insert)(const struct nilfs_bmap *, __u64); int (*bop_check_delete)(struct nilfs_bmap *, __u64); int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int); @@ -155,6 +157,7 @@ void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); +int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp); int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); void nilfs_bmap_clear(struct nilfs_bmap *); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index ecdbae1..059f371 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -633,6 +633,44 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree, return 0; } +/** + * nilfs_btree_get_next_key - get next valid key from btree path array + * @btree: bmap struct of btree + * @path: array of nilfs_btree_path struct + * @minlevel: start level + * @nextkey: place to store the next valid key + * + * Return Value: If a next key was found, 0 is returned. Otherwise, + * -ENOENT is returned. + */ +static int nilfs_btree_get_next_key(const struct nilfs_bmap *btree, + const struct nilfs_btree_path *path, + int minlevel, __u64 *nextkey) +{ + struct nilfs_btree_node *node; + int maxlevel = nilfs_btree_height(btree) - 1; + int index, next_adj, level; + + /* Next index is already set to bp_index for leaf nodes. */ + next_adj = 0; + for (level = minlevel; level <= maxlevel; level++) { + if (level == maxlevel) + node = nilfs_btree_get_root(btree); + else + node = nilfs_btree_get_nonroot_node(path, level); + + index = path[level].bp_index + next_adj; + if (index < nilfs_btree_node_get_nchildren(node)) { + /* Next key is in this node */ + *nextkey = nilfs_btree_node_get_key(node, index); + return 0; + } + /* For non-leaf nodes, next index is stored at bp_index + 1. */ + next_adj = 1; + } + return -ENOENT; +} + static int nilfs_btree_lookup(const struct nilfs_bmap *btree, __u64 key, int level, __u64 *ptrp) { @@ -1563,6 +1601,27 @@ out: return ret; } +static int nilfs_btree_seek_key(const struct nilfs_bmap *btree, __u64 start, + __u64 *keyp) +{ + struct nilfs_btree_path *path; + const int minlevel = NILFS_BTREE_LEVEL_NODE_MIN; + int ret; + + path = nilfs_btree_alloc_path(); + if (!path) + return -ENOMEM; + + ret = nilfs_btree_do_lookup(btree, path, start, NULL, minlevel, 0); + if (!ret) + *keyp = start; + else if (ret == -ENOENT) + ret = nilfs_btree_get_next_key(btree, path, minlevel, keyp); + + nilfs_btree_free_path(path); + return ret; +} + static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) { struct nilfs_btree_path *path; @@ -2298,7 +2357,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = { .bop_assign = nilfs_btree_assign, .bop_mark = nilfs_btree_mark, + .bop_seek_key = nilfs_btree_seek_key, .bop_last_key = nilfs_btree_last_key, + .bop_check_insert = NULL, .bop_check_delete = nilfs_btree_check_delete, .bop_gather_data = nilfs_btree_gather_data, @@ -2318,7 +2379,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { .bop_assign = nilfs_btree_assign_gc, .bop_mark = NULL, + .bop_seek_key = NULL, .bop_last_key = NULL, + .bop_check_insert = NULL, .bop_check_delete = NULL, .bop_gather_data = NULL, diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 82f4865..ebf89fd 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c @@ -173,6 +173,21 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) return ret; } +static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start, + __u64 *keyp) +{ + __u64 key; + + for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) { + if (nilfs_direct_get_ptr(direct, key) != + NILFS_BMAP_INVALID_PTR) { + *keyp = key; + return 0; + } + } + return -ENOENT; +} + static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) { __u64 key, lastkey; @@ -355,7 +370,9 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = { .bop_assign = nilfs_direct_assign, .bop_mark = NULL, + .bop_seek_key = nilfs_direct_seek_key, .bop_last_key = nilfs_direct_last_key, + .bop_check_insert = nilfs_direct_check_insert, .bop_check_delete = NULL, .bop_gather_data = nilfs_direct_gather_data, -- cgit v0.10.2 From fa33915c92b43f5a4e95649f81303cc089b10dc6 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:39 -0700 Subject: nilfs2: add helper to find existent block on metadata file Add a new metadata file function, nilfs_mdt_find_block(), which finds an existent block on a metadata file in a given range of blocks. This function skips continuous hole blocks efficiently by using nilfs_bmap_seek_key(). Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 892cf5f..dee34d9 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -261,6 +261,60 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, } /** + * nilfs_mdt_find_block - find and get a buffer on meta data file. + * @inode: inode of the meta data file + * @start: start block offset (inclusive) + * @end: end block offset (inclusive) + * @blkoff: block offset + * @out_bh: place to store a pointer to buffer_head struct + * + * nilfs_mdt_find_block() looks up an existing block in range of + * [@start, @end] and stores pointer to a buffer head of the block to + * @out_bh, and block offset to @blkoff, respectively. @out_bh and + * @blkoff are substituted only when zero is returned. + * + * Return Value: On success, it returns 0. On error, the following negative + * error code is returned. + * + * %-ENOMEM - Insufficient memory available. + * + * %-EIO - I/O error + * + * %-ENOENT - no block was found in the range + */ +int nilfs_mdt_find_block(struct inode *inode, unsigned long start, + unsigned long end, unsigned long *blkoff, + struct buffer_head **out_bh) +{ + __u64 next; + int ret; + + if (unlikely(start > end)) + return -ENOENT; + + ret = nilfs_mdt_read_block(inode, start, true, out_bh); + if (!ret) { + *blkoff = start; + goto out; + } + if (unlikely(ret != -ENOENT || start == ULONG_MAX)) + goto out; + + ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next); + if (!ret) { + if (next <= end) { + ret = nilfs_mdt_read_block(inode, next, true, out_bh); + if (!ret) + *blkoff = next; + } else { + ret = -ENOENT; + } + } +out: + return ret; +} + +/** * nilfs_mdt_delete_block - make a hole on the meta data file. * @inode: inode of the meta data file * @block: block offset diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index a294ea3..fe529a8 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -78,6 +78,9 @@ int nilfs_mdt_get_block(struct inode *, unsigned long, int, void (*init_block)(struct inode *, struct buffer_head *, void *), struct buffer_head **); +int nilfs_mdt_find_block(struct inode *inode, unsigned long start, + unsigned long end, unsigned long *blkoff, + struct buffer_head **out_bh); int nilfs_mdt_delete_block(struct inode *, unsigned long); int nilfs_mdt_forget_block(struct inode *, unsigned long); int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); -- cgit v0.10.2 From 53a2c3bdf4132c2c9cc3581e15265fd962f34fa8 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:42 -0700 Subject: nilfs2: improve execution time of NILFS_IOCTL_GET_CPINFO ioctl The older a filesystem gets, the slower lscp command becomes. This is because nilfs_cpfile_do_get_cpinfo() function meets more hole blocks as the start offset of valid checkpoint numbers gets bigger. This reduces the overhead by skipping hole blocks efficiently with nilfs_mdt_find_block() helper. A measurement result of this patch is as follows: Before: $ time lscp CNO DATE TIME MODE FLG BLKCNT ICNT 5769303 2015-02-22 19:31:33 cp - 108 1 5769304 2015-02-22 19:38:54 cp - 108 1 real 0m0.182s user 0m0.003s sys 0m0.180s After: $ time lscp CNO DATE TIME MODE FLG BLKCNT ICNT 5769303 2015-02-22 19:31:33 cp - 108 1 5769304 2015-02-22 19:38:54 cp - 108 1 real 0m0.003s user 0m0.001s sys 0m0.002s Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 0d58075..b6596ca 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -53,6 +53,13 @@ nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno) return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile)); } +static __u64 nilfs_cpfile_first_checkpoint_in_block(const struct inode *cpfile, + unsigned long blkoff) +{ + return (__u64)nilfs_cpfile_checkpoints_per_block(cpfile) * blkoff + + 1 - NILFS_MDT(cpfile)->mi_first_entry_offset; +} + static unsigned long nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile, __u64 curr, @@ -146,6 +153,44 @@ static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile, create, nilfs_cpfile_block_init, bhp); } +/** + * nilfs_cpfile_find_checkpoint_block - find and get a buffer on cpfile + * @cpfile: inode of cpfile + * @start_cno: start checkpoint number (inclusive) + * @end_cno: end checkpoint number (inclusive) + * @cnop: place to store the next checkpoint number + * @bhp: place to store a pointer to buffer_head struct + * + * Return Value: On success, it returns 0. On error, the following negative + * error code is returned. + * + * %-ENOMEM - Insufficient memory available. + * + * %-EIO - I/O error + * + * %-ENOENT - no block exists in the range. + */ +static int nilfs_cpfile_find_checkpoint_block(struct inode *cpfile, + __u64 start_cno, __u64 end_cno, + __u64 *cnop, + struct buffer_head **bhp) +{ + unsigned long start, end, blkoff; + int ret; + + if (unlikely(start_cno > end_cno)) + return -ENOENT; + + start = nilfs_cpfile_get_blkoff(cpfile, start_cno); + end = nilfs_cpfile_get_blkoff(cpfile, end_cno); + + ret = nilfs_mdt_find_block(cpfile, start, end, &blkoff, bhp); + if (!ret) + *cnop = (blkoff == start) ? start_cno : + nilfs_cpfile_first_checkpoint_in_block(cpfile, blkoff); + return ret; +} + static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile, __u64 cno) { @@ -403,14 +448,15 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, return -ENOENT; /* checkpoint number 0 is invalid */ down_read(&NILFS_MDT(cpfile)->mi_sem); - for (n = 0; cno < cur_cno && n < nci; cno += ncps) { - ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); - ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); + for (n = 0; n < nci; cno += ncps) { + ret = nilfs_cpfile_find_checkpoint_block( + cpfile, cno, cur_cno - 1, &cno, &bh); if (ret < 0) { - if (ret != -ENOENT) - goto out; - continue; /* skip hole */ + if (likely(ret == -ENOENT)) + break; + goto out; } + ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); kaddr = kmap_atomic(bh->b_page); cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); -- cgit v0.10.2 From 3377f843cf80e33d63f1a3ded67fd129a298c6b0 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:45 -0700 Subject: nilfs2: fix gcc warning at nilfs_checkpoint_is_mounted() Fix the following build warning: fs/nilfs2/super.c: In function 'nilfs_checkpoint_is_mounted': fs/nilfs2/super.c:1023:10: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] if (cno < 0 || cno > nilfs->ns_cno) ^ This warning indicates that the comparision "cno < 0" is useless because variable "cno" has an unsigned integer type "__u64". Signed-off-by: Ryusuke Konishi Reported-by: David Binderman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 5bc2a1c..c1725f20 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1020,7 +1020,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) struct dentry *dentry; int ret; - if (cno < 0 || cno > nilfs->ns_cno) + if (cno > nilfs->ns_cno) return false; if (cno >= nilfs_last_cno(nilfs)) -- cgit v0.10.2 From 0ce187c4f32d77eae077f249aa10656b5eef5f28 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:47 -0700 Subject: nilfs2: put out gfp mask manipulation from nilfs_set_inode_flags() nilfs_set_inode_flags() function adjusts gfp-mask of inode->i_mapping as well as i_flags, however, this coupling of operations is not appropriate. For instance, nilfs_ioctl_setflags(), one of three callers of nilfs_set_inode_flags(), doesn't need to reinitialize the gfp-mask at all. In addition, nilfs_new_inode(), another caller of nilfs_set_inode_flags(), doesn't either because it has already initialized the gfp-mask. Only __nilfs_read_inode(), the remaining caller, needs it. So, this moves the gfp mask manipulation to __nilfs_read_inode() from nilfs_set_inode_flags(). Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 07577cb..8138b11 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -456,8 +456,6 @@ void nilfs_set_inode_flags(struct inode *inode) inode->i_flags |= S_NOATIME; if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; - mapping_set_gfp_mask(inode->i_mapping, - mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); } int nilfs_read_inode_common(struct inode *inode, @@ -542,6 +540,8 @@ static int __nilfs_read_inode(struct super_block *sb, brelse(bh); up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); nilfs_set_inode_flags(inode); + mapping_set_gfp_mask(inode->i_mapping, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); return 0; failed_unmap: -- cgit v0.10.2 From faea2c5311e162f5ceda8e0a261a9f9ece6f921d Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 16 Apr 2015 12:46:50 -0700 Subject: nilfs2: use inode_set_flags() in nilfs_set_inode_flags() Use inode_set_flags() to atomically set i_flags instead of clearing out the S_IMMUTABLE, S_APPEND, etc. flags and then setting them from the FS_IMMUTABLE_FL, FS_APPEND_FL flags to avoid a race where an immutable file has the immutable flag cleared for a brief window of time. This is a similar fix to commit 5f16f3225b06 ("ext4: atomically set inode->i_flags in ext4_set_inode_flags()"). Signed-off-by: Ryusuke Konishi Cc: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 8138b11..766cb85 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -443,19 +443,20 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) void nilfs_set_inode_flags(struct inode *inode) { unsigned int flags = NILFS_I(inode)->i_flags; + unsigned int new_fl = 0; - inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | - S_DIRSYNC); if (flags & FS_SYNC_FL) - inode->i_flags |= S_SYNC; + new_fl |= S_SYNC; if (flags & FS_APPEND_FL) - inode->i_flags |= S_APPEND; + new_fl |= S_APPEND; if (flags & FS_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; + new_fl |= S_IMMUTABLE; if (flags & FS_NOATIME_FL) - inode->i_flags |= S_NOATIME; + new_fl |= S_NOATIME; if (flags & FS_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; + new_fl |= S_DIRSYNC; + inode_set_flags(inode, new_fl, S_SYNC | S_APPEND | S_IMMUTABLE | + S_NOATIME | S_DIRSYNC); } int nilfs_read_inode_common(struct inode *inode, -- cgit v0.10.2 From 13f244852f1197b623af2d3076fae197d2e038ec Mon Sep 17 00:00:00 2001 From: Chengyu Song Date: Thu, 16 Apr 2015 12:46:53 -0700 Subject: hfs: incorrect return values In case of memory allocation error, the return should be -ENOMEM, instead of -ENOSPC. Signed-off-by: Chengyu Song Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 1455668..36d1a6a 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -197,7 +197,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, inode = hfs_new_inode(dir, &dentry->d_name, mode); if (!inode) - return -ENOSPC; + return -ENOMEM; res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode); if (res) { @@ -226,7 +226,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode); if (!inode) - return -ENOSPC; + return -ENOMEM; res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode); if (res) { -- cgit v0.10.2 From f01fa5fb35c132587855be788297771e94b84330 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Apr 2015 12:46:56 -0700 Subject: hfsplus: add missing curly braces in hfsplus_delete_cat() This doesn't change how the code works, but clearly the curly braces were intended. Signed-off-by: Dan Carpenter Cc: Vyacheslav Dubeyko Cc: Sougata Santra Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 7892e6f..022974a 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c @@ -350,10 +350,11 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) &fd.search_key->cat.name.unicode, off + 2, len); fd.search_key->key_len = cpu_to_be16(6 + len); - } else + } else { err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str); if (unlikely(err)) goto out; + } err = hfs_brec_find(&fd, hfs_find_rec_by_key); if (err) -- cgit v0.10.2 From a3cef4cd6886c755d2148739699751900b51a365 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:46:58 -0700 Subject: fs/hfsplus: move xattr_name allocation in hfsplus_getxattr() security/trusted/user/osx getxattr did the same xattr_name initialization. Move that operation in hfsplus_getxattr(). Tested with security/trusted/user getfattr/setfattr Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index d98094a..087f8da 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -560,6 +560,30 @@ failed_getxattr_init: return res; } +ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size, + const char *prefix, size_t prefixlen) +{ + int res; + char *xattr_name; + + if (!strcmp(name, "")) + return -EINVAL; + + xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, + GFP_KERNEL); + if (!xattr_name) + return -ENOMEM; + + strcpy(xattr_name, prefix); + strcpy(xattr_name + prefixlen, name); + + res = __hfsplus_getxattr(dentry->d_inode, xattr_name, value, size); + kfree(xattr_name); + return res; + +} + static inline int can_list(const char *xattr_name) { if (!xattr_name) @@ -806,9 +830,6 @@ end_removexattr: static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { - char *xattr_name; - int res; - if (!strcmp(name, "")) return -EINVAL; @@ -818,16 +839,9 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name, */ if (is_known_namespace(name)) return -EOPNOTSUPP; - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN - + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_MAC_OSX_PREFIX); - strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name); - res = hfsplus_getxattr(dentry, xattr_name, buffer, size); - kfree(xattr_name); - return res; + return hfsplus_getxattr(dentry, name, buffer, size, + XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN); } static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h index 288530c..570d406 100644 --- a/fs/hfsplus/xattr.h +++ b/fs/hfsplus/xattr.h @@ -28,15 +28,11 @@ static inline int hfsplus_setxattr(struct dentry *dentry, const char *name, } ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, - void *value, size_t size); + void *value, size_t size); -static inline ssize_t hfsplus_getxattr(struct dentry *dentry, - const char *name, - void *value, - size_t size) -{ - return __hfsplus_getxattr(dentry->d_inode, name, value, size); -} +ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size, + const char *prefix, size_t prefixlen); ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size); diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c index 6ec5e10..e67d528 100644 --- a/fs/hfsplus/xattr_security.c +++ b/fs/hfsplus/xattr_security.c @@ -16,22 +16,9 @@ static int hfsplus_security_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_SECURITY_PREFIX); - strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name); - - res = hfsplus_getxattr(dentry, xattr_name, buffer, size); - kfree(xattr_name); - return res; + return hfsplus_getxattr(dentry, name, buffer, size, + XATTR_SECURITY_PREFIX, + XATTR_SECURITY_PREFIX_LEN); } static int hfsplus_security_setxattr(struct dentry *dentry, const char *name, diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c index 3c5f27e..0b7d78f2 100644 --- a/fs/hfsplus/xattr_trusted.c +++ b/fs/hfsplus/xattr_trusted.c @@ -14,22 +14,9 @@ static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_TRUSTED_PREFIX); - strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name); - - res = hfsplus_getxattr(dentry, xattr_name, buffer, size); - kfree(xattr_name); - return res; + return hfsplus_getxattr(dentry, name, buffer, size, + XATTR_TRUSTED_PREFIX, + XATTR_TRUSTED_PREFIX_LEN); } static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name, diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c index 2b625a5..f8860df 100644 --- a/fs/hfsplus/xattr_user.c +++ b/fs/hfsplus/xattr_user.c @@ -14,22 +14,9 @@ static int hfsplus_user_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_USER_PREFIX); - strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name); - res = hfsplus_getxattr(dentry, xattr_name, buffer, size); - kfree(xattr_name); - return res; + return hfsplus_getxattr(dentry, name, buffer, size, + XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } static int hfsplus_user_setxattr(struct dentry *dentry, const char *name, -- cgit v0.10.2 From 5e61473ea9f1ed6537ffaf6bf1cb60655f0d1b2c Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:47:01 -0700 Subject: fs/hfsplus: move xattr_name allocation in hfsplus_setxattr() security/trusted/user/osx setxattr did the same xattr_name initialization. Move that operation in hfsplus_setxattr(). Tested with security/trusted/user getfattr/setfattr Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 087f8da..16f545d 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -424,6 +424,28 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len) return len; } +int hfsplus_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, + const char *prefix, size_t prefixlen) +{ + char *xattr_name; + int res; + + if (!strcmp(name, "")) + return -EINVAL; + + xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, + GFP_KERNEL); + if (!xattr_name) + return -ENOMEM; + strcpy(xattr_name, prefix); + strcpy(xattr_name + prefixlen, name); + res = __hfsplus_setxattr(dentry->d_inode, xattr_name, value, size, + flags); + kfree(xattr_name); + return res; +} + static ssize_t hfsplus_getxattr_finder_info(struct inode *inode, void *value, size_t size) { @@ -847,9 +869,6 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name, static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags, int type) { - char *xattr_name; - int res; - if (!strcmp(name, "")) return -EINVAL; @@ -859,16 +878,10 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, */ if (is_known_namespace(name)) return -EOPNOTSUPP; - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN - + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_MAC_OSX_PREFIX); - strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name); - res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags); - kfree(xattr_name); - return res; + return hfsplus_setxattr(dentry, name, buffer, size, flags, + XATTR_MAC_OSX_PREFIX, + XATTR_MAC_OSX_PREFIX_LEN); } static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list, diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h index 570d406..f9b0955 100644 --- a/fs/hfsplus/xattr.h +++ b/fs/hfsplus/xattr.h @@ -21,11 +21,9 @@ extern const struct xattr_handler *hfsplus_xattr_handlers[]; int __hfsplus_setxattr(struct inode *inode, const char *name, const void *value, size_t size, int flags); -static inline int hfsplus_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags); -} +int hfsplus_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, + const char *prefix, size_t prefixlen); ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, void *value, size_t size); diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c index e67d528..aacff00 100644 --- a/fs/hfsplus/xattr_security.c +++ b/fs/hfsplus/xattr_security.c @@ -24,22 +24,9 @@ static int hfsplus_security_getxattr(struct dentry *dentry, const char *name, static int hfsplus_security_setxattr(struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_SECURITY_PREFIX); - strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name); - - res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags); - kfree(xattr_name); - return res; + return hfsplus_setxattr(dentry, name, buffer, size, flags, + XATTR_SECURITY_PREFIX, + XATTR_SECURITY_PREFIX_LEN); } static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list, diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c index 0b7d78f2..bcf65089 100644 --- a/fs/hfsplus/xattr_trusted.c +++ b/fs/hfsplus/xattr_trusted.c @@ -22,22 +22,8 @@ static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name, static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_TRUSTED_PREFIX); - strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name); - - res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags); - kfree(xattr_name); - return res; + return hfsplus_setxattr(dentry, name, buffer, size, flags, + XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); } static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list, diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c index f8860df..5aa0e6d 100644 --- a/fs/hfsplus/xattr_user.c +++ b/fs/hfsplus/xattr_user.c @@ -22,22 +22,8 @@ static int hfsplus_user_getxattr(struct dentry *dentry, const char *name, static int hfsplus_user_setxattr(struct dentry *dentry, const char *name, const void *buffer, size_t size, int flags, int type) { - char *xattr_name; - int res; - - if (!strcmp(name, "")) - return -EINVAL; - - xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, - GFP_KERNEL); - if (!xattr_name) - return -ENOMEM; - strcpy(xattr_name, XATTR_USER_PREFIX); - strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name); - - res = hfsplus_setxattr(dentry, xattr_name, buffer, size, flags); - kfree(xattr_name); - return res; + return hfsplus_setxattr(dentry, name, buffer, size, flags, + XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list, -- cgit v0.10.2 From 73d28d571d09082e132340ae4ad4d973211b7668 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:47:04 -0700 Subject: fs/hfsplus: atomically set inode->i_flags According to commit 5f16f3225b06 ("ext4: atomically set inode->i_flags in ext4_set_inode_flags()"). Signed-off-by: Fabian Frederick Cc: "Theodore Ts'o" Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index d3ff5cc..8e98f5d 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c @@ -76,7 +76,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) { struct inode *inode = file_inode(file); struct hfsplus_inode_info *hip = HFSPLUS_I(inode); - unsigned int flags; + unsigned int flags, new_fl = 0; int err = 0; err = mnt_want_write_file(file); @@ -110,14 +110,12 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) } if (flags & FS_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; + new_fl |= S_IMMUTABLE; if (flags & FS_APPEND_FL) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; + new_fl |= S_APPEND; + + inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND); if (flags & FS_NODUMP_FL) hip->userflags |= HFSPLUS_FLG_NODUMP; -- cgit v0.10.2 From 1ad8d63d63e21d711d97a4cd1105136bd0cfd647 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:47:07 -0700 Subject: fs/hfsplus: use bool instead of int for is_known_namespace() return value is_known_namespace() only returns true/false. Also remove inline and let compiler decide what to do with static functions. Signed-off-by: Fabian Frederick Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 16f545d..8d62de0 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -44,7 +44,7 @@ static int strcmp_xattr_acl(const char *name) return -1; } -static inline int is_known_namespace(const char *name) +static bool is_known_namespace(const char *name) { if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) && strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && -- cgit v0.10.2 From 7ce844a20eb58c9823205e091b815163464e9d19 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:47:09 -0700 Subject: fs/hfsplus: replace if/BUG by BUG_ON Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c index c1422d9..528e38b 100644 --- a/fs/hfsplus/bfind.c +++ b/fs/hfsplus/bfind.c @@ -118,9 +118,7 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd, int b, e; int res; - if (!rec_found) - BUG(); - + BUG_ON(!rec_found); b = 0; e = bnode->num_recs - 1; res = -ENOENT; -- cgit v0.10.2 From 27a4e3884e9c6497f96cc28256c3cdaa93d4cf97 Mon Sep 17 00:00:00 2001 From: Chengyu Song Date: Thu, 16 Apr 2015 12:47:12 -0700 Subject: hfsplus: incorrect return value In case of memory allocation error, the return should be -ENOMEM, instead of -ENOSPC. Signed-off-by: Chengyu Song Reviewed-by: Sergei Antonov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index f0235c1..3074609 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -434,7 +434,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, { struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); struct inode *inode; - int res = -ENOSPC; + int res = -ENOMEM; mutex_lock(&sbi->vh_mutex); inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); @@ -476,7 +476,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, { struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); struct inode *inode; - int res = -ENOSPC; + int res = -ENOMEM; mutex_lock(&sbi->vh_mutex); inode = hfsplus_new_inode(dir->i_sb, mode); -- cgit v0.10.2 From 059a704c43ea8800a689cf90fadb48f1e985c7eb Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Thu, 16 Apr 2015 12:47:15 -0700 Subject: hfsplus: fix expand when not enough available space Fix a bug which is reproduced as follows. Create a file: echo abc > test_file Try to expand the file beyond available space: truncate --size= test_file Since HFS+ does not support file size > allocated size, truncate should fail. However, it ends successfully. The driver returns success despite having been unable to allocate the requested space for the file. Also filesystem check finds an error: Checking catalog file. Incorrect size for file test_file (It should be 469094400 instead of 1000000000) Add a piece of code analogous to code in the fat driver. Now a proper error is returned and filesystem remains consistent. Signed-off-by: Sergei Antonov Cc: Vyacheslav Dubeyko Cc: Hin-Tak Leung Reviewed-by: Anton Altaparmakov Cc: Al Viro Cc: Christoph Hellwig Cc: Sougata Santra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 5f86cadb..6229214 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -254,6 +254,12 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size != i_size_read(inode)) { inode_dio_wait(inode); + if (attr->ia_size > inode->i_size) { + error = generic_cont_expand_simple(inode, + attr->ia_size); + if (error) + return error; + } truncate_setsize(inode, attr->ia_size); hfsplus_file_truncate(inode); } -- cgit v0.10.2 From db579e76f06e78de011b2cb7e028740a82f5558c Mon Sep 17 00:00:00 2001 From: Thomas Hebb Date: Thu, 16 Apr 2015 12:47:18 -0700 Subject: hfsplus: don't store special "osx" xattr prefix on-disk On Mac OS X, HFS+ extended attributes are not namespaced. Since we want to be compatible with OS X filesystems and yet still support the Linux namespacing system, the hfsplus driver implements a special "osx" namespace that is reported for any attribute that is not namespaced on-disk. However, the current code for getting and setting these unprefixed attributes is broken. hfsplus_osx_setattr() and hfsplus_osx_getattr() are passed names that have already had their "osx." prefixes stripped by the generic functions. The functions first, quite correctly, check those names to make sure that they aren't prefixed with a known namespace, which would allow namespace access restrictions to be bypassed. However, the functions then prepend "osx." to the name they're given before passing it on to hfsplus_getattr() and hfsplus_setattr(). Not only does this cause the "osx." prefix to be stored on-disk, defeating its purpose, it also breaks the check for the special "com.apple.FinderInfo" attribute, which is reported for all files, and as a consequence makes some userspace applications (e.g. GNU patch) fail even when extended attributes are not otherwise in use. There are five commits which have touched this particular code: 127e5f5ae51e ("hfsplus: rework functionality of getting, setting and deleting of extended attributes") b168fff72109 ("hfsplus: use xattr handlers for removexattr") bf29e886b242 ("hfsplus: correct usage of HFSPLUS_ATTR_MAX_STRLEN for non-English attributes") fcacbd95e121 ("fs/hfsplus: move xattr_name allocation in hfsplus_getxattr()") ec1bbd346f18 ("fs/hfsplus: move xattr_name allocation in hfsplus_setxattr()") The first commit creates the functions to begin with. The namespace is prepended by the original code, which I believe was correct at the time, since hfsplus_?etattr() stripped the prefix if found. The second commit removes this behavior from hfsplus_?etattr() and appears to have been intended to also remove the prefixing from hfsplus_osx_?etattr(). However, what it actually does is remove a necessary strncpy() call completely, breaking the osx namespace entirely. The third commit re-adds the strncpy() call as it was originally, but doesn't mention it in its commit message. The final two commits refactor the code and don't affect its functionality. This commit does what b168fff attempted to do (prevent the prefix from being added), but does it properly, instead of passing in an empty buffer (which is what b168fff actually did). Fixes: b168fff72109 ("hfsplus: use xattr handlers for removexattr") Signed-off-by: Thomas Hebb Cc: Hin-Tak Leung Cc: Sergei Antonov Cc: Anton Altaparmakov Cc: Fabian Frederick Cc: Christian Kujau Cc: Christoph Hellwig Cc: Al Viro Cc: Viacheslav Dubeyko Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 8d62de0..89f262d 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -862,8 +862,13 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name, if (is_known_namespace(name)) return -EOPNOTSUPP; - return hfsplus_getxattr(dentry, name, buffer, size, - XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN); + /* + * osx is the namespace we use to indicate an unprefixed + * attribute on the filesystem (like the ones that OS X + * creates), so we pass the name through unmodified (after + * ensuring it doesn't conflict with another namespace). + */ + return __hfsplus_getxattr(dentry->d_inode, name, buffer, size); } static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, @@ -879,9 +884,13 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, if (is_known_namespace(name)) return -EOPNOTSUPP; - return hfsplus_setxattr(dentry, name, buffer, size, flags, - XATTR_MAC_OSX_PREFIX, - XATTR_MAC_OSX_PREFIX_LEN); + /* + * osx is the namespace we use to indicate an unprefixed + * attribute on the filesystem (like the ones that OS X + * creates), so we pass the name through unmodified (after + * ensuring it doesn't conflict with another namespace). + */ + return __hfsplus_setxattr(dentry->d_inode, name, buffer, size, flags); } static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list, -- cgit v0.10.2 From a40a7d9d07b818ce9aa9f6ddf86076a5eef2d8f9 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Thu, 16 Apr 2015 12:47:21 -0700 Subject: fs/fat: remove unnecessary defintion '*sb' never used, so let's remote it and pass inode->i_sb directly to the MSDOS_SB. Signed-off-by: Alexander Kuleshov Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 8521207..b3a2a0e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -1279,8 +1279,7 @@ out: static int fat_read_root(struct inode *inode) { - struct super_block *sb = inode->i_sb; - struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); int error; MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO; -- cgit v0.10.2 From 58932ef7f2f28e89ee37c6e2be94885e5078ba77 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Thu, 16 Apr 2015 12:47:24 -0700 Subject: fs/fat: remove unnecessary includes 'fat.h' includes which includes which includes all the header files required for all *.c files fat filesystem. [akpm@linux-foundation.org: fs/fat/iode.c needs seq_file.h] [sfr@canb.auug.org.au: put one actually necessary include file back] Signed-off-by: Alexander Kuleshov Acked-by: OGAWA Hirofumi Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 91ad9e1..93fc622 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -8,9 +8,7 @@ * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers. */ -#include #include -#include #include "fat.h" /* this must be > 0. */ diff --git a/fs/fat/dir.c b/fs/fat/dir.c index c5d6bb9..4afc4d9 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -13,13 +13,9 @@ * Short name translation 1999, 2001 by Wolfram Pienkoss */ -#include #include -#include -#include #include #include -#include #include "fat.h" /* diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 64e295e..fe65a7d 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -2,11 +2,8 @@ #define _FAT_H #include -#include #include -#include #include -#include #include #include diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 260705c..8226557 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -3,9 +3,6 @@ * Released under GPL v2. */ -#include -#include -#include #include #include "fat.h" diff --git a/fs/fat/file.c b/fs/fat/file.c index 1e98d33..cf50d93 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -10,10 +10,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include diff --git a/fs/fat/inode.c b/fs/fat/inode.c index b3a2a0e..d1a26c2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -11,20 +11,12 @@ */ #include -#include -#include -#include -#include #include #include -#include -#include #include +#include #include #include -#include -#include -#include #include #include #include "fat.h" diff --git a/fs/fat/misc.c b/fs/fat/misc.c index d8da2d2..c4589e9 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -6,10 +6,6 @@ * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) */ -#include -#include -#include -#include #include "fat.h" /* diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index a783b0e..cc6a854 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -7,8 +7,6 @@ */ #include -#include -#include #include "fat.h" /* Characters that are undesirable in an MS-DOS file name */ diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index b8b92c2..7e0974e 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -16,10 +16,8 @@ */ #include -#include #include #include -#include #include #include "fat.h" -- cgit v0.10.2 From 8de560def7426a770ce8f967b3c3534bc9a2f683 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Thu, 16 Apr 2015 12:47:26 -0700 Subject: fs/fat: comment fix, fat_bits can be also 32 Signed-off-by: Alexander Kuleshov Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/fat.h b/fs/fat/fat.h index fe65a7d..be5e153 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -63,7 +63,7 @@ struct msdos_sb_info { unsigned short sec_per_clus; /* sectors/cluster */ unsigned short cluster_bits; /* log2(cluster_size) */ unsigned int cluster_size; /* cluster size */ - unsigned char fats, fat_bits; /* number of FATs, FAT bits (12 or 16) */ + unsigned char fats, fat_bits; /* number of FATs, FAT bits (12,16 or 32) */ unsigned short fat_start; unsigned long fat_length; /* FAT start & length (sec.) */ unsigned long dir_start; -- cgit v0.10.2 From b72c186999e689cb0b055ab1c7b3cd8fffbeb5ed Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 16 Apr 2015 12:47:29 -0700 Subject: ptrace: fix race between ptrace_resume() and wait_task_stopped() ptrace_resume() is called when the tracee is still __TASK_TRACED. We set tracee->exit_code and then wake_up_state() changes tracee->state. If the tracer's sub-thread does wait() in between, task_stopped_code(ptrace => T) wrongly looks like another report from tracee. This confuses debugger, and since wait_task_stopped() clears ->exit_code the tracee can miss a signal. Test-case: #include #include #include #include #include #include int pid; void *waiter(void *arg) { int stat; for (;;) { assert(pid == wait(&stat)); assert(WIFSTOPPED(stat)); if (WSTOPSIG(stat) == SIGHUP) continue; assert(WSTOPSIG(stat) == SIGCONT); printf("ERR! extra/wrong report:%x\n", stat); } } int main(void) { pthread_t thread; pid = fork(); if (!pid) { assert(ptrace(PTRACE_TRACEME, 0,0,0) == 0); for (;;) kill(getpid(), SIGHUP); } assert(pthread_create(&thread, NULL, waiter, NULL) == 0); for (;;) ptrace(PTRACE_CONT, pid, 0, SIGCONT); return 0; } Note for stable: the bug is very old, but without 9899d11f6544 "ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL" the fix should use lock_task_sighand(child). Signed-off-by: Oleg Nesterov Reported-by: Pavel Labath Tested-by: Pavel Labath Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 227fec3..9a34bd8 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -697,6 +697,8 @@ static int ptrace_peek_siginfo(struct task_struct *child, static int ptrace_resume(struct task_struct *child, long request, unsigned long data) { + bool need_siglock; + if (!valid_signal(data)) return -EIO; @@ -724,8 +726,26 @@ static int ptrace_resume(struct task_struct *child, long request, user_disable_single_step(child); } + /* + * Change ->exit_code and ->state under siglock to avoid the race + * with wait_task_stopped() in between; a non-zero ->exit_code will + * wrongly look like another report from tracee. + * + * Note that we need siglock even if ->exit_code == data and/or this + * status was not reported yet, the new status must not be cleared by + * wait_task_stopped() after resume. + * + * If data == 0 we do not care if wait_task_stopped() reports the old + * status and clears the code too; this can't race with the tracee, it + * takes siglock after resume. + */ + need_siglock = data && !thread_group_empty(current); + if (need_siglock) + spin_lock_irq(&child->sighand->siglock); child->exit_code = data; wake_up_state(child, __TASK_TRACED); + if (need_siglock) + spin_unlock_irq(&child->sighand->siglock); return 0; } -- cgit v0.10.2 From 64a4096c5cdab377b6e1f44008ee8b2636db579d Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 16 Apr 2015 12:47:32 -0700 Subject: ptrace: ptrace_detach() can no longer race with SIGKILL ptrace_detach() re-checks ->ptrace under tasklist lock and calls release_task() if __ptrace_detach() returns true. This was needed because the __TASK_TRACED tracee could be killed/untraced, and it could even pass exit_notify() before we take tasklist_lock. But this is no longer possible after 9899d11f6544 "ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL". We can turn these checks into WARN_ON() and remove release_task(). While at it, document the setting of child->exit_code. Signed-off-by: Oleg Nesterov Cc: Pavel Labath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 9a34bd8..c8e0e05 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -456,8 +456,6 @@ static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) static int ptrace_detach(struct task_struct *child, unsigned int data) { - bool dead = false; - if (!valid_signal(data)) return -EIO; @@ -467,18 +465,19 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) write_lock_irq(&tasklist_lock); /* - * This child can be already killed. Make sure de_thread() or - * our sub-thread doing do_wait() didn't do release_task() yet. + * We rely on ptrace_freeze_traced(). It can't be killed and + * untraced by another thread, it can't be a zombie. */ - if (child->ptrace) { - child->exit_code = data; - dead = __ptrace_detach(current, child); - } + WARN_ON(!child->ptrace || child->exit_state); + /* + * tasklist_lock avoids the race with wait_task_stopped(), see + * the comment in ptrace_resume(). + */ + child->exit_code = data; + __ptrace_detach(current, child); write_unlock_irq(&tasklist_lock); proc_ptrace_connector(child, PTRACE_DETACH); - if (unlikely(dead)) - release_task(child); return 0; } -- cgit v0.10.2 From 69828dce7af2cb6d08ef5a03de687d422fb7ec1f Mon Sep 17 00:00:00 2001 From: Vladimir Davydov Date: Thu, 16 Apr 2015 12:47:35 -0700 Subject: signal: remove warning about using SI_TKILL in rt_[tg]sigqueueinfo Sending SI_TKILL from rt_[tg]sigqueueinfo was deprecated, so now we issue a warning on the first attempt of doing it. We use WARN_ON_ONCE, which is not informative and, what is worse, taints the kernel, making the trinity syscall fuzzer complain false-positively from time to time. It does not look like we need this warning at all, because the behaviour changed quite a long time ago (2.6.39), and if an application relies on the old API, it gets EPERM anyway and can issue a warning by itself. So let us zap the warning in kernel. Signed-off-by: Vladimir Davydov Acked-by: Oleg Nesterov Cc: Richard Weinberger Cc: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index a390499..d51c5dd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2992,11 +2992,9 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) * Nor can they impersonate a kill()/tgkill(), which adds source info. */ if ((info->si_code >= 0 || info->si_code == SI_TKILL) && - (task_pid_vnr(current) != pid)) { - /* We used to allow any < 0 si_code */ - WARN_ON_ONCE(info->si_code < 0); + (task_pid_vnr(current) != pid)) return -EPERM; - } + info->si_signo = sig; /* POSIX.1b doesn't mention process groups. */ @@ -3041,12 +3039,10 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) /* Not even root can pretend to send signals from the kernel. * Nor can they impersonate a kill()/tgkill(), which adds source info. */ - if (((info->si_code >= 0 || info->si_code == SI_TKILL)) && - (task_pid_vnr(current) != pid)) { - /* We used to allow any < 0 si_code */ - WARN_ON_ONCE(info->si_code < 0); + if ((info->si_code >= 0 || info->si_code == SI_TKILL) && + (task_pid_vnr(current) != pid)) return -EPERM; - } + info->si_signo = sig; return do_send_specific(tgid, pid, sig, info); -- cgit v0.10.2 From 35f71bc0a09a45924bed268d8ccd0d3407bc476f Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 16 Apr 2015 12:47:38 -0700 Subject: fork: report pid reservation failure properly copy_process will report any failure in alloc_pid as ENOMEM currently which is misleading because the pid allocation might fail not only when the memory is short but also when the pid space is consumed already. The current man page even mentions this case: : EAGAIN : : A system-imposed limit on the number of threads was encountered. : There are a number of limits that may trigger this error: the : RLIMIT_NPROC soft resource limit (set via setrlimit(2)), which : limits the number of processes and threads for a real user ID, was : reached; the kernel's system-wide limit on the number of processes : and threads, /proc/sys/kernel/threads-max, was reached (see : proc(5)); or the maximum number of PIDs, /proc/sys/kernel/pid_max, : was reached (see proc(5)). so the current behavior is also incorrect wrt. documentation. POSIX man page also suggest returing EAGAIN when the process count limit is reached. This patch simply propagates error code from alloc_pid and makes sure we return -EAGAIN due to reservation failure. This will make behavior of fork closer to both our documentation and POSIX. alloc_pid might alsoo fail when the reaper in the pid namespace is dead (the namespace basically disallows all new processes) and there is no good error code which would match documented ones. We have traditionally returned ENOMEM for this case which is misleading as well but as per Eric W. Biederman this behavior is documented in man pid_namespaces(7) : If the "init" process of a PID namespace terminates, the kernel : terminates all of the processes in the namespace via a SIGKILL signal. : This behavior reflects the fact that the "init" process is essential for : the correct operation of a PID namespace. In this case, a subsequent : fork(2) into this PID namespace will fail with the error ENOMEM; it is : not possible to create a new processes in a PID namespace whose "init" : process has terminated. and introducing a new error code would be too risky so let's stick to ENOMEM for this case. Signed-off-by: Michal Hocko Cc: Oleg Nesterov Cc: "Eric W. Biederman" Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index f2c1e73..d778016 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1403,10 +1403,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, goto bad_fork_cleanup_io; if (pid != &init_struct_pid) { - retval = -ENOMEM; pid = alloc_pid(p->nsproxy->pid_ns_for_children); - if (!pid) + if (IS_ERR(pid)) { + retval = PTR_ERR(pid); goto bad_fork_cleanup_io; + } } p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; diff --git a/kernel/pid.c b/kernel/pid.c index cd36a5e..4fd07d5 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -182,7 +182,7 @@ static int alloc_pidmap(struct pid_namespace *pid_ns) spin_unlock_irq(&pidmap_lock); kfree(page); if (unlikely(!map->page)) - break; + return -ENOMEM; } if (likely(atomic_read(&map->nr_free))) { for ( ; ; ) { @@ -210,7 +210,7 @@ static int alloc_pidmap(struct pid_namespace *pid_ns) } pid = mk_pid(pid_ns, map, offset); } - return -1; + return -EAGAIN; } int next_pidmap(struct pid_namespace *pid_ns, unsigned int last) @@ -301,17 +301,20 @@ struct pid *alloc_pid(struct pid_namespace *ns) int i, nr; struct pid_namespace *tmp; struct upid *upid; + int retval = -ENOMEM; pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) - goto out; + return ERR_PTR(retval); tmp = ns; pid->level = ns->level; for (i = ns->level; i >= 0; i--) { nr = alloc_pidmap(tmp); - if (nr < 0) + if (IS_ERR_VALUE(nr)) { + retval = nr; goto out_free; + } pid->numbers[i].nr = nr; pid->numbers[i].ns = tmp; @@ -339,7 +342,6 @@ struct pid *alloc_pid(struct pid_namespace *ns) } spin_unlock_irq(&pidmap_lock); -out: return pid; out_unlock: @@ -351,8 +353,7 @@ out_free: free_pidmap(pid->numbers + i); kmem_cache_free(ns->pid_cachep, pid); - pid = NULL; - goto out; + return ERR_PTR(retval); } void disable_pid_allocation(struct pid_namespace *ns) -- cgit v0.10.2 From 3ea7f5e25ec271909451b7dc17be37581b888de6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 16 Apr 2015 12:47:41 -0700 Subject: fork_init: update max_threads comment The comment explaining what value max_threads is set to is outdated. The maximum memory consumption ratio for thread structures was 1/2 until February 2002, then it was briefly changed to 1/16 before being set to 1/8 which we still use today. The comment was never updated to reflect that change, it's about time. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index d778016..c507e29 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -270,8 +270,8 @@ void __init fork_init(unsigned long mempages) /* * The default maximum number of threads is set to a safe - * value: the thread structures can take up at most half - * of memory. + * value: the thread structures can take up at most one + * eighth of the memory. */ max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE); -- cgit v0.10.2 From ff691f6e03815dc8f99461ea509df863a879fc3a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Apr 2015 12:47:44 -0700 Subject: kernel/fork.c: new function for max_threads PAGE_SIZE is not guaranteed to be equal to or less than 8 times the THREAD_SIZE. E.g. architecture hexagon may have page size 1M and thread size 4096. This would lead to a division by zero in the calculation of max_threads. With this patch the buggy code is moved to a separate function set_max_threads. The error is not fixed. After fixing the problem in a separate patch the new function can be reused to adjust max_threads after adding or removing memory. Argument mempages of function fork_init() is removed as totalram_pages is an exported symbol. The creation of separate patches for refactoring to a new function and for fixing the logic was suggested by Ingo Molnar. Signed-off-by: Heinrich Schuchardt Cc: Oleg Nesterov Cc: Ingo Molnar Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/init/main.c b/init/main.c index a7e969d..2115055 100644 --- a/init/main.c +++ b/init/main.c @@ -91,7 +91,7 @@ static int kernel_init(void *); extern void init_IRQ(void); -extern void fork_init(unsigned long); +extern void fork_init(void); extern void radix_tree_init(void); #ifndef CONFIG_DEBUG_RODATA static inline void mark_rodata_ro(void) { } @@ -645,7 +645,7 @@ asmlinkage __visible void __init start_kernel(void) #endif thread_info_cache_init(); cred_init(); - fork_init(totalram_pages); + fork_init(); proc_caches_init(); buffer_init(); key_init(); diff --git a/kernel/fork.c b/kernel/fork.c index c507e29..01038e6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -253,7 +253,26 @@ EXPORT_SYMBOL_GPL(__put_task_struct); void __init __weak arch_task_cache_init(void) { } -void __init fork_init(unsigned long mempages) +/* + * set_max_threads + */ +static void set_max_threads(void) +{ + /* + * The default maximum number of threads is set to a safe + * value: the thread structures can take up at most one + * eighth of the memory. + */ + max_threads = totalram_pages / (8 * THREAD_SIZE / PAGE_SIZE); + + /* + * we need to allow at least 20 threads to boot a system + */ + if (max_threads < 20) + max_threads = 20; +} + +void __init fork_init(void) { #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR #ifndef ARCH_MIN_TASKALIGN @@ -268,18 +287,7 @@ void __init fork_init(unsigned long mempages) /* do the arch specific task caches init */ arch_task_cache_init(); - /* - * The default maximum number of threads is set to a safe - * value: the thread structures can take up at most one - * eighth of the memory. - */ - max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE); - - /* - * we need to allow at least 20 threads to boot a system - */ - if (max_threads < 20) - max_threads = 20; + set_max_threads(); init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2; -- cgit v0.10.2 From ac1b398de1ef94aeee8ba87b0120763526572a6e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Apr 2015 12:47:47 -0700 Subject: kernel/fork.c: avoid division by zero PAGE_SIZE is not guaranteed to be equal to or less than 8 times the THREAD_SIZE. E.g. architecture hexagon may have page size 1M and thread size 4096. This would lead to a division by zero in the calculation of max_threads. With 32-bit calculation there is no solution which delivers valid results for all possible combinations of the parameters. The code is only called once. Hence a 64-bit calculation can be used as solution. [akpm@linux-foundation.org: use clamp_t(), per Oleg] Signed-off-by: Heinrich Schuchardt Cc: Oleg Nesterov Cc: Ingo Molnar Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 01038e6..c7f2e1a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -88,6 +88,16 @@ #include /* + * Minimum number of threads to boot the kernel + */ +#define MIN_THREADS 20 + +/* + * Maximum number of threads + */ +#define MAX_THREADS FUTEX_TID_MASK + +/* * Protected counters by write_lock_irq(&tasklist_lock) */ unsigned long total_forks; /* Handle normal Linux uptimes. */ @@ -258,18 +268,19 @@ void __init __weak arch_task_cache_init(void) { } */ static void set_max_threads(void) { - /* - * The default maximum number of threads is set to a safe - * value: the thread structures can take up at most one - * eighth of the memory. - */ - max_threads = totalram_pages / (8 * THREAD_SIZE / PAGE_SIZE); + u64 threads; /* - * we need to allow at least 20 threads to boot a system + * The number of threads shall be limited such that the thread + * structures may only consume a small part of the available memory. */ - if (max_threads < 20) - max_threads = 20; + if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64) + threads = MAX_THREADS; + else + threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, + (u64) THREAD_SIZE * 8UL); + + max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); } void __init fork_init(void) -- cgit v0.10.2 From 16db3d3f1170fb0efca652c9378ce7c5f5cb4232 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Apr 2015 12:47:50 -0700 Subject: kernel/sysctl.c: threads-max observe limits Users can change the maximum number of threads by writing to /proc/sys/kernel/threads-max. With the patch the value entered is checked against the same limits that apply when fork_init is called. Signed-off-by: Heinrich Schuchardt Cc: Oleg Nesterov Cc: Ingo Molnar Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b7361f8..795d5fe 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -212,4 +212,7 @@ static inline void setup_sysctl_set(struct ctl_table_set *p, #endif /* CONFIG_SYSCTL */ +int sysctl_max_threads(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); + #endif /* _LINUX_SYSCTL_H */ diff --git a/kernel/fork.c b/kernel/fork.c index c7f2e1a..8807a12 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -266,7 +267,7 @@ void __init __weak arch_task_cache_init(void) { } /* * set_max_threads */ -static void set_max_threads(void) +static void set_max_threads(unsigned int max_threads_suggested) { u64 threads; @@ -280,6 +281,9 @@ static void set_max_threads(void) threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, (u64) THREAD_SIZE * 8UL); + if (threads > max_threads_suggested) + threads = max_threads_suggested; + max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); } @@ -298,7 +302,7 @@ void __init fork_init(void) /* do the arch specific task caches init */ arch_task_cache_init(); - set_max_threads(); + set_max_threads(MAX_THREADS); init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2; @@ -2020,3 +2024,26 @@ int unshare_files(struct files_struct **displaced) task_unlock(task); return 0; } + +int sysctl_max_threads(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table t; + int ret; + int threads = max_threads; + int min = MIN_THREADS; + int max = MAX_THREADS; + + t = *table; + t.data = &threads; + t.extra1 = &min; + t.extra2 = &max; + + ret = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); + if (ret || !write) + return ret; + + set_max_threads(threads); + + return 0; +} diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 42b7fc2..3c09984 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -93,11 +93,9 @@ #include #endif - #if defined(CONFIG_SYSCTL) /* External variables not in a header file. */ -extern int max_threads; extern int suid_dumpable; #ifdef CONFIG_COREDUMP extern int core_uses_pid; @@ -710,10 +708,10 @@ static struct ctl_table kern_table[] = { #endif { .procname = "threads-max", - .data = &max_threads, + .data = NULL, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = sysctl_max_threads, }, { .procname = "random", -- cgit v0.10.2 From 0ec62afeb143a34ce78143cf442f879ef68382f7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Apr 2015 12:47:53 -0700 Subject: Doc/sysctl/kernel.txt: document threads-max File /proc/sys/kernel/threads-max controls the maximum number of threads that can be created using fork(). [akpm@linux-foundation.org: fix typo, per Guenter] Signed-off-by: Heinrich Schuchardt Cc: Oleg Nesterov Cc: Ingo Molnar Cc: Guenter Roeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 99d7eb3..c831001 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -872,6 +872,27 @@ can be ORed together: ============================================================== +threads-max + +This value controls the maximum number of threads that can be created +using fork(). + +During initialization the kernel sets this value such that even if the +maximum number of threads is created, the thread structures occupy only +a part (1/8th) of the available RAM pages. + +The minimum value that can be written to threads-max is 20. +The maximum value that can be written to threads-max is given by the +constant FUTEX_TID_MASK (0x3fffffff). +If a value outside of this range is written to threads-max an error +EINVAL occurs. + +The value written is checked against the available RAM pages. If the +thread structures would occupy too much (more than 1/8th) of the +available RAM pages threads-max is reduced accordingly. + +============================================================== + unknown_nmi_panic: The value in this file affects behavior of handling NMI. When the -- cgit v0.10.2 From 90f31d0ea88880f780574f3d0bb1a227c4c66ca3 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Thu, 16 Apr 2015 12:47:56 -0700 Subject: mm: rcu-protected get_mm_exe_file() This patch removes mm->mmap_sem from mm->exe_file read side. Also it kills dup_mm_exe_file() and moves exe_file duplication into dup_mmap() where both mmap_sems are locked. [akpm@linux-foundation.org: fix comment typo] Signed-off-by: Konstantin Khlebnikov Cc: Davidlohr Bueso Cc: Al Viro Cc: Oleg Nesterov Cc: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/file.c b/fs/file.c index ee738ea..93c5f89 100644 --- a/fs/file.c +++ b/fs/file.c @@ -638,8 +638,7 @@ static struct file *__fget(unsigned int fd, fmode_t mask) file = fcheck_files(files, fd); if (file) { /* File object ref couldn't be taken */ - if ((file->f_mode & mask) || - !atomic_long_inc_not_zero(&file->f_count)) + if ((file->f_mode & mask) || !get_file_rcu(file)) file = NULL; } rcu_read_unlock(); diff --git a/include/linux/fs.h b/include/linux/fs.h index f4fc607..6bf7ab7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -870,6 +870,7 @@ static inline struct file *get_file(struct file *f) atomic_long_inc(&f->f_count); return f; } +#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count) #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1) #define file_count(x) atomic_long_read(&(x)->f_count) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 590630e..8d37e26 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -429,7 +429,7 @@ struct mm_struct { #endif /* store ref to file /proc//exe symlink points to */ - struct file *exe_file; + struct file __rcu *exe_file; #ifdef CONFIG_MMU_NOTIFIER struct mmu_notifier_mm *mmu_notifier_mm; #endif diff --git a/kernel/fork.c b/kernel/fork.c index 8807a12..2592026 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -403,6 +403,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) */ down_write_nested(&mm->mmap_sem, SINGLE_DEPTH_NESTING); + /* No ordering required: file already has been exposed. */ + RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm)); + mm->total_vm = oldmm->total_vm; mm->shared_vm = oldmm->shared_vm; mm->exec_vm = oldmm->exec_vm; @@ -528,7 +531,13 @@ static inline void mm_free_pgd(struct mm_struct *mm) pgd_free(mm, mm->pgd); } #else -#define dup_mmap(mm, oldmm) (0) +static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +{ + down_write(&oldmm->mmap_sem); + RCU_INIT_POINTER(mm->exe_file, get_mm_exe_file(oldmm)); + up_write(&oldmm->mmap_sem); + return 0; +} #define mm_alloc_pgd(mm) (0) #define mm_free_pgd(mm) #endif /* CONFIG_MMU */ @@ -697,35 +706,46 @@ void mmput(struct mm_struct *mm) } EXPORT_SYMBOL_GPL(mmput); +/** + * set_mm_exe_file - change a reference to the mm's executable file + * + * This changes mm's executable file (shown as symlink /proc/[pid]/exe). + * + * Main users are mmput(), sys_execve() and sys_prctl(PR_SET_MM_MAP/EXE_FILE). + * Callers prevent concurrent invocations: in mmput() nobody alive left, + * in execve task is single-threaded, prctl holds mmap_sem exclusively. + */ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) { + struct file *old_exe_file = rcu_dereference_protected(mm->exe_file, + !atomic_read(&mm->mm_users) || current->in_execve || + lockdep_is_held(&mm->mmap_sem)); + if (new_exe_file) get_file(new_exe_file); - if (mm->exe_file) - fput(mm->exe_file); - mm->exe_file = new_exe_file; + rcu_assign_pointer(mm->exe_file, new_exe_file); + if (old_exe_file) + fput(old_exe_file); } +/** + * get_mm_exe_file - acquire a reference to the mm's executable file + * + * Returns %NULL if mm has no associated executable file. + * User must release file via fput(). + */ struct file *get_mm_exe_file(struct mm_struct *mm) { struct file *exe_file; - /* We need mmap_sem to protect against races with removal of exe_file */ - down_read(&mm->mmap_sem); - exe_file = mm->exe_file; - if (exe_file) - get_file(exe_file); - up_read(&mm->mmap_sem); + rcu_read_lock(); + exe_file = rcu_dereference(mm->exe_file); + if (exe_file && !get_file_rcu(exe_file)) + exe_file = NULL; + rcu_read_unlock(); return exe_file; } -static void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) -{ - /* It's safe to write the exe_file pointer without exe_file_lock because - * this is called during fork when the task is not yet in /proc */ - newmm->exe_file = get_mm_exe_file(oldmm); -} - /** * get_task_mm - acquire a reference to the task's mm * @@ -887,8 +907,6 @@ static struct mm_struct *dup_mm(struct task_struct *tsk) if (!mm_init(mm, tsk)) goto fail_nomem; - dup_mm_exe_file(oldmm, mm); - err = dup_mmap(mm, oldmm); if (err) goto free_pt; -- cgit v0.10.2 From 6e399cd144d8500ffb5d40fa6848890e2580a80a Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:47:59 -0700 Subject: prctl: avoid using mmap_sem for exe_file serialization Oleg cleverly suggested using xchg() to set the new mm->exe_file instead of calling set_mm_exe_file() which requires some form of serialization -- mmap_sem in this case. For archs that do not have atomic rmw instructions we still fallback to a spinlock alternative, so this should always be safe. As such, we only need the mmap_sem for looking up the backing vm_file, which can be done sharing the lock. Naturally, this means we need to manually deal with both the new and old file reference counting, and we need not worry about the MMF_EXE_FILE_CHANGED bits, which can probably be deleted in the future anyway. Signed-off-by: Davidlohr Bueso Suggested-by: Oleg Nesterov Acked-by: Oleg Nesterov Reviewed-by: Konstantin Khlebnikov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/exec.c b/fs/exec.c index c7f9b73..a5fef83 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1078,7 +1078,13 @@ int flush_old_exec(struct linux_binprm * bprm) if (retval) goto out; + /* + * Must be called _before_ exec_mmap() as bprm->mm is + * not visibile until then. This also enables the update + * to be lockless. + */ set_mm_exe_file(bprm->mm, bprm->file); + /* * Release all of the old mmap stuff */ diff --git a/kernel/fork.c b/kernel/fork.c index 2592026..0d23e76 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -711,15 +711,22 @@ EXPORT_SYMBOL_GPL(mmput); * * This changes mm's executable file (shown as symlink /proc/[pid]/exe). * - * Main users are mmput(), sys_execve() and sys_prctl(PR_SET_MM_MAP/EXE_FILE). - * Callers prevent concurrent invocations: in mmput() nobody alive left, - * in execve task is single-threaded, prctl holds mmap_sem exclusively. + * Main users are mmput() and sys_execve(). Callers prevent concurrent + * invocations: in mmput() nobody alive left, in execve task is single + * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the + * mm->exe_file, but does so without using set_mm_exe_file() in order + * to do avoid the need for any locks. */ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) { - struct file *old_exe_file = rcu_dereference_protected(mm->exe_file, - !atomic_read(&mm->mm_users) || current->in_execve || - lockdep_is_held(&mm->mmap_sem)); + struct file *old_exe_file; + + /* + * It is safe to dereference the exe_file without RCU as + * this function is only called if nobody else can access + * this mm -- see comment above for justification. + */ + old_exe_file = rcu_dereference_raw(mm->exe_file); if (new_exe_file) get_file(new_exe_file); diff --git a/kernel/sys.c b/kernel/sys.c index 3be3449..a4e372b 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1649,14 +1649,13 @@ SYSCALL_DEFINE1(umask, int, mask) return mask; } -static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) +static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) { struct fd exe; + struct file *old_exe, *exe_file; struct inode *inode; int err; - VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm); - exe = fdget(fd); if (!exe.file) return -EBADF; @@ -1680,15 +1679,22 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) /* * Forbid mm->exe_file change if old file still mapped. */ + exe_file = get_mm_exe_file(mm); err = -EBUSY; - if (mm->exe_file) { + if (exe_file) { struct vm_area_struct *vma; - for (vma = mm->mmap; vma; vma = vma->vm_next) - if (vma->vm_file && - path_equal(&vma->vm_file->f_path, - &mm->exe_file->f_path)) - goto exit; + down_read(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { + if (!vma->vm_file) + continue; + if (path_equal(&vma->vm_file->f_path, + &exe_file->f_path)) + goto exit_err; + } + + up_read(&mm->mmap_sem); + fput(exe_file); } /* @@ -1702,10 +1708,18 @@ static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) goto exit; err = 0; - set_mm_exe_file(mm, exe.file); /* this grabs a reference to exe.file */ + /* set the new file, lockless */ + get_file(exe.file); + old_exe = xchg(&mm->exe_file, exe.file); + if (old_exe) + fput(old_exe); exit: fdput(exe); return err; +exit_err: + up_read(&mm->mmap_sem); + fput(exe_file); + goto exit; } #ifdef CONFIG_CHECKPOINT_RESTORE @@ -1840,10 +1854,9 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; } - down_write(&mm->mmap_sem); if (prctl_map.exe_fd != (u32)-1) - error = prctl_set_mm_exe_file_locked(mm, prctl_map.exe_fd); - downgrade_write(&mm->mmap_sem); + error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd); + down_read(&mm->mmap_sem); if (error) goto out; @@ -1909,12 +1922,8 @@ static int prctl_set_mm(int opt, unsigned long addr, if (!capable(CAP_SYS_RESOURCE)) return -EPERM; - if (opt == PR_SET_MM_EXE_FILE) { - down_write(&mm->mmap_sem); - error = prctl_set_mm_exe_file_locked(mm, (unsigned int)addr); - up_write(&mm->mmap_sem); - return error; - } + if (opt == PR_SET_MM_EXE_FILE) + return prctl_set_mm_exe_file(mm, (unsigned int)addr); if (addr >= TASK_SIZE || addr < mmap_min_addr) return -EINVAL; -- cgit v0.10.2 From dfcce791fb0ad06f3f0b745a23160b9d8858fe39 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Thu, 16 Apr 2015 12:48:01 -0700 Subject: fs/exec.c:de_thread: move notify_count write under lock We set sig->notify_count = -1 between RELEASE and ACQUIRE operations: spin_unlock_irq(lock); ... if (!thread_group_leader(tsk)) { ... for (;;) { sig->notify_count = -1; write_lock_irq(&tasklist_lock); There are no restriction on it so other processors may see this STORE mixed with other STOREs in both areas limited by the spinlocks. Probably, it may be reordered with the above sig->group_exit_task = tsk; sig->notify_count = zap_other_threads(tsk); in some way. Set it under tasklist_lock locked to be sure nothing will be reordered. Signed-off-by: Kirill Tkhai Acked-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/exec.c b/fs/exec.c index a5fef83..02bfd98 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -926,10 +926,14 @@ static int de_thread(struct task_struct *tsk) if (!thread_group_leader(tsk)) { struct task_struct *leader = tsk->group_leader; - sig->notify_count = -1; /* for exit_notify() */ for (;;) { threadgroup_change_begin(tsk); write_lock_irq(&tasklist_lock); + /* + * Do this under tasklist_lock to ensure that + * exit_notify() can't miss ->group_exit_task + */ + sig->notify_count = -1; if (likely(leader->exit_state)) break; __set_current_state(TASK_KILLABLE); -- cgit v0.10.2 From 534b483a86e6b96f1b5cc03bbe4b696f3daead6d Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Thu, 16 Apr 2015 12:48:04 -0700 Subject: cpumask: don't perform while loop in cpumask_next_and() cpumask_next_and() is looking for cpumask_next() in src1 in a loop and tests if found cpu is also present in src2. remove that loop, perform cpumask_and() of src1 and src2 first and use that new mask to find cpumask_next(). Apart from removing while loop, ./bloat-o-meter on x86_64 shows add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8 (-8) function old new delta cpumask_next_and 62 54 -8 Signed-off-by: Sergey Senozhatsky Cc: Tejun Heo Cc: "David S. Miller" Cc: Amir Vadai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/cpumask.c b/lib/cpumask.c index b6513a9..5ab1553 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -37,10 +37,11 @@ EXPORT_SYMBOL(__next_cpu_nr); int cpumask_next_and(int n, const struct cpumask *src1p, const struct cpumask *src2p) { - while ((n = cpumask_next(n, src1p)) < nr_cpu_ids) - if (cpumask_test_cpu(n, src2p)) - break; - return n; + struct cpumask tmp; + + if (cpumask_and(&tmp, src1p, src2p)) + return cpumask_next(n, &tmp); + return nr_cpu_ids; } EXPORT_SYMBOL(cpumask_next_and); -- cgit v0.10.2 From 230633d109e35b0a24277498e773edeb79b4a331 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Apr 2015 12:48:07 -0700 Subject: kernel/sysctl.c: detect overflows when converting to int When converting unsigned long to int overflows may occur. These currently are not detected when writing to the sysctl file system. E.g. on a system where int has 32 bits and long has 64 bits echo 0x800001234 > /proc/sys/kernel/threads-max has the same effect as echo 0x1234 > /proc/sys/kernel/threads-max The patch adds the missing check in do_proc_dointvec_conv. With the patch an overflow will result in an error EINVAL when writing to the the sysctl file system. Signed-off-by: Heinrich Schuchardt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3c09984..2082b1a 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1981,7 +1981,15 @@ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp, int write, void *data) { if (write) { - *valp = *negp ? -*lvalp : *lvalp; + if (*negp) { + if (*lvalp > (unsigned long) INT_MAX + 1) + return -EINVAL; + *valp = -*lvalp; + } else { + if (*lvalp > (unsigned long) INT_MAX) + return -EINVAL; + *valp = *lvalp; + } } else { int val = *valp; if (val < 0) { -- cgit v0.10.2 From 9d796e66230205cd3366f5660387bd9ecca9d336 Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Thu, 16 Apr 2015 12:48:10 -0700 Subject: gcov: fix softlockups gcov profiling if enabled with other heavy compile-time instrumentation like KASan could trigger following softlockups: NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [swapper/0:1] Modules linked in: irq event stamp: 22823276 hardirqs last enabled at (22823275): [] mutex_lock_nested+0x7d9/0x930 hardirqs last disabled at (22823276): [] apic_timer_interrupt+0x6d/0x80 softirqs last enabled at (22823172): [] __do_softirq+0x4db/0x729 softirqs last disabled at (22823167): [] irq_exit+0x7d/0x15b CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W 3.19.0-05245-gbb33326-dirty #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5.1-0-g8936dbb-20141113_115728-nilsson.home.kraxel.org 04/01/2014 task: ffff88006cba8000 ti: ffff88006cbb0000 task.ti: ffff88006cbb0000 RIP: kasan_mem_to_shadow+0x1e/0x1f Call Trace: strcmp+0x28/0x70 get_node_by_name+0x66/0x99 gcov_event+0x4f/0x69e gcov_enable_events+0x54/0x7b gcov_fs_init+0xf8/0x134 do_one_initcall+0x1b2/0x288 kernel_init_freeable+0x467/0x580 kernel_init+0x15/0x18b ret_from_fork+0x7c/0xb0 Kernel panic - not syncing: softlockup: hung tasks Fix this by sticking cond_resched() in gcov_enable_events(). Signed-off-by: Andrey Ryabinin Reported-by: Fengguang Wu Cc: Peter Oberparleiter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c index b358a80..a744098 100644 --- a/kernel/gcov/base.c +++ b/kernel/gcov/base.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "gcov.h" static int gcov_events_enabled; @@ -107,8 +108,10 @@ void gcov_enable_events(void) gcov_events_enabled = 1; /* Perform event callback for previously registered entries. */ - while ((info = gcov_info_next(info))) + while ((info = gcov_info_next(info))) { gcov_event(GCOV_ADD, info); + cond_resched(); + } mutex_unlock(&gcov_lock); } -- cgit v0.10.2 From b796410630a0f090864d7595c6bffbc0136f0f8c Mon Sep 17 00:00:00 2001 From: Sanidhya Kashyap Date: Thu, 16 Apr 2015 12:48:13 -0700 Subject: adfs: return correct return values Fix the wrong values returned by various functions such as EIO and ENOMEM. Signed-off-by: Sanidhya Kashyap Cc: Fabian Frederick Cc: Joe Perches Cc: Taesoo kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index f2ba88a..82d14cd 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c @@ -61,6 +61,7 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct kcalloc(size, sizeof(struct buffer_head *), GFP_KERNEL); if (!bh_fplus) { + ret = -ENOMEM; adfs_error(sb, "not enough memory for" " dir object %X (%d blocks)", id, size); goto out; diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 9852bdf..a19c31d 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -316,7 +316,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL); if (dm == NULL) { adfs_error(sb, "not enough memory"); - return NULL; + return ERR_PTR(-ENOMEM); } for (zone = 0; zone < nzones; zone++, map_addr++) { @@ -349,7 +349,7 @@ error_free: brelse(dm[zone].dm_bh); kfree(dm); - return NULL; + return ERR_PTR(-EIO); } static inline unsigned long adfs_discsize(struct adfs_discrecord *dr, int block_bits) @@ -370,6 +370,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) unsigned char *b_data; struct adfs_sb_info *asb; struct inode *root; + int ret = -EINVAL; sb->s_flags |= MS_NODIRATIME; @@ -391,6 +392,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) sb_set_blocksize(sb, BLOCK_SIZE); if (!(bh = sb_bread(sb, ADFS_DISCRECORD / BLOCK_SIZE))) { adfs_error(sb, "unable to read superblock"); + ret = -EIO; goto error; } @@ -400,6 +402,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) if (!silent) printk("VFS: Can't find an adfs filesystem on dev " "%s.\n", sb->s_id); + ret = -EINVAL; goto error_free_bh; } @@ -412,6 +415,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) if (!silent) printk("VPS: Can't find an adfs filesystem on dev " "%s.\n", sb->s_id); + ret = -EINVAL; goto error_free_bh; } @@ -421,11 +425,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) if (!bh) { adfs_error(sb, "couldn't read superblock on " "2nd try."); + ret = -EIO; goto error; } b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize); if (adfs_checkbblk(b_data)) { adfs_error(sb, "disc record mismatch, very weird!"); + ret = -EINVAL; goto error_free_bh; } dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET); @@ -433,6 +439,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) if (!silent) printk(KERN_ERR "VFS: Unsupported blocksize on dev " "%s.\n", sb->s_id); + ret = -EINVAL; goto error; } @@ -447,10 +454,12 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) asb->s_size = adfs_discsize(dr, sb->s_blocksize_bits); asb->s_version = dr->format_version; asb->s_log2sharesize = dr->log2sharesize; - + asb->s_map = adfs_read_map(sb, dr); - if (!asb->s_map) + if (IS_ERR(asb->s_map)) { + ret = PTR_ERR(asb->s_map); goto error_free_bh; + } brelse(bh); @@ -499,6 +508,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) brelse(asb->s_map[i].dm_bh); kfree(asb->s_map); adfs_error(sb, "get root inode failed\n"); + ret = -EIO; goto error; } return 0; @@ -508,7 +518,7 @@ error_free_bh: error: sb->s_fs_info = NULL; kfree(asb); - return -EINVAL; + return ret; } static struct dentry *adfs_mount(struct file_system_type *fs_type, -- cgit v0.10.2 From a0016ff2867ad25aad9807fb46bd0d85429dd5e8 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:48:15 -0700 Subject: fs/affs: use AFFS_MOUNT prefix for mount options Currently, affs still uses direct access on mount_options. This patch prepares to use affs_clear/set/test_opt() like other filesystems. Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/affs.h b/fs/affs/affs.h index c8764bd..35a855a 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -106,18 +106,18 @@ struct affs_sb_info { spinlock_t work_lock; /* protects sb_work and work_queued */ }; -#define SF_INTL 0x0001 /* International filesystem. */ -#define SF_BM_VALID 0x0002 /* Bitmap is valid. */ -#define SF_IMMUTABLE 0x0004 /* Protection bits cannot be changed */ -#define SF_QUIET 0x0008 /* chmod errors will be not reported */ -#define SF_SETUID 0x0010 /* Ignore Amiga uid */ -#define SF_SETGID 0x0020 /* Ignore Amiga gid */ -#define SF_SETMODE 0x0040 /* Ignore Amiga protection bits */ -#define SF_MUFS 0x0100 /* Use MUFS uid/gid mapping */ -#define SF_OFS 0x0200 /* Old filesystem */ -#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ -#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */ -#define SF_NO_TRUNCATE 0x1000 /* Don't truncate filenames */ +#define AFFS_MOUNT_SF_INTL 0x0001 /* International filesystem. */ +#define AFFS_MOUNT_SF_BM_VALID 0x0002 /* Bitmap is valid. */ +#define AFFS_MOUNT_SF_IMMUTABLE 0x0004 /* Protection bits cannot be changed */ +#define AFFS_MOUNT_SF_QUIET 0x0008 /* chmod errors will be not reported */ +#define AFFS_MOUNT_SF_SETUID 0x0010 /* Ignore Amiga uid */ +#define AFFS_MOUNT_SF_SETGID 0x0020 /* Ignore Amiga gid */ +#define AFFS_MOUNT_SF_SETMODE 0x0040 /* Ignore Amiga protection bits */ +#define AFFS_MOUNT_SF_MUFS 0x0100 /* Use MUFS uid/gid mapping */ +#define AFFS_MOUNT_SF_OFS 0x0200 /* Old filesystem */ +#define AFFS_MOUNT_SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ +#define AFFS_MOUNT_SF_VERBOSE 0x0800 /* Talk about fs when mounting */ +#define AFFS_MOUNT_SF_NO_TRUNCATE 0x1000 /* Don't truncate filenames */ /* short cut to get to the affs specific sb data */ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 388da1e..1a90e19 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -472,7 +472,7 @@ bool affs_nofilenametruncate(const struct dentry *dentry) { struct inode *inode = dentry->d_inode; - return AFFS_SB(inode->i_sb)->s_flags & SF_NO_TRUNCATE; + return AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_NO_TRUNCATE; } diff --git a/fs/affs/file.c b/fs/affs/file.c index 7c1a3d4..2e24759 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -915,7 +915,7 @@ affs_truncate(struct inode *inode) if (inode->i_size) { AFFS_I(inode)->i_blkcnt = last_blk + 1; AFFS_I(inode)->i_extcnt = ext + 1; - if (AFFS_SB(sb)->s_flags & SF_OFS) { + if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_OFS) { struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0); u32 tmp; if (IS_ERR(bh)) { diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 6f34510..53af66b 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -66,23 +66,23 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) AFFS_I(inode)->i_lastalloc = 0; AFFS_I(inode)->i_pa_cnt = 0; - if (sbi->s_flags & SF_SETMODE) + if (sbi->s_flags & AFFS_MOUNT_SF_SETMODE) inode->i_mode = sbi->s_mode; else inode->i_mode = prot_to_mode(prot); id = be16_to_cpu(tail->uid); - if (id == 0 || sbi->s_flags & SF_SETUID) + if (id == 0 || sbi->s_flags & AFFS_MOUNT_SF_SETUID) inode->i_uid = sbi->s_uid; - else if (id == 0xFFFF && sbi->s_flags & SF_MUFS) + else if (id == 0xFFFF && sbi->s_flags & AFFS_MOUNT_SF_MUFS) i_uid_write(inode, 0); else i_uid_write(inode, id); id = be16_to_cpu(tail->gid); - if (id == 0 || sbi->s_flags & SF_SETGID) + if (id == 0 || sbi->s_flags & AFFS_MOUNT_SF_SETGID) inode->i_gid = sbi->s_gid; - else if (id == 0xFFFF && sbi->s_flags & SF_MUFS) + else if (id == 0xFFFF && sbi->s_flags & AFFS_MOUNT_SF_MUFS) i_gid_write(inode, 0); else i_gid_write(inode, id); @@ -94,7 +94,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) /* fall through */ case ST_USERDIR: if (be32_to_cpu(tail->stype) == ST_USERDIR || - sbi->s_flags & SF_SETMODE) { + sbi->s_flags & AFFS_MOUNT_SF_SETMODE) { if (inode->i_mode & S_IRUSR) inode->i_mode |= S_IXUSR; if (inode->i_mode & S_IRGRP) @@ -133,7 +133,8 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) } if (tail->link_chain) set_nlink(inode, 2); - inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; + inode->i_mapping->a_ops = (sbi->s_flags & AFFS_MOUNT_SF_OFS) ? + &affs_aops_ofs : &affs_aops; inode->i_op = &affs_file_inode_operations; inode->i_fop = &affs_file_operations; break; @@ -190,15 +191,15 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc) if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) { uid = i_uid_read(inode); gid = i_gid_read(inode); - if (AFFS_SB(sb)->s_flags & SF_MUFS) { + if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_MUFS) { if (uid == 0 || uid == 0xFFFF) uid = uid ^ ~0; if (gid == 0 || gid == 0xFFFF) gid = gid ^ ~0; } - if (!(AFFS_SB(sb)->s_flags & SF_SETUID)) + if (!(AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_SETUID)) tail->uid = cpu_to_be16(uid); - if (!(AFFS_SB(sb)->s_flags & SF_SETGID)) + if (!(AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_SETGID)) tail->gid = cpu_to_be16(gid); } } @@ -221,11 +222,14 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) if (error) goto out; - if (((attr->ia_valid & ATTR_UID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETUID)) || - ((attr->ia_valid & ATTR_GID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETGID)) || + if (((attr->ia_valid & ATTR_UID) && + (AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_SETUID)) || + ((attr->ia_valid & ATTR_GID) && + (AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_SETGID)) || ((attr->ia_valid & ATTR_MODE) && - (AFFS_SB(inode->i_sb)->s_flags & (SF_SETMODE | SF_IMMUTABLE)))) { - if (!(AFFS_SB(inode->i_sb)->s_flags & SF_QUIET)) + (AFFS_SB(inode->i_sb)->s_flags & + (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) { + if (!(AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_QUIET)) error = -EPERM; goto out; } diff --git a/fs/affs/namei.c b/fs/affs/namei.c index ffb7bd8..aaa81ab 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -53,7 +53,8 @@ affs_intl_toupper(int ch) static inline toupper_t affs_get_toupper(struct super_block *sb) { - return AFFS_SB(sb)->s_flags & SF_INTL ? affs_intl_toupper : affs_toupper; + return AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_INTL ? + affs_intl_toupper : affs_toupper; } /* @@ -275,7 +276,8 @@ affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) inode->i_op = &affs_file_inode_operations; inode->i_fop = &affs_file_operations; - inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops; + inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_OFS) ? + &affs_aops_ofs : &affs_aops; error = affs_add_entry(dir, inode, dentry, ST_FILE); if (error) { clear_nlink(inode); diff --git a/fs/affs/super.c b/fs/affs/super.c index 4cf0e91..5623b49 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -227,22 +227,22 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, if (match_octal(&args[0], &option)) return 0; *mode = option & 0777; - *mount_opts |= SF_SETMODE; + *mount_opts |= AFFS_MOUNT_SF_SETMODE; break; case Opt_mufs: - *mount_opts |= SF_MUFS; + *mount_opts |= AFFS_MOUNT_SF_MUFS; break; case Opt_notruncate: - *mount_opts |= SF_NO_TRUNCATE; + *mount_opts |= AFFS_MOUNT_SF_NO_TRUNCATE; break; case Opt_prefix: *prefix = match_strdup(&args[0]); if (!*prefix) return 0; - *mount_opts |= SF_PREFIX; + *mount_opts |= AFFS_MOUNT_SF_PREFIX; break; case Opt_protect: - *mount_opts |= SF_IMMUTABLE; + *mount_opts |= AFFS_MOUNT_SF_IMMUTABLE; break; case Opt_reserved: if (match_int(&args[0], reserved)) @@ -258,7 +258,7 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, *gid = make_kgid(current_user_ns(), option); if (!gid_valid(*gid)) return 0; - *mount_opts |= SF_SETGID; + *mount_opts |= AFFS_MOUNT_SF_SETGID; break; case Opt_setuid: if (match_int(&args[0], &option)) @@ -266,10 +266,10 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, *uid = make_kuid(current_user_ns(), option); if (!uid_valid(*uid)) return 0; - *mount_opts |= SF_SETUID; + *mount_opts |= AFFS_MOUNT_SF_SETUID; break; case Opt_verbose: - *mount_opts |= SF_VERBOSE; + *mount_opts |= AFFS_MOUNT_SF_VERBOSE; break; case Opt_volume: { char *vol = match_strdup(&args[0]); @@ -435,30 +435,30 @@ got_root: case MUFS_FS: case MUFS_INTLFFS: case MUFS_DCFFS: - sbi->s_flags |= SF_MUFS; + sbi->s_flags |= AFFS_MOUNT_SF_MUFS; /* fall thru */ case FS_INTLFFS: case FS_DCFFS: - sbi->s_flags |= SF_INTL; + sbi->s_flags |= AFFS_MOUNT_SF_INTL; break; case MUFS_FFS: - sbi->s_flags |= SF_MUFS; + sbi->s_flags |= AFFS_MOUNT_SF_MUFS; break; case FS_FFS: break; case MUFS_OFS: - sbi->s_flags |= SF_MUFS; + sbi->s_flags |= AFFS_MOUNT_SF_MUFS; /* fall thru */ case FS_OFS: - sbi->s_flags |= SF_OFS; + sbi->s_flags |= AFFS_MOUNT_SF_OFS; sb->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: - sbi->s_flags |= SF_MUFS; + sbi->s_flags |= AFFS_MOUNT_SF_MUFS; case FS_DCOFS: case FS_INTLOFS: - sbi->s_flags |= SF_INTL | SF_OFS; + sbi->s_flags |= AFFS_MOUNT_SF_INTL | AFFS_MOUNT_SF_OFS; sb->s_flags |= MS_NOEXEC; break; default: @@ -467,7 +467,7 @@ got_root: return -EINVAL; } - if (mount_flags & SF_VERBOSE) { + if (mount_flags & AFFS_MOUNT_SF_VERBOSE) { u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0]; pr_notice("Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n", len > 31 ? 31 : len, @@ -478,7 +478,7 @@ got_root: sb->s_flags |= MS_NODEV | MS_NOSUID; sbi->s_data_blksize = sb->s_blocksize; - if (sbi->s_flags & SF_OFS) + if (sbi->s_flags & AFFS_MOUNT_SF_OFS) sbi->s_data_blksize -= 24; tmp_flags = sb->s_flags; @@ -493,7 +493,7 @@ got_root: if (IS_ERR(root_inode)) return PTR_ERR(root_inode); - if (AFFS_SB(sb)->s_flags & SF_INTL) + if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_INTL) sb->s_d_op = &affs_intl_dentry_operations; else sb->s_d_op = &affs_dentry_operations; -- cgit v0.10.2 From 6bf445ce35353fe865664af0dbaeb848f0a2820f Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:48:18 -0700 Subject: fs/affs/affs.h: add mount option manipulation macros Add clear/set/test affs mount option macros. Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 35a855a..cffe837 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -119,6 +119,10 @@ struct affs_sb_info { #define AFFS_MOUNT_SF_VERBOSE 0x0800 /* Talk about fs when mounting */ #define AFFS_MOUNT_SF_NO_TRUNCATE 0x1000 /* Don't truncate filenames */ +#define affs_clear_opt(o, opt) (o &= ~AFFS_MOUNT_##opt) +#define affs_set_opt(o, opt) (o |= AFFS_MOUNT_##opt) +#define affs_test_opt(o, opt) ((o) & AFFS_MOUNT_##opt) + /* short cut to get to the affs specific sb data */ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) { -- cgit v0.10.2 From 34f24835383092098cb4ce5c4eb6e719a9973d68 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:48:21 -0700 Subject: fs/affs/super.c: use affs_set_opt() Replace direct mount option assignation by affs_set_opt() macro. Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/super.c b/fs/affs/super.c index 5623b49..32bfad4 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -227,22 +227,22 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, if (match_octal(&args[0], &option)) return 0; *mode = option & 0777; - *mount_opts |= AFFS_MOUNT_SF_SETMODE; + affs_set_opt(*mount_opts, SF_SETMODE); break; case Opt_mufs: - *mount_opts |= AFFS_MOUNT_SF_MUFS; + affs_set_opt(*mount_opts, SF_MUFS); break; case Opt_notruncate: - *mount_opts |= AFFS_MOUNT_SF_NO_TRUNCATE; + affs_set_opt(*mount_opts, SF_NO_TRUNCATE); break; case Opt_prefix: *prefix = match_strdup(&args[0]); if (!*prefix) return 0; - *mount_opts |= AFFS_MOUNT_SF_PREFIX; + affs_set_opt(*mount_opts, SF_PREFIX); break; case Opt_protect: - *mount_opts |= AFFS_MOUNT_SF_IMMUTABLE; + affs_set_opt(*mount_opts, SF_IMMUTABLE); break; case Opt_reserved: if (match_int(&args[0], reserved)) @@ -258,7 +258,7 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, *gid = make_kgid(current_user_ns(), option); if (!gid_valid(*gid)) return 0; - *mount_opts |= AFFS_MOUNT_SF_SETGID; + affs_set_opt(*mount_opts, SF_SETGID); break; case Opt_setuid: if (match_int(&args[0], &option)) @@ -266,10 +266,10 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, *uid = make_kuid(current_user_ns(), option); if (!uid_valid(*uid)) return 0; - *mount_opts |= AFFS_MOUNT_SF_SETUID; + affs_set_opt(*mount_opts, SF_SETUID); break; case Opt_verbose: - *mount_opts |= AFFS_MOUNT_SF_VERBOSE; + affs_set_opt(*mount_opts, SF_VERBOSE); break; case Opt_volume: { char *vol = match_strdup(&args[0]); @@ -435,30 +435,31 @@ got_root: case MUFS_FS: case MUFS_INTLFFS: case MUFS_DCFFS: - sbi->s_flags |= AFFS_MOUNT_SF_MUFS; + affs_set_opt(sbi->s_flags, SF_MUFS); /* fall thru */ case FS_INTLFFS: case FS_DCFFS: - sbi->s_flags |= AFFS_MOUNT_SF_INTL; + affs_set_opt(sbi->s_flags, SF_INTL); break; case MUFS_FFS: - sbi->s_flags |= AFFS_MOUNT_SF_MUFS; + affs_set_opt(sbi->s_flags, SF_MUFS); break; case FS_FFS: break; case MUFS_OFS: - sbi->s_flags |= AFFS_MOUNT_SF_MUFS; + affs_set_opt(sbi->s_flags, SF_MUFS); /* fall thru */ case FS_OFS: - sbi->s_flags |= AFFS_MOUNT_SF_OFS; + affs_set_opt(sbi->s_flags, SF_OFS); sb->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: - sbi->s_flags |= AFFS_MOUNT_SF_MUFS; + affs_set_opt(sbi->s_flags, SF_MUFS); case FS_DCOFS: case FS_INTLOFS: - sbi->s_flags |= AFFS_MOUNT_SF_INTL | AFFS_MOUNT_SF_OFS; + affs_set_opt(sbi->s_flags, SF_INTL); + affs_set_opt(sbi->s_flags, SF_OFS); sb->s_flags |= MS_NOEXEC; break; default: -- cgit v0.10.2 From 79bda4d510f80e403ef66fee852f8ccb17308581 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 16 Apr 2015 12:48:24 -0700 Subject: fs/affs: use affs_test_opt() Replace mount option test by affs_test_opt(). Signed-off-by: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 1a90e19..5022ac9 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -472,7 +472,8 @@ bool affs_nofilenametruncate(const struct dentry *dentry) { struct inode *inode = dentry->d_inode; - return AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_NO_TRUNCATE; + + return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE); } diff --git a/fs/affs/file.c b/fs/affs/file.c index 2e24759..7f506fb 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -915,7 +915,7 @@ affs_truncate(struct inode *inode) if (inode->i_size) { AFFS_I(inode)->i_blkcnt = last_blk + 1; AFFS_I(inode)->i_extcnt = ext + 1; - if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_OFS) { + if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS)) { struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0); u32 tmp; if (IS_ERR(bh)) { diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 53af66b..9628003 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -66,23 +66,23 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) AFFS_I(inode)->i_lastalloc = 0; AFFS_I(inode)->i_pa_cnt = 0; - if (sbi->s_flags & AFFS_MOUNT_SF_SETMODE) + if (affs_test_opt(sbi->s_flags, SF_SETMODE)) inode->i_mode = sbi->s_mode; else inode->i_mode = prot_to_mode(prot); id = be16_to_cpu(tail->uid); - if (id == 0 || sbi->s_flags & AFFS_MOUNT_SF_SETUID) + if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID)) inode->i_uid = sbi->s_uid; - else if (id == 0xFFFF && sbi->s_flags & AFFS_MOUNT_SF_MUFS) + else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS)) i_uid_write(inode, 0); else i_uid_write(inode, id); id = be16_to_cpu(tail->gid); - if (id == 0 || sbi->s_flags & AFFS_MOUNT_SF_SETGID) + if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID)) inode->i_gid = sbi->s_gid; - else if (id == 0xFFFF && sbi->s_flags & AFFS_MOUNT_SF_MUFS) + else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS)) i_gid_write(inode, 0); else i_gid_write(inode, id); @@ -94,7 +94,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) /* fall through */ case ST_USERDIR: if (be32_to_cpu(tail->stype) == ST_USERDIR || - sbi->s_flags & AFFS_MOUNT_SF_SETMODE) { + affs_test_opt(sbi->s_flags, SF_SETMODE)) { if (inode->i_mode & S_IRUSR) inode->i_mode |= S_IXUSR; if (inode->i_mode & S_IRGRP) @@ -133,7 +133,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) } if (tail->link_chain) set_nlink(inode, 2); - inode->i_mapping->a_ops = (sbi->s_flags & AFFS_MOUNT_SF_OFS) ? + inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ? &affs_aops_ofs : &affs_aops; inode->i_op = &affs_file_inode_operations; inode->i_fop = &affs_file_operations; @@ -191,15 +191,15 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc) if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) { uid = i_uid_read(inode); gid = i_gid_read(inode); - if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_MUFS) { + if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) { if (uid == 0 || uid == 0xFFFF) uid = uid ^ ~0; if (gid == 0 || gid == 0xFFFF) gid = gid ^ ~0; } - if (!(AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_SETUID)) + if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID)) tail->uid = cpu_to_be16(uid); - if (!(AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_SETGID)) + if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID)) tail->gid = cpu_to_be16(gid); } } @@ -223,13 +223,13 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) goto out; if (((attr->ia_valid & ATTR_UID) && - (AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_SETUID)) || + affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) || ((attr->ia_valid & ATTR_GID) && - (AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_SETGID)) || + affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) || ((attr->ia_valid & ATTR_MODE) && (AFFS_SB(inode->i_sb)->s_flags & (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) { - if (!(AFFS_SB(inode->i_sb)->s_flags & AFFS_MOUNT_SF_QUIET)) + if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET)) error = -EPERM; goto out; } diff --git a/fs/affs/namei.c b/fs/affs/namei.c index aaa81ab..ec8ca0e 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -53,8 +53,8 @@ affs_intl_toupper(int ch) static inline toupper_t affs_get_toupper(struct super_block *sb) { - return AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_INTL ? - affs_intl_toupper : affs_toupper; + return affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL) ? + affs_intl_toupper : affs_toupper; } /* @@ -276,7 +276,7 @@ affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) inode->i_op = &affs_file_inode_operations; inode->i_fop = &affs_file_operations; - inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_OFS) ? + inode->i_mapping->a_ops = affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS) ? &affs_aops_ofs : &affs_aops; error = affs_add_entry(dir, inode, dentry, ST_FILE); if (error) { diff --git a/fs/affs/super.c b/fs/affs/super.c index 32bfad4..6819d04 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -468,7 +468,7 @@ got_root: return -EINVAL; } - if (mount_flags & AFFS_MOUNT_SF_VERBOSE) { + if (affs_test_opt(mount_flags, SF_VERBOSE)) { u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0]; pr_notice("Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n", len > 31 ? 31 : len, @@ -479,7 +479,7 @@ got_root: sb->s_flags |= MS_NODEV | MS_NOSUID; sbi->s_data_blksize = sb->s_blocksize; - if (sbi->s_flags & AFFS_MOUNT_SF_OFS) + if (affs_test_opt(sbi->s_flags, SF_OFS)) sbi->s_data_blksize -= 24; tmp_flags = sb->s_flags; @@ -494,7 +494,7 @@ got_root: if (IS_ERR(root_inode)) return PTR_ERR(root_inode); - if (AFFS_SB(sb)->s_flags & AFFS_MOUNT_SF_INTL) + if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL)) sb->s_d_op = &affs_intl_dentry_operations; else sb->s_d_op = &affs_dentry_operations; -- cgit v0.10.2 From c8f33d0bec999a4f2b5c3f9380361b88ce6f6ab0 Mon Sep 17 00:00:00 2001 From: Sanidhya Kashyap Date: Thu, 16 Apr 2015 12:48:26 -0700 Subject: affs: kstrdup() memory handling There is a possibility of kstrdup() failure upon memory pressure. Therefore, returning ENOMEM even for new_opts. [akpm@linux-foundation.org: cleanup] Signed-off-by: Sanidhya Kashyap Cc: Taesoo kim Cc: Fabian Frederick Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/affs/super.c b/fs/affs/super.c index 6819d04..3f89c9e 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -521,10 +521,14 @@ affs_remount(struct super_block *sb, int *flags, char *data) int root_block; unsigned long mount_flags; int res = 0; - char *new_opts = kstrdup(data, GFP_KERNEL); + char *new_opts; char volume[32]; char *prefix = NULL; + new_opts = kstrdup(data, GFP_KERNEL); + if (!new_opts) + return -ENOMEM; + pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data); sync_filesystem(sb); -- cgit v0.10.2 From 8f7d3f0f1ed5dce6ea7b833ec19cabe61a6e7ff8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 16 Apr 2015 12:48:29 -0700 Subject: bfs: bfad_worker cleanup This kthread is not loop at all due to break at the end of the loop. Make that function linear, with no while loop. And remove an unnecessary cast. Signed-off-by: Jiri Slaby Cc: Anil Gurumurthy Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index e90a374..cc3b9d3 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1079,22 +1079,18 @@ bfad_start_ops(struct bfad_s *bfad) { int bfad_worker(void *ptr) { - struct bfad_s *bfad; - unsigned long flags; - - bfad = (struct bfad_s *)ptr; - - while (!kthread_should_stop()) { + struct bfad_s *bfad = ptr; + unsigned long flags; - /* Send event BFAD_E_INIT_SUCCESS */ - bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS); + if (kthread_should_stop()) + return 0; - spin_lock_irqsave(&bfad->bfad_lock, flags); - bfad->bfad_tsk = NULL; - spin_unlock_irqrestore(&bfad->bfad_lock, flags); + /* Send event BFAD_E_INIT_SUCCESS */ + bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS); - break; - } + spin_lock_irqsave(&bfad->bfad_lock, flags); + bfad->bfad_tsk = NULL; + spin_unlock_irqrestore(&bfad->bfad_lock, flags); return 0; } -- cgit v0.10.2 From c3fe5872eb3f5f9e027d61d8a3f5d092168fdbca Mon Sep 17 00:00:00 2001 From: Sanidhya Kashyap Date: Thu, 16 Apr 2015 12:48:32 -0700 Subject: bfs: correct return values In case of failed memory allocation, the return should be ENOMEM instead of ENOSPC. Return -EIO when sb_bread() fails. Signed-off-by: Sanidhya Kashyap Cc: Tigran Aivazian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 08063ae..7a818277 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -86,7 +86,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, inode = new_inode(s); if (!inode) - return -ENOSPC; + return -ENOMEM; mutex_lock(&info->bfs_lock); ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1); if (ino > info->si_lasti) { @@ -293,7 +293,7 @@ static int bfs_add_entry(struct inode *dir, const unsigned char *name, for (block = sblock; block <= eblock; block++) { bh = sb_bread(dir->i_sb, block); if (!bh) - return -ENOSPC; + return -EIO; for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) { de = (struct bfs_dirent *)(bh->b_data + off); if (!de->ino) { -- cgit v0.10.2 From 13f6b191aaa11c7fd718d35a0c565f3c16bc1d99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Apr 2015 12:48:35 -0700 Subject: memstick: mspro_block: add missing curly braces Using the indenting we can see the curly braces were obviously intended. This is a static checker fix, but my guess is that we don't read enough bytes, because we don't calculate "t_len" correctly. Fixes: f1d82698029b ('memstick: use fully asynchronous request processing') Signed-off-by: Dan Carpenter Cc: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index fc145d2..922a750 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { if (msb->data_dir == READ) { - for (cnt = 0; cnt < msb->current_seg; cnt++) + for (cnt = 0; cnt < msb->current_seg; cnt++) { t_len += msb->req_sg[cnt].length / msb->page_size; @@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) t_len += msb->current_page - 1; t_len *= msb->page_size; + } } } else t_len = blk_rq_bytes(msb->block_req); -- cgit v0.10.2 From 02d699f1f464410d5753a034dd38c76a1a1647e0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2015 12:48:38 -0700 Subject: include/linux/kconfig.h: ese macros which are already defined It is better to use macros which are already available because then there is just one location which needs to be change. [akpm@linux-foundation.org: move IS_ENABLED definition to after the IS_BUILTIN and IS_MODULE definitions] Signed-off-by: Michal Simek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h index be342b9..63ca8da 100644 --- a/include/linux/kconfig.h +++ b/include/linux/kconfig.h @@ -23,14 +23,6 @@ #define ___config_enabled(__ignored, val, ...) val /* - * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', - * 0 otherwise. - * - */ -#define IS_ENABLED(option) \ - (config_enabled(option) || config_enabled(option##_MODULE)) - -/* * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 * otherwise. For boolean options, this is equivalent to * IS_ENABLED(CONFIG_FOO). @@ -43,4 +35,11 @@ */ #define IS_MODULE(option) config_enabled(option##_MODULE) +/* + * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', + * 0 otherwise. + */ +#define IS_ENABLED(option) \ + (IS_BUILTIN(option) || IS_MODULE(option)) + #endif /* __LINUX_KCONFIG_H */ -- cgit v0.10.2 From be2a7fce397d82b7dc3fdbc61fb0bdab118e65ca Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:48:40 -0700 Subject: arc: do not export symbols in troubleshoot.c print_task_path_n_nm() is local to this file, its only user being show_regs(). Mark the function static and avoid the EXPORT_SYMBOL. Signed-off-by: Davidlohr Bueso Acked-by: Vineet Gupta Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 1badf9b..e00a018 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -52,7 +52,7 @@ static void show_callee_regs(struct callee_regs *cregs) print_reg_file(&(cregs->r13), 13); } -void print_task_path_n_nm(struct task_struct *tsk, char *buf) +static void print_task_path_n_nm(struct task_struct *tsk, char *buf) { struct path path; char *path_nm = NULL; @@ -77,7 +77,6 @@ void print_task_path_n_nm(struct task_struct *tsk, char *buf) done: pr_info("Path: %s\n", path_nm); } -EXPORT_SYMBOL(print_task_path_n_nm); static void show_faulting_vma(unsigned long address, char *buf) { -- cgit v0.10.2 From ddaa27ee627fb58d1a68eb1eb196393d64c25d1b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:44 -0700 Subject: seccomp: allow COMPAT sigreturn overrides Most architectures don't need to do much special for the strict-mode seccomp syscall entries. Remove the redundant headers and reduce the others. This patch (of 8): Some architectures may need to override the compat sigreturn definition, as is already possible in the non-compat case. Signed-off-by: Kees Cook Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Thomas Gleixner Cc: Russell King Cc: Michal Simek Cc: Ralf Baechle Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: "David S. Miller" Cc: Arnd Bergmann Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Will Deacon Cc: Daniel Borkmann Cc: Laura Abbott Cc: James Hogan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-generic/seccomp.h b/include/asm-generic/seccomp.h index 9fa1f65..c9ccafa 100644 --- a/include/asm-generic/seccomp.h +++ b/include/asm-generic/seccomp.h @@ -17,7 +17,9 @@ #define __NR_seccomp_read_32 __NR_read #define __NR_seccomp_write_32 __NR_write #define __NR_seccomp_exit_32 __NR_exit +#ifndef __NR_seccomp_sigreturn_32 #define __NR_seccomp_sigreturn_32 __NR_rt_sigreturn +#endif #endif /* CONFIG_COMPAT && ! already defined */ #define __NR_seccomp_read __NR_read -- cgit v0.10.2 From 6bcf4e9aab9e9f718edebe77712512fc5c4ecd3e Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:47 -0700 Subject: arm: use asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. Definitions were identical. Signed-off-by: Kees Cook Cc: Russell King Cc: Laura Abbott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index eb0f43f..3c4596d 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -21,6 +21,7 @@ generic-y += preempt.h generic-y += resource.h generic-y += rwsem.h generic-y += scatterlist.h +generic-y += seccomp.h generic-y += sections.h generic-y += segment.h generic-y += sembuf.h diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h deleted file mode 100644 index 52b156b..0000000 --- a/arch/arm/include/asm/seccomp.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _ASM_ARM_SECCOMP_H -#define _ASM_ARM_SECCOMP_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#endif /* _ASM_ARM_SECCOMP_H */ -- cgit v0.10.2 From cc2d316fe7b2f39ecacdbd4be04fccbc2476cb7a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:50 -0700 Subject: microblaze: use asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. Since microblaze is 32-bit, the COMPAT seccomp defines are unused and can be dropped. The obsolete sigreturn for seccomp strict mode is retained as an override. Remaining definitions are identical. Signed-off-by: Kees Cook Cc: Michal Simek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/microblaze/include/asm/seccomp.h b/arch/microblaze/include/asm/seccomp.h index 0d91275..204618a 100644 --- a/arch/microblaze/include/asm/seccomp.h +++ b/arch/microblaze/include/asm/seccomp.h @@ -3,14 +3,8 @@ #include -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit #define __NR_seccomp_sigreturn __NR_sigreturn -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit -#define __NR_seccomp_sigreturn_32 __NR_sigreturn +#include #endif /* _ASM_MICROBLAZE_SECCOMP_H */ -- cgit v0.10.2 From 97247fd99da723ce2c87a45e714c332b71e3e003 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:53 -0700 Subject: mips: switch to using asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. COMPAT definitions retain their overrides and the remaining definitions were identical. Signed-off-by: Kees Cook Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index f29c75c..1d8a2e2 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -2,11 +2,6 @@ #include -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - /* * Kludge alert: * @@ -29,4 +24,6 @@ #endif /* CONFIG_MIPS32_O32 */ +#include + #endif /* __ASM_SECCOMP_H */ -- cgit v0.10.2 From cf7a71b602fe2255b5b42162fa39a3090a1ea2c7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:55 -0700 Subject: parisc: switch to using asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. Definitions were identical. Signed-off-by: Kees Cook Cc: "James E.J. Bottomley" Cc: Helge Deller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index 8686237..12b341d 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild @@ -20,6 +20,7 @@ generic-y += param.h generic-y += percpu.h generic-y += poll.h generic-y += preempt.h +generic-y += seccomp.h generic-y += segment.h generic-y += topology.h generic-y += trace_clock.h diff --git a/arch/parisc/include/asm/seccomp.h b/arch/parisc/include/asm/seccomp.h deleted file mode 100644 index 015f788..0000000 --- a/arch/parisc/include/asm/seccomp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ASM_PARISC_SECCOMP_H -#define _ASM_PARISC_SECCOMP_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit -#define __NR_seccomp_sigreturn_32 __NR_rt_sigreturn - -#endif /* _ASM_PARISC_SECCOMP_H */ -- cgit v0.10.2 From 1a3aff9ec376666563c7a2223a1d6c19f908919d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:48:58 -0700 Subject: powerpc: switch to using asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. The obsolete sigreturn in COMPAT mode is retained as an override. Remaining definitions are identical, though they incorrectly appeared in uapi, which has been corrected. Signed-off-by: Kees Cook Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h new file mode 100644 index 0000000..c1818e3 --- /dev/null +++ b/arch/powerpc/include/asm/seccomp.h @@ -0,0 +1,10 @@ +#ifndef _ASM_POWERPC_SECCOMP_H +#define _ASM_POWERPC_SECCOMP_H + +#include + +#define __NR_seccomp_sigreturn_32 __NR_sigreturn + +#include + +#endif /* _ASM_POWERPC_SECCOMP_H */ diff --git a/arch/powerpc/include/uapi/asm/Kbuild b/arch/powerpc/include/uapi/asm/Kbuild index 7a3f795..79c4068 100644 --- a/arch/powerpc/include/uapi/asm/Kbuild +++ b/arch/powerpc/include/uapi/asm/Kbuild @@ -25,7 +25,6 @@ header-y += posix_types.h header-y += ps3fb.h header-y += ptrace.h header-y += resource.h -header-y += seccomp.h header-y += sembuf.h header-y += setup.h header-y += shmbuf.h diff --git a/arch/powerpc/include/uapi/asm/seccomp.h b/arch/powerpc/include/uapi/asm/seccomp.h deleted file mode 100644 index 00c1d91..0000000 --- a/arch/powerpc/include/uapi/asm/seccomp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ASM_POWERPC_SECCOMP_H -#define _ASM_POWERPC_SECCOMP_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit -#define __NR_seccomp_sigreturn_32 __NR_sigreturn - -#endif /* _ASM_POWERPC_SECCOMP_H */ -- cgit v0.10.2 From d0f138b0853e3b0a0bcd83f3019d34842e12951d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:49:01 -0700 Subject: sparc: switch to using asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. The obsolete sigreturn in COMPAT mode is retained as an override. Remaining definitions are identical. Also corrected missing #define for header reinclusion protection. Signed-off-by: Kees Cook Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/sparc/include/asm/seccomp.h b/arch/sparc/include/asm/seccomp.h index adca1bc..5ef8826 100644 --- a/arch/sparc/include/asm/seccomp.h +++ b/arch/sparc/include/asm/seccomp.h @@ -1,15 +1,10 @@ #ifndef _ASM_SECCOMP_H +#define _ASM_SECCOMP_H #include -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_read -#define __NR_seccomp_write_32 __NR_write -#define __NR_seccomp_exit_32 __NR_exit #define __NR_seccomp_sigreturn_32 __NR_sigreturn +#include + #endif /* _ASM_SECCOMP_H */ -- cgit v0.10.2 From 8eb68bf75eb7ea73bce88cb9d42efd3bbcece3cd Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 16 Apr 2015 12:49:04 -0700 Subject: x86: switch to using asm-generic for seccomp.h Switch to using the newly created asm-generic/seccomp.h for the seccomp strict mode syscall definitions. The obsolete sigreturn syscall override is retained in 32-bit mode, and the ia32 syscall overrides are used in the compat case. Remaining definitions were identical. Signed-off-by: Kees Cook Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86/include/asm/seccomp.h b/arch/x86/include/asm/seccomp.h index 0f3d7f0..0c8c7c8 100644 --- a/arch/x86/include/asm/seccomp.h +++ b/arch/x86/include/asm/seccomp.h @@ -1,5 +1,20 @@ +#ifndef _ASM_X86_SECCOMP_H +#define _ASM_X86_SECCOMP_H + +#include + #ifdef CONFIG_X86_32 -# include -#else -# include +#define __NR_seccomp_sigreturn __NR_sigreturn #endif + +#ifdef CONFIG_COMPAT +#include +#define __NR_seccomp_read_32 __NR_ia32_read +#define __NR_seccomp_write_32 __NR_ia32_write +#define __NR_seccomp_exit_32 __NR_ia32_exit +#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn +#endif + +#include + +#endif /* _ASM_X86_SECCOMP_H */ diff --git a/arch/x86/include/asm/seccomp_32.h b/arch/x86/include/asm/seccomp_32.h deleted file mode 100644 index b811d6f..0000000 --- a/arch/x86/include/asm/seccomp_32.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _ASM_X86_SECCOMP_32_H -#define _ASM_X86_SECCOMP_32_H - -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_sigreturn - -#endif /* _ASM_X86_SECCOMP_32_H */ diff --git a/arch/x86/include/asm/seccomp_64.h b/arch/x86/include/asm/seccomp_64.h deleted file mode 100644 index 84ec1bd..0000000 --- a/arch/x86/include/asm/seccomp_64.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_X86_SECCOMP_64_H -#define _ASM_X86_SECCOMP_64_H - -#include -#include - -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - -#define __NR_seccomp_read_32 __NR_ia32_read -#define __NR_seccomp_write_32 __NR_ia32_write -#define __NR_seccomp_exit_32 __NR_ia32_exit -#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn - -#endif /* _ASM_X86_SECCOMP_64_H */ -- cgit v0.10.2 From 9e522c0d28d1418c2983ffbc3903f7bed3354180 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 16 Apr 2015 12:49:07 -0700 Subject: lib/Kconfig: fix up HAVE_ARCH_BITREVERSE help text Cc: Yalin Wang Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/Kconfig b/lib/Kconfig index 87da53b..f544022 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -18,9 +18,8 @@ config HAVE_ARCH_BITREVERSE default n depends on BITREVERSE help - This option provides an config for the architecture which have instruction - can do bitreverse operation, we use the hardware instruction if the architecture - have this capability. + This option enables the use of hardware bit-reversal instructions on + architectures which support such operations. config RATIONAL bool -- cgit v0.10.2 From 15beb694c66146e1133b9ff81d54e3ef3daa1d7c Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Thu, 16 Apr 2015 12:49:09 -0700 Subject: mips: ip32: add platform data hooks to use DS1685 driver This modifies the IP32 (SGI O2) platform and reset code to utilize the new rtc-ds1685 driver. The old mc146818rtc.h header is removed and ip32_defconfig is updated as well. Signed-off-by: Joshua Kinard Acked-by: Ralf Baechle Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 70ffe9b..fe48220 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -105,7 +105,8 @@ CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set # CONFIG_RTC_INTF_SYSFS is not set # CONFIG_RTC_INTF_PROC is not set -CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_DS1685_FAMILY=y +CONFIG_RTC_DRV_DS1685=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y diff --git a/arch/mips/include/asm/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h deleted file mode 100644 index 6b6bab4..0000000 --- a/arch/mips/include/asm/mach-ip32/mc146818rtc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1998, 2001, 03 by Ralf Baechle - * Copyright (C) 2000 Harald Koerfgen - * - * RTC routines for IP32 style attached Dallas chip. - */ -#ifndef __ASM_MACH_IP32_MC146818RTC_H -#define __ASM_MACH_IP32_MC146818RTC_H - -#include - -#define RTC_PORT(x) (0x70 + (x)) - -static unsigned char CMOS_READ(unsigned long addr) -{ - return mace->isa.rtc[addr << 8]; -} - -static inline void CMOS_WRITE(unsigned char data, unsigned long addr) -{ - mace->isa.rtc[addr << 8] = data; -} - -/* - * FIXME: Do it right. For now just assume that no one lives in 20th century - * and no O2 user in 22th century ;-) - */ -#define mc146818_decode_year(year) ((year) + 2000) - -#define RTC_ALWAYS_BCD 0 - -#endif /* __ASM_MACH_IP32_MC146818RTC_H */ diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c index 511e9ff..b522477 100644 --- a/arch/mips/sgi-ip32/ip32-platform.c +++ b/arch/mips/sgi-ip32/ip32-platform.c @@ -9,10 +9,13 @@ #include #include #include +#include #include #include +extern void ip32_prepare_poweroff(void); + #define MACEISA_SERIAL1_OFFS offsetof(struct sgi_mace, isa.serial1) #define MACEISA_SERIAL2_OFFS offsetof(struct sgi_mace, isa.serial2) @@ -90,18 +93,47 @@ static __init int sgio2btns_devinit(void) device_initcall(sgio2btns_devinit); -static struct resource sgio2_cmos_rsrc[] = { +#define MACE_RTC_RES_START (MACE_BASE + offsetof(struct sgi_mace, isa.rtc)) +#define MACE_RTC_RES_END (MACE_RTC_RES_START + 32767) + +static struct resource ip32_rtc_resources[] = { { - .start = 0x70, - .end = 0x71, - .flags = IORESOURCE_IO + .start = MACEISA_RTC_IRQ, + .end = MACEISA_RTC_IRQ, + .flags = IORESOURCE_IRQ + }, { + .start = MACE_RTC_RES_START, + .end = MACE_RTC_RES_END, + .flags = IORESOURCE_MEM, } }; -static __init int sgio2_cmos_devinit(void) +/* RTC registers on IP32 are each padded by 256 bytes (0x100). */ +static struct ds1685_rtc_platform_data +ip32_rtc_platform_data[] = { + { + .regstep = 0x100, + .bcd_mode = true, + .no_irq = false, + .uie_unsupported = false, + .alloc_io_resources = true, + .plat_prepare_poweroff = ip32_prepare_poweroff, + }, +}; + +struct platform_device ip32_rtc_device = { + .name = "rtc-ds1685", + .id = -1, + .dev = { + .platform_data = ip32_rtc_platform_data, + }, + .num_resources = ARRAY_SIZE(ip32_rtc_resources), + .resource = ip32_rtc_resources, +}; + ++static int __init sgio2_rtc_devinit(void) { - return IS_ERR(platform_device_register_simple("rtc_cmos", -1, - sgio2_cmos_rsrc, 1)); + return platform_device_register(&ip32_rtc_device); } device_initcall(sgio2_cmos_devinit); diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 44b3470..8bd415c 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -11,10 +11,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -33,53 +34,40 @@ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) -static struct timer_list power_timer, blink_timer, debounce_timer; -static int has_panicked, shuting_down; +extern struct platform_device ip32_rtc_device; -static void ip32_machine_restart(char *command) __noreturn; -static void ip32_machine_halt(void) __noreturn; -static void ip32_machine_power_off(void) __noreturn; +static struct timer_list power_timer, blink_timer; +static int has_panicked, shutting_down; -static void ip32_machine_restart(char *cmd) +static __noreturn void ip32_poweroff(void *data) { - crime->control = CRIME_CONTROL_HARD_RESET; - while (1); -} + void (*poweroff_func)(struct platform_device *) = + symbol_get(ds1685_rtc_poweroff); + +#ifdef CONFIG_MODULES + /* If the first __symbol_get failed, our module wasn't loaded. */ + if (!poweroff_func) { + request_module("rtc-ds1685"); + poweroff_func = symbol_get(ds1685_rtc_poweroff); + } +#endif -static inline void ip32_machine_halt(void) -{ - ip32_machine_power_off(); -} + if (!poweroff_func) + pr_emerg("RTC not available for power-off. Spinning forever ...\n"); + else { + (*poweroff_func)((struct platform_device *)data); + symbol_put(ds1685_rtc_poweroff); + } -static void ip32_machine_power_off(void) -{ - unsigned char reg_a, xctrl_a, xctrl_b; - - disable_irq(MACEISA_RTC_IRQ); - reg_a = CMOS_READ(RTC_REG_A); - - /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */ - reg_a &= ~DS_REGA_DV2; - reg_a |= DS_REGA_DV1; - - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_b = CMOS_READ(DS_B1_XCTRL4B) - | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE; - CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS; - CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A); - wbflush(); - /* adios amigos... */ - CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a, RTC_REG_A); - wbflush(); - while (1); + unreachable(); } -static void power_timeout(unsigned long data) +static void ip32_machine_restart(char *cmd) __noreturn; +static void ip32_machine_restart(char *cmd) { - ip32_machine_power_off(); + msleep(20); + crime->control = CRIME_CONTROL_HARD_RESET; + unreachable(); } static void blink_timeout(unsigned long data) @@ -89,44 +77,27 @@ static void blink_timeout(unsigned long data) mod_timer(&blink_timer, jiffies + data); } -static void debounce(unsigned long data) +static void ip32_machine_halt(void) { - unsigned char reg_a, reg_c, xctrl_a; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - reg_a = CMOS_READ(RTC_REG_A); - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A); - if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) { - /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - /* clear interrupt source */ - CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - return; - } - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - - if (has_panicked) - ip32_machine_restart(NULL); + ip32_poweroff(&ip32_rtc_device); +} - enable_irq(MACEISA_RTC_IRQ); +static void power_timeout(unsigned long data) +{ + ip32_poweroff(&ip32_rtc_device); } -static inline void ip32_power_button(void) +void ip32_prepare_poweroff(void) { if (has_panicked) return; - if (shuting_down || kill_cad_pid(SIGINT, 1)) { + if (shutting_down || kill_cad_pid(SIGINT, 1)) { /* No init process or button pressed twice. */ - ip32_machine_power_off(); + ip32_poweroff(&ip32_rtc_device); } - shuting_down = 1; + shutting_down = 1; blink_timer.data = POWERDOWN_FREQ; blink_timeout(POWERDOWN_FREQ); @@ -136,27 +107,6 @@ static inline void ip32_power_button(void) add_timer(&power_timer); } -static irqreturn_t ip32_rtc_int(int irq, void *dev_id) -{ - unsigned char reg_c; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - if (!(reg_c & RTC_IRQF)) { - printk(KERN_WARNING - "%s: RTC IRQ without RTC_IRQF\n", __func__); - } - /* Wait until interrupt goes away */ - disable_irq_nosync(MACEISA_RTC_IRQ); - init_timer(&debounce_timer); - debounce_timer.function = debounce; - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - printk(KERN_DEBUG "Power button pressed\n"); - ip32_power_button(); - return IRQ_HANDLED; -} - static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -190,15 +140,12 @@ static __init int ip32_reboot_setup(void) _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; - pm_power_off = ip32_machine_power_off; + pm_power_off = ip32_machine_halt; init_timer(&blink_timer); blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) - panic("Can't allocate MACEISA RTC IRQ"); - return 0; } -- cgit v0.10.2 From 11163348a23cdbcdca5fb42485418e75f8566a5c Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:49:12 -0700 Subject: oprofile: reduce mmap_sem hold for mm->exe_file sync_buffer() needs the mmap_sem for two distinct operations, both only occurring upon user context switch handling: 1) Dealing with the exe_file. 2) Adding the dcookie data as we need to lookup the vma that backs it. This is done via add_sample() and add_data(). This patch isolates 1), for it will no longer need the mmap_sem for serialization. However, for now, make of the more standard get_mm_exe_file(), requiring only holding the mmap_sem to read the value, and relying on reference counting to make sure that the exe file won't dissappear underneath us while doing the get dcookie. As a consequence, for 2) we move the mmap_sem locking into where we really need it, in lookup_dcookie(). The benefits are twofold: reduce mmap_sem hold times, and cleaner code. [akpm@linux-foundation.org: export get_mm_exe_file for arch/x86/oprofile/oprofile.ko] Signed-off-by: Davidlohr Bueso Cc: Robert Richter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d93b2b6..82f7000 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -21,6 +21,7 @@ * objects. */ +#include #include #include #include @@ -224,10 +225,18 @@ static inline unsigned long fast_get_dcookie(struct path *path) static unsigned long get_exec_dcookie(struct mm_struct *mm) { unsigned long cookie = NO_COOKIE; + struct file *exe_file; - if (mm && mm->exe_file) - cookie = fast_get_dcookie(&mm->exe_file->f_path); + if (!mm) + goto done; + + exe_file = get_mm_exe_file(mm); + if (!exe_file) + goto done; + cookie = fast_get_dcookie(&exe_file->f_path); + fput(exe_file); +done: return cookie; } @@ -236,6 +245,8 @@ static unsigned long get_exec_dcookie(struct mm_struct *mm) * pair that can then be added to the global event buffer. We make * sure to do this lookup before a mm->mmap modification happens so * we don't lose track. + * + * The caller must ensure the mm is not nil (ie: not a kernel thread). */ static unsigned long lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) @@ -243,6 +254,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) unsigned long cookie = NO_COOKIE; struct vm_area_struct *vma; + down_read(&mm->mmap_sem); for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { if (addr < vma->vm_start || addr >= vma->vm_end) @@ -262,6 +274,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) if (!vma) cookie = INVALID_COOKIE; + up_read(&mm->mmap_sem); return cookie; } @@ -402,20 +415,9 @@ static void release_mm(struct mm_struct *mm) { if (!mm) return; - up_read(&mm->mmap_sem); mmput(mm); } - -static struct mm_struct *take_tasks_mm(struct task_struct *task) -{ - struct mm_struct *mm = get_task_mm(task); - if (mm) - down_read(&mm->mmap_sem); - return mm; -} - - static inline int is_code(unsigned long val) { return val == ESCAPE_CODE; @@ -532,7 +534,7 @@ void sync_buffer(int cpu) new = (struct task_struct *)val; oldmm = mm; release_mm(oldmm); - mm = take_tasks_mm(new); + mm = get_task_mm(new); if (mm != oldmm) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); diff --git a/kernel/fork.c b/kernel/fork.c index 0d23e76..03c1eaa 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -752,6 +752,7 @@ struct file *get_mm_exe_file(struct mm_struct *mm) rcu_read_unlock(); return exe_file; } +EXPORT_SYMBOL(get_mm_exe_file); /** * get_task_mm - acquire a reference to the task's mm -- cgit v0.10.2 From fd89a65f155fa890c0130139dfb91684d6da4cfb Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:49:15 -0700 Subject: powerpc/oprofile: reduce mmap_sem hold for exe_file In the future mm->exe_file will be done without mmap_sem serialization, thus isolate and reorganize the related code to make the transition easier. Good users will, make use of the more standard get_mm_exe_file(), requiring only holding the mmap_sem to read the value, and relying on reference counting to make sure that the exe file won't dissappear underneath us while getting the dcookie. Signed-off-by: Davidlohr Bueso Cc: Arnd Bergmann Cc: Robert Richter Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c index 1c27831..ed7b097 100644 --- a/arch/powerpc/oprofile/cell/spu_task_sync.c +++ b/arch/powerpc/oprofile/cell/spu_task_sync.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -322,18 +323,20 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp, unsigned long app_cookie = 0; unsigned int my_offset = 0; struct vm_area_struct *vma; + struct file *exe_file; struct mm_struct *mm = spu->mm; if (!mm) goto out; - down_read(&mm->mmap_sem); - - if (mm->exe_file) { - app_cookie = fast_get_dcookie(&mm->exe_file->f_path); - pr_debug("got dcookie for %pD\n", mm->exe_file); + exe_file = get_mm_exe_file(mm); + if (exe_file) { + app_cookie = fast_get_dcookie(&exe_file->f_path); + pr_debug("got dcookie for %pD\n", exe_file); + fput(exe_file); } + down_read(&mm->mmap_sem); for (vma = mm->mmap; vma; vma = vma->vm_next) { if (vma->vm_start > spu_ref || vma->vm_end <= spu_ref) continue; -- cgit v0.10.2 From d4144ea6e7cc307e84cd9ca227df7b04a54a2365 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:49:18 -0700 Subject: tomoyo: reduce mmap_sem hold for mm->exe_file The mm->exe_file is currently serialized with mmap_sem (shared) in order to both safely (1) read the file and (2) compute the realpath by calling tomoyo_realpath_from_path, making it an absolute overkill. Good users will, on the other hand, make use of the more standard get_mm_exe_file(), requiring only holding the mmap_sem to read the value, and relying on reference [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Davidlohr Bueso Acked-by: Tetsuo Handa Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 2952ba5..b974a69 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -948,15 +948,18 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, */ const char *tomoyo_get_exe(void) { + struct file *exe_file; + const char *cp; struct mm_struct *mm = current->mm; - const char *cp = NULL; if (!mm) return NULL; - down_read(&mm->mmap_sem); - if (mm->exe_file) - cp = tomoyo_realpath_from_path(&mm->exe_file->f_path); - up_read(&mm->mmap_sem); + exe_file = get_mm_exe_file(mm); + if (!exe_file) + return NULL; + + cp = tomoyo_realpath_from_path(&exe_file->f_path); + fput(exe_file); return cp; } -- cgit v0.10.2 From 17b199d62d7fd732ba02c13433e438ebb368aac9 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Thu, 16 Apr 2015 12:49:21 -0700 Subject: MAINTAINERS: add Mediatek SoC mailing list Add the new list that Mediatek specific patches should also be directed to. Signed-off-by: Matthias Brugger Cc: Olof Johansson Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 8b0a0c9..d24e8a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1215,6 +1215,7 @@ F: arch/arm/mach-orion5x/ts78xx-* ARM/Mediatek SoC support M: Matthias Brugger L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/mt6* F: arch/arm/boot/dts/mt8* -- cgit v0.10.2 From f4ae9497288336e9a1900e8e351edf71e27b6944 Mon Sep 17 00:00:00 2001 From: Andrey Skvortsov Date: Thu, 16 Apr 2015 12:49:24 -0700 Subject: .gitignore: ignore *.tar Running make tar-pkg results in following: # Untracked files: # (use "git add ..." to include in what will be committed) # # linux-4.0.0-rc3-next-20150313-150225--x86.tar This patch makes git ignore *.tar files. Running 'git ls-files -i --exclude-standard' does not show any tar files excluded from tracking after the change. Signed-off-by: Andrey Skvortsov Cc: Michal Marek Cc: Greg Kroah-Hartman Cc: Boaz Harrosh Cc: Andi Kleen Cc: Benjamin Romer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/.gitignore b/.gitignore index acb6afe..4ad4a98 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.order *.elf *.bin +*.tar *.gz *.bz2 *.lzma -- cgit v0.10.2 From 94f919225890a1adb3d44bf5b31ff4cb21d8ee7e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:49:27 -0700 Subject: drivers/rtc/rtc-s5m.c: allow usage on device type different than main MFD type The RTC driver supports two flavors of S5M devices: S5M8767-like and S2MPS14-like. On S2MPS13 and S2MPS14 devices the RTC module is the same so we want to re-use the existing support of S2MPS14. However device type was passed from parent MFD driver in platform data structure. This way for the S2MPS13 device the main MFD driver passed device type of 'S2MPS13X'. Instead decouple detecting of device type between main MFD and RTC driver. This allows adding support for other S2MPS14 variations (like S2MPS11 and S2MPS13) easily by adding to mfd/sec-core.c: static const struct mfd_cell s2mps13_devs[] = { { .name = "s2mps14-rtc", } }; Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Kyungmin Park Cc: Marek Szyprowski Cc: Chanwoo Choi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 64baad3..8c70d78 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -92,7 +92,7 @@ struct s5m_rtc_info { struct regmap *regmap; struct rtc_device *rtc_dev; int irq; - int device_type; + enum sec_device_type device_type; int rtc_24hr_mode; const struct s5m_rtc_reg_config *regs; }; @@ -668,7 +668,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) if (!info) return -ENOMEM; - switch (pdata->device_type) { + switch (platform_get_device_id(pdev)->driver_data) { case S2MPS14X: case S2MPS13X: regmap_cfg = &s2mps14_rtc_regmap_config; @@ -686,7 +686,9 @@ static int s5m_rtc_probe(struct platform_device *pdev) alarm_irq = S5M8767_IRQ_RTCA1; break; default: - dev_err(&pdev->dev, "Device type is not supported by RTC driver\n"); + dev_err(&pdev->dev, + "Device type %lu is not supported by RTC driver\n", + platform_get_device_id(pdev)->driver_data); return -ENODEV; } @@ -706,7 +708,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->s5m87xx = s5m87xx; - info->device_type = s5m87xx->device_type; + info->device_type = platform_get_device_id(pdev)->driver_data; if (s5m87xx->irq_data) { info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); -- cgit v0.10.2 From 07eec628ffcea711e14644e14d2c83b4150ba1b7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 16 Apr 2015 12:49:29 -0700 Subject: Documentation/spi/spidev_test.c: fix warning Documentation/spi/spidev_test.c:83:5: warning: no previous prototype for 'unespcape' [-Wmissing-prototypes] fix spelling too. Acked-by: Mark Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c index 94f574b..135b3f5 100644 --- a/Documentation/spi/spidev_test.c +++ b/Documentation/spi/spidev_test.c @@ -80,7 +80,7 @@ static void hex_dump(const void *src, size_t length, size_t line_size, char *pre * Unescape - process hexadecimal escape character * converts shell input "\x23" -> 0x23 */ -int unespcape(char *_dst, char *_src, size_t len) +static int unescape(char *_dst, char *_src, size_t len) { int ret = 0; char *src = _src; @@ -304,7 +304,7 @@ int main(int argc, char *argv[]) size = strlen(input_tx+1); tx = malloc(size); rx = malloc(size); - size = unespcape((char *)tx, input_tx, size); + size = unescape((char *)tx, input_tx, size); transfer(fd, tx, rx, size); free(rx); free(tx); -- cgit v0.10.2 From 6da7bb1e9cef9ab956e4223125090e4465f51fb2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 16 Apr 2015 12:49:32 -0700 Subject: drivers/rtc/rtc-at91rm9200.c: make IO endian agnostic Change the __raw IO calls to readl/write_relaxed which makes the driver endian agnostic to run properly on big endian systems. Signed-off-by: Ben Dooks Cc: Alessandro Zummo Cc: Andrew Victor Acked-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index b283a1a..35efd3f 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -37,9 +37,9 @@ #include "rtc-at91rm9200.h" #define at91_rtc_read(field) \ - __raw_readl(at91_rtc_regs + field) + readl_relaxed(at91_rtc_regs + field) #define at91_rtc_write(field, val) \ - __raw_writel((val), at91_rtc_regs + field) + writel_relaxed((val), at91_rtc_regs + field) #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ -- cgit v0.10.2 From 15eb42d674de8da66950f78b5c7202accabe026e Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 16 Apr 2015 12:49:35 -0700 Subject: docs: add missing and new /proc/PID/status file entries, fix typos docs: add missing and new /proc/PID/status file entries, fix typos Signed-off-by: Nathan Scott Signed-off-by: Chen Hanxiao Cc: Serge Hallyn Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a07ba61..6d37062 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -200,12 +200,12 @@ contains details information about the process itself. Its fields are explained in Table 1-4. (for SMP CONFIG users) -For making accounting scalable, RSS related information are handled in -asynchronous manner and the vaule may not be very precise. To see a precise +For making accounting scalable, RSS related information are handled in an +asynchronous manner and the value may not be very precise. To see a precise snapshot of a moment, you can see /proc//smaps file and scan page table. It's slow but very precise. -Table 1-2: Contents of the status files (as of 2.6.30-rc7) +Table 1-2: Contents of the status files (as of 3.20.0) .............................................................................. Field Content Name filename of the executable @@ -213,6 +213,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7) in an uninterruptible wait, Z is zombie, T is traced or stopped) Tgid thread group ID + Ngid NUMA group ID (0 if none) Pid process id PPid process id of the parent process TracerPid PID of process tracing this process (0 if not) @@ -220,6 +221,10 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7) Gid Real, effective, saved set, and file system GIDs FDSize number of file descriptor slots currently allocated Groups supplementary group list + NStgid descendant namespace thread group ID hierarchy + NSpid descendant namespace process ID hierarchy + NSpgid descendant namespace process group ID hierarchy + NSsid descendant namespace session ID hierarchy VmPeak peak virtual memory size VmSize total program size VmLck locked memory size -- cgit v0.10.2 From 6c8c90319c0bb1c9e0b68e721359b89ae4f28465 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Thu, 16 Apr 2015 12:49:38 -0700 Subject: proc: show locks in /proc/pid/fdinfo/X Let's show locks which are associated with a file descriptor in its fdinfo file. Currently we don't have a reliable way to determine who holds a lock. We can find some information in /proc/locks, but PID which is reported there can be wrong. For example, a process takes a lock, then forks a child and dies. In this case /proc/locks contains the parent pid, which can be reused by another process. $ cat /proc/locks ... 6: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF ... $ ps -C rpcbind PID TTY TIME CMD 332 ? 00:00:00 rpcbind $ cat /proc/332/fdinfo/4 pos: 0 flags: 0100000 mnt_id: 22 lock: 1: FLOCK ADVISORY WRITE 324 00:13:13431 0 EOF $ ls -l /proc/332/fd/4 lr-x------ 1 root root 64 Mar 5 14:43 /proc/332/fd/4 -> /run/rpcbind.lock $ ls -l /proc/324/fd/ total 0 lrwx------ 1 root root 64 Feb 27 14:50 0 -> /dev/pts/0 lrwx------ 1 root root 64 Feb 27 14:50 1 -> /dev/pts/0 lrwx------ 1 root root 64 Feb 27 14:49 2 -> /dev/pts/0 You can see that the process with the 324 pid doesn't hold the lock. This information is required for proper dumping and restoring file locks. Signed-off-by: Andrey Vagin Cc: Jonathan Corbet Cc: Alexander Viro Acked-by: Jeff Layton Acked-by: "J. Bruce Fields" Acked-by: Cyrill Gorcunov Cc: Pavel Emelyanov Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 6d37062..8e36c7e 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1709,6 +1709,10 @@ A typical output is flags: 0100002 mnt_id: 19 +All locks associated with a file descriptor are shown in its fdinfo too. + +lock: 1: FLOCK ADVISORY WRITE 359 00:13:11691 0 EOF + The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags pair provide additional information particular to the objects they represent. diff --git a/fs/locks.c b/fs/locks.c index 52b780f..653faab 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2590,6 +2590,44 @@ static int locks_show(struct seq_file *f, void *v) return 0; } +static void __show_fd_locks(struct seq_file *f, + struct list_head *head, int *id, + struct file *filp, struct files_struct *files) +{ + struct file_lock *fl; + + list_for_each_entry(fl, head, fl_list) { + + if (filp != fl->fl_file) + continue; + if (fl->fl_owner != files && + fl->fl_owner != filp) + continue; + + (*id)++; + seq_puts(f, "lock:\t"); + lock_get_status(f, fl, *id, ""); + } +} + +void show_fd_locks(struct seq_file *f, + struct file *filp, struct files_struct *files) +{ + struct inode *inode = file_inode(filp); + struct file_lock_context *ctx; + int id = 0; + + ctx = inode->i_flctx; + if (!ctx) + return; + + spin_lock(&ctx->flc_lock); + __show_fd_locks(f, &ctx->flc_flock, &id, filp, files); + __show_fd_locks(f, &ctx->flc_posix, &id, filp, files); + __show_fd_locks(f, &ctx->flc_lease, &id, filp, files); + spin_unlock(&ctx->flc_lock); +} + static void *locks_start(struct seq_file *f, loff_t *pos) __acquires(&blocked_lock_lock) { diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 8e5ad83..af84ad0 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -48,17 +49,23 @@ static int seq_show(struct seq_file *m, void *v) put_files_struct(files); } - if (!ret) { - seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n", - (long long)file->f_pos, f_flags, - real_mount(file->f_path.mnt)->mnt_id); - if (file->f_op->show_fdinfo) - file->f_op->show_fdinfo(m, file); - ret = seq_has_overflowed(m); - fput(file); - } + if (ret) + return ret; - return ret; + seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n", + (long long)file->f_pos, f_flags, + real_mount(file->f_path.mnt)->mnt_id); + + show_fd_locks(m, file, files); + if (seq_has_overflowed(m)) + goto out; + + if (file->f_op->show_fdinfo) + file->f_op->show_fdinfo(m, file); + +out: + fput(file); + return 0; } static int seq_fdinfo_open(struct inode *inode, struct file *file) diff --git a/include/linux/fs.h b/include/linux/fs.h index 6bf7ab7..c4e9273 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1042,6 +1042,9 @@ extern void lease_get_mtime(struct inode *, struct timespec *time); extern int generic_setlease(struct file *, long, struct file_lock **, void **priv); extern int vfs_setlease(struct file *, long, struct file_lock **, void **); extern int lease_modify(struct file_lock *, int, struct list_head *); +struct files_struct; +extern void show_fd_locks(struct seq_file *f, + struct file *filp, struct files_struct *files); #else /* !CONFIG_FILE_LOCKING */ static inline int fcntl_getlk(struct file *file, unsigned int cmd, struct flock __user *user) @@ -1178,6 +1181,10 @@ static inline int lease_modify(struct file_lock *fl, int arg, { return -EINVAL; } + +struct files_struct; +static inline void show_fd_locks(struct seq_file *f, + struct file *filp, struct files_struct *files) {} #endif /* !CONFIG_FILE_LOCKING */ -- cgit v0.10.2