]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Apr 2018 08:10:24 +0000 (10:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Apr 2018 08:10:24 +0000 (10:10 +0200)
added patches:
bitmap-fix-memset-optimization-on-big-endian-systems.patch

queue-4.14/bitmap-fix-memset-optimization-on-big-endian-systems.patch [new file with mode: 0644]
queue-4.14/series
queue-4.16/series [new file with mode: 0644]

diff --git a/queue-4.14/bitmap-fix-memset-optimization-on-big-endian-systems.patch b/queue-4.14/bitmap-fix-memset-optimization-on-big-endian-systems.patch
new file mode 100644 (file)
index 0000000..ee4d5a9
--- /dev/null
@@ -0,0 +1,89 @@
+From 21035965f60b0502fc6537b232839389bb4ce664 Mon Sep 17 00:00:00 2001
+From: Omar Sandoval <osandov@fb.com>
+Date: Mon, 2 Apr 2018 15:58:31 -0700
+Subject: bitmap: fix memset optimization on big-endian systems
+
+From: Omar Sandoval <osandov@fb.com>
+
+commit 21035965f60b0502fc6537b232839389bb4ce664 upstream.
+
+Commit 2a98dc028f91 ("include/linux/bitmap.h: turn bitmap_set and
+bitmap_clear into memset when possible") introduced an optimization to
+bitmap_{set,clear}() which uses memset() when the start and length are
+constants aligned to a byte.
+
+This is wrong on big-endian systems; our bitmaps are arrays of unsigned
+long, so bit n is not at byte n / 8 in memory.  This was caught by the
+Btrfs selftests, but the bitmap selftests also fail when run on a
+big-endian machine.
+
+We can still use memset if the start and length are aligned to an
+unsigned long, so do that on big-endian.  The same problem applies to
+the memcmp in bitmap_equal(), so fix it there, too.
+
+Fixes: 2a98dc028f91 ("include/linux/bitmap.h: turn bitmap_set and bitmap_clear into memset when possible")
+Fixes: 2c6deb01525a ("bitmap: use memcmp optimisation in more situations")
+Cc: stable@kernel.org
+Reported-by: "Erhard F." <erhard_f@mailbox.org>
+Cc: Matthew Wilcox <mawilcox@microsoft.com>
+Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/bitmap.h |   22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -262,12 +262,20 @@ static inline void bitmap_complement(uns
+               __bitmap_complement(dst, src, nbits);
+ }
++#ifdef __LITTLE_ENDIAN
++#define BITMAP_MEM_ALIGNMENT 8
++#else
++#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
++#endif
++#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
++
+ static inline int bitmap_equal(const unsigned long *src1,
+                       const unsigned long *src2, unsigned int nbits)
+ {
+       if (small_const_nbits(nbits))
+               return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
+-      if (__builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
++      if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
++          IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
+               return !memcmp(src1, src2, nbits / 8);
+       return __bitmap_equal(src1, src2, nbits);
+ }
+@@ -318,8 +326,10 @@ static __always_inline void bitmap_set(u
+ {
+       if (__builtin_constant_p(nbits) && nbits == 1)
+               __set_bit(start, map);
+-      else if (__builtin_constant_p(start & 7) && IS_ALIGNED(start, 8) &&
+-               __builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
++      else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
++               IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
++               __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
++               IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
+               memset((char *)map + start / 8, 0xff, nbits / 8);
+       else
+               __bitmap_set(map, start, nbits);
+@@ -330,8 +340,10 @@ static __always_inline void bitmap_clear
+ {
+       if (__builtin_constant_p(nbits) && nbits == 1)
+               __clear_bit(start, map);
+-      else if (__builtin_constant_p(start & 7) && IS_ALIGNED(start, 8) &&
+-               __builtin_constant_p(nbits & 7) && IS_ALIGNED(nbits, 8))
++      else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
++               IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
++               __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
++               IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
+               memset((char *)map + start / 8, 0, nbits / 8);
+       else
+               __bitmap_clear(map, start, nbits);
index 436e3ea9f5c5e91163bd46e806cd8ad03addaeca..2e5f198935a4cb6a9350fb41399ebfc94ebc6e61 100644 (file)
@@ -34,3 +34,4 @@ netfilter-x_tables-add-and-use-xt_check_proc_name.patch
 phy-qcom-ufs-add-module_license-tag.patch
 bluetooth-fix-missing-encryption-refresh-on-security-request.patch
 usb-dwc2-improve-gadget-state-disconnection-handling.patch
+bitmap-fix-memset-optimization-on-big-endian-systems.patch
diff --git a/queue-4.16/series b/queue-4.16/series
new file mode 100644 (file)
index 0000000..ba9fdb3
--- /dev/null
@@ -0,0 +1 @@
+bitmap-fix-memset-optimization-on-big-endian-systems.patch