]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 May 2018 09:39:09 +0000 (11:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 May 2018 09:39:09 +0000 (11:39 +0200)
added patches:
futex-remove-duplicated-code-and-fix-undefined-behaviour.patch
mm-vmstat-print-non-populated-zones-in-zoneinfo.patch
serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch

queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch [new file with mode: 0644]
queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch [new file with mode: 0644]
queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch b/queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch
new file mode 100644 (file)
index 0000000..0ecb8a0
--- /dev/null
@@ -0,0 +1,1090 @@
+From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Thu, 24 Aug 2017 09:31:05 +0200
+Subject: futex: Remove duplicated code and fix undefined behaviour
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.
+
+There is code duplicated over all architecture's headers for
+futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,
+and comparison of the result.
+
+Remove this duplication and leave up to the arches only the needed
+assembly which is now in arch_futex_atomic_op_inuser.
+
+This effectively distributes the Will Deacon's arm64 fix for undefined
+behaviour reported by UBSAN to all architectures. The fix was done in
+commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with
+FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.
+
+And as suggested by Thomas, check for negative oparg too, because it was
+also reported to cause undefined behaviour report.
+
+Note that s390 removed access_ok check in d12a29703 ("s390/uaccess:
+remove pointless access_ok() checks") as access_ok there returns true.
+We introduce it back to the helper for the sake of simplicity (it gets
+optimized away anyway).
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
+Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]
+Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]
+Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org>
+Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64]
+Cc: linux-mips@linux-mips.org
+Cc: Rich Felker <dalias@libc.org>
+Cc: linux-ia64@vger.kernel.org
+Cc: linux-sh@vger.kernel.org
+Cc: peterz@infradead.org
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Max Filippov <jcmvbkbc@gmail.com>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: sparclinux@vger.kernel.org
+Cc: Jonas Bonn <jonas@southpole.se>
+Cc: linux-s390@vger.kernel.org
+Cc: linux-arch@vger.kernel.org
+Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
+Cc: linux-hexagon@vger.kernel.org
+Cc: Helge Deller <deller@gmx.de>
+Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Matt Turner <mattst88@gmail.com>
+Cc: linux-snps-arc@lists.infradead.org
+Cc: Fenghua Yu <fenghua.yu@intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: linux-xtensa@linux-xtensa.org
+Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+Cc: openrisc@lists.librecores.org
+Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+Cc: Stafford Horne <shorne@gmail.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: Richard Henderson <rth@twiddle.net>
+Cc: Chris Zankel <chris@zankel.net>
+Cc: Michal Simek <monstr@monstr.eu>
+Cc: Tony Luck <tony.luck@intel.com>
+Cc: linux-parisc@vger.kernel.org
+Cc: Vineet Gupta <vgupta@synopsys.com>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: Richard Kuo <rkuo@codeaurora.org>
+Cc: linux-alpha@vger.kernel.org
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Cc: linuxppc-dev@lists.ozlabs.org
+Cc: "David S. Miller" <davem@davemloft.net>
+Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby@suse.cz
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/alpha/include/asm/futex.h      |   26 +++---------------
+ arch/arc/include/asm/futex.h        |   40 +++-------------------------
+ arch/arm/include/asm/futex.h        |   26 ++----------------
+ arch/arm64/include/asm/futex.h      |   27 ++-----------------
+ arch/frv/include/asm/futex.h        |    3 +-
+ arch/frv/kernel/futex.c             |   27 ++-----------------
+ arch/hexagon/include/asm/futex.h    |   38 ++-------------------------
+ arch/ia64/include/asm/futex.h       |   25 ++----------------
+ arch/microblaze/include/asm/futex.h |   38 ++-------------------------
+ arch/mips/include/asm/futex.h       |   25 ++----------------
+ arch/parisc/include/asm/futex.h     |   26 ++----------------
+ arch/powerpc/include/asm/futex.h    |   26 +++---------------
+ arch/s390/include/asm/futex.h       |   23 +++-------------
+ arch/sh/include/asm/futex.h         |   26 ++----------------
+ arch/sparc/include/asm/futex_64.h   |   26 +++---------------
+ arch/tile/include/asm/futex.h       |   40 +++-------------------------
+ arch/x86/include/asm/futex.h        |   40 +++-------------------------
+ arch/xtensa/include/asm/futex.h     |   27 +++----------------
+ include/asm-generic/futex.h         |   50 ++++++------------------------------
+ kernel/futex.c                      |   39 ++++++++++++++++++++++++++++
+ 20 files changed, 126 insertions(+), 472 deletions(-)
+
+--- a/arch/alpha/include/asm/futex.h
++++ b/arch/alpha/include/asm/futex.h
+@@ -29,18 +29,10 @@
+       :       "r" (uaddr), "r"(oparg)                         \
+       :       "memory")
+-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/arc/include/asm/futex.h
++++ b/arch/arc/include/asm/futex.h
+@@ -73,20 +73,11 @@
+ #endif
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+-              return -EFAULT;
+-
+ #ifndef CONFIG_ARC_HAS_LLSC
+       preempt_disable();      /* to guarantee atomic r-m-w of futex op */
+ #endif
+@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser
+       preempt_enable();
+ #endif
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ:
+-                      ret = (oldval == cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_NE:
+-                      ret = (oldval != cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LT:
+-                      ret = (oldval < cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GE:
+-                      ret = (oldval >= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LE:
+-                      ret = (oldval <= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GT:
+-                      ret = (oldval > cmparg);
+-                      break;
+-              default:
+-                      ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/arm/include/asm/futex.h
++++ b/arch/arm/include/asm/futex.h
+@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
+ #endif /* !SMP */
+ static inline int
+-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tmp;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+-
+ #ifndef CONFIG_SMP
+       preempt_disable();
+ #endif
+@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,
+       preempt_enable();
+ #endif
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/arm64/include/asm/futex.h
++++ b/arch/arm64/include/asm/futex.h
+@@ -51,20 +51,9 @@
+       : "memory")
+ static inline int
+-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *_uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (int)(encoded_op << 8) >> 20;
+-      int cmparg = (int)(encoded_op << 20) >> 20;
+       int oldval = 0, ret, tmp;
+-      u32 __user *uaddr = __uaccess_mask_ptr(_uaddr);
+-
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1U << (oparg & 0x1f);
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -95,17 +84,9 @@ futex_atomic_op_inuser(unsigned int enco
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/frv/include/asm/futex.h
++++ b/arch/frv/include/asm/futex.h
+@@ -7,7 +7,8 @@
+ #include <asm/errno.h>
+ #include <asm/uaccess.h>
+-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
++extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr);
+ static inline int
+ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+--- a/arch/frv/kernel/futex.c
++++ b/arch/frv/kernel/futex.c
+@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x
+ /*
+  * do the futex operations
+  */
+-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+-
+       pagefault_disable();
+       switch (op) {
+@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS; break;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
+       return ret;
+-} /* end futex_atomic_op_inuser() */
++} /* end arch_futex_atomic_op_inuser() */
+--- a/arch/hexagon/include/asm/futex.h
++++ b/arch/hexagon/include/asm/futex.h
+@@ -31,18 +31,9 @@
+ static inline int
+-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ:
+-                      ret = (oldval == cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_NE:
+-                      ret = (oldval != cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LT:
+-                      ret = (oldval < cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GE:
+-                      ret = (oldval >= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LE:
+-                      ret = (oldval <= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GT:
+-                      ret = (oldval > cmparg);
+-                      break;
+-              default:
+-                      ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/ia64/include/asm/futex.h
++++ b/arch/ia64/include/asm/futex.h
+@@ -45,18 +45,9 @@ do {                                                                        \
+ } while (0)
+ static inline int
+-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/microblaze/include/asm/futex.h
++++ b/arch/microblaze/include/asm/futex.h
+@@ -29,18 +29,9 @@
+ })
+ static inline int
+-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ:
+-                      ret = (oldval == cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_NE:
+-                      ret = (oldval != cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LT:
+-                      ret = (oldval < cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GE:
+-                      ret = (oldval >= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LE:
+-                      ret = (oldval <= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GT:
+-                      ret = (oldval > cmparg);
+-                      break;
+-              default:
+-                      ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/mips/include/asm/futex.h
++++ b/arch/mips/include/asm/futex.h
+@@ -83,18 +83,9 @@
+ }
+ static inline int
+-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/parisc/include/asm/futex.h
++++ b/arch/parisc/include/asm/futex.h
+@@ -32,22 +32,12 @@ _futex_spin_unlock_irqrestore(u32 __user
+ }
+ static inline int
+-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+ {
+       unsigned long int flags;
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval, ret;
+       u32 tmp;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
+-              return -EFAULT;
+-
+       _futex_spin_lock_irqsave(uaddr, &flags);
+       pagefault_disable();
+@@ -85,17 +75,9 @@ out_pagefault_enable:
+       pagefault_enable();
+       _futex_spin_unlock_irqrestore(uaddr, &flags);
+-      if (ret == 0) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/powerpc/include/asm/futex.h
++++ b/arch/powerpc/include/asm/futex.h
+@@ -31,18 +31,10 @@
+       : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
+       : "cr0", "memory")
+-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/s390/include/asm/futex.h
++++ b/arch/s390/include/asm/futex.h
+@@ -21,17 +21,12 @@
+               : "0" (-EFAULT), "d" (oparg), "a" (uaddr),              \
+                 "m" (*uaddr) : "cc");
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, newval, ret;
+       load_kernel_asce();
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+       pagefault_disable();
+       switch (op) {
+@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser
+       }
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/sh/include/asm/futex.h
++++ b/arch/sh/include/asm/futex.h
+@@ -27,21 +27,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
+       return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
+ }
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      u32 oparg = (encoded_op << 8) >> 20;
+-      u32 cmparg = (encoded_op << 20) >> 20;
+       u32 oldval, newval, prev;
+       int ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+-
+       pagefault_disable();
+       do {
+@@ -80,17 +71,8 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
+       return ret;
+ }
+--- a/arch/sparc/include/asm/futex_64.h
++++ b/arch/sparc/include/asm/futex_64.h
+@@ -29,22 +29,14 @@
+       : "r" (uaddr), "r" (oparg), "i" (-EFAULT)       \
+       : "memory")
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+-      if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
+-              return -EFAULT;
+       if (unlikely((((unsigned long) uaddr) & 0x3UL)))
+               return -EINVAL;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+       pagefault_disable();
+       switch (op) {
+@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/tile/include/asm/futex.h
++++ b/arch/tile/include/asm/futex.h
+@@ -106,12 +106,9 @@
+       lock = __atomic_hashed_lock((int __force *)uaddr)
+ #endif
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int uninitialized_var(val), ret;
+       __futex_prolog();
+@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser
+       /* The 32-bit futex code makes this assumption, so validate it here. */
+       BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+-
+       pagefault_disable();
+       switch (op) {
+       case FUTEX_OP_SET:
+@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser
+       }
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ:
+-                      ret = (val == cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_NE:
+-                      ret = (val != cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LT:
+-                      ret = (val < cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GE:
+-                      ret = (val >= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LE:
+-                      ret = (val <= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GT:
+-                      ret = (val > cmparg);
+-                      break;
+-              default:
+-                      ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = val;
++
+       return ret;
+ }
+--- a/arch/x86/include/asm/futex.h
++++ b/arch/x86/include/asm/futex.h
+@@ -41,20 +41,11 @@
+                      "+m" (*uaddr), "=&r" (tem)               \
+                    : "r" (oparg), "i" (-EFAULT), "1" (0))
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret, tem;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+-
+       pagefault_disable();
+       switch (op) {
+@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ:
+-                      ret = (oldval == cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_NE:
+-                      ret = (oldval != cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LT:
+-                      ret = (oldval < cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GE:
+-                      ret = (oldval >= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_LE:
+-                      ret = (oldval <= cmparg);
+-                      break;
+-              case FUTEX_OP_CMP_GT:
+-                      ret = (oldval > cmparg);
+-                      break;
+-              default:
+-                      ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/arch/xtensa/include/asm/futex.h
++++ b/arch/xtensa/include/asm/futex.h
+@@ -44,18 +44,10 @@
+       : "r" (uaddr), "I" (-EFAULT), "r" (oparg)       \
+       : "memory")
+-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
++              u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+ #if !XCHAL_HAVE_S32C1I
+       return -ENOSYS;
+@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser
+       pagefault_enable();
+-      if (ret)
+-              return ret;
+-
+-      switch (cmp) {
+-      case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
+-      case FUTEX_OP_CMP_NE: return (oldval != cmparg);
+-      case FUTEX_OP_CMP_LT: return (oldval < cmparg);
+-      case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
+-      case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
+-      case FUTEX_OP_CMP_GT: return (oldval > cmparg);
+-      }
++      if (!ret)
++              *oval = oldval;
+-      return -ENOSYS;
++      return ret;
+ }
+ static inline int
+--- a/include/asm-generic/futex.h
++++ b/include/asm-generic/futex.h
+@@ -13,7 +13,7 @@
+  */
+ /**
+- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant
++ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
+  *                      argument and comparison of the previous
+  *                      futex value with another constant.
+  *
+@@ -25,18 +25,11 @@
+  * <0 - On error
+  */
+ static inline int
+-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval, ret;
+       u32 tmp;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+       preempt_disable();
+       pagefault_disable();
+@@ -74,17 +67,9 @@ out_pagefault_enable:
+       pagefault_enable();
+       preempt_enable();
+-      if (ret == 0) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (ret == 0)
++              *oval = oldval;
++
+       return ret;
+ }
+@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
+ #else
+ static inline int
+-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
+ {
+-      int op = (encoded_op >> 28) & 7;
+-      int cmp = (encoded_op >> 24) & 15;
+-      int oparg = (encoded_op << 8) >> 20;
+-      int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+-      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-              oparg = 1 << oparg;
+-
+-      if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
+-              return -EFAULT;
+       pagefault_disable();
+@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,
+       pagefault_enable();
+-      if (!ret) {
+-              switch (cmp) {
+-              case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-              case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-              case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-              case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-              case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-              case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-              default: ret = -ENOSYS;
+-              }
+-      }
++      if (!ret)
++              *oval = oldval;
++
+       return ret;
+ }
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1458,6 +1458,45 @@ out:
+       return ret;
+ }
++static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
++{
++      unsigned int op =         (encoded_op & 0x70000000) >> 28;
++      unsigned int cmp =        (encoded_op & 0x0f000000) >> 24;
++      int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);
++      int cmparg = sign_extend32(encoded_op & 0x00000fff, 12);
++      int oldval, ret;
++
++      if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
++              if (oparg < 0 || oparg > 31)
++                      return -EINVAL;
++              oparg = 1 << oparg;
++      }
++
++      if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
++              return -EFAULT;
++
++      ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
++      if (ret)
++              return ret;
++
++      switch (cmp) {
++      case FUTEX_OP_CMP_EQ:
++              return oldval == cmparg;
++      case FUTEX_OP_CMP_NE:
++              return oldval != cmparg;
++      case FUTEX_OP_CMP_LT:
++              return oldval < cmparg;
++      case FUTEX_OP_CMP_GE:
++              return oldval >= cmparg;
++      case FUTEX_OP_CMP_LE:
++              return oldval <= cmparg;
++      case FUTEX_OP_CMP_GT:
++              return oldval > cmparg;
++      default:
++              return -ENOSYS;
++      }
++}
++
+ /*
+  * Wake up all waiters hashed on the physical page that is mapped
+  * to this virtual address:
diff --git a/queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch b/queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch
new file mode 100644 (file)
index 0000000..9b1effc
--- /dev/null
@@ -0,0 +1,143 @@
+From b2bd8598195f1b2a72130592125ac6b4218988a2 Mon Sep 17 00:00:00 2001
+From: David Rientjes <rientjes@google.com>
+Date: Wed, 3 May 2017 14:52:59 -0700
+Subject: mm, vmstat: print non-populated zones in zoneinfo
+
+From: David Rientjes <rientjes@google.com>
+
+commit b2bd8598195f1b2a72130592125ac6b4218988a2 upstream.
+
+Initscripts can use the information (protection levels) from
+/proc/zoneinfo to configure vm.lowmem_reserve_ratio at boot.
+
+vm.lowmem_reserve_ratio is an array of ratios for each configured zone
+on the system.  If a zone is not populated on an arch, /proc/zoneinfo
+suppresses its output.
+
+This results in there not being a 1:1 mapping between the set of zones
+emitted by /proc/zoneinfo and the zones configured by
+vm.lowmem_reserve_ratio.
+
+This patch shows statistics for non-populated zones in /proc/zoneinfo.
+The zones exist and hold a spot in the vm.lowmem_reserve_ratio array.
+Without this patch, it is not possible to determine which index in the
+array controls which zone if one or more zones on the system are not
+populated.
+
+Remaining users of walk_zones_in_node() are unchanged.  Files such as
+/proc/pagetypeinfo require certain zone data to be initialized properly
+for display, which is not done for unpopulated zones.
+
+Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1703031451310.98023@chino.kir.corp.google.com
+Signed-off-by: David Rientjes <rientjes@google.com>
+Reviewed-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Michal Hocko <mhocko@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/vmstat.c |   27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+--- a/mm/vmstat.c
++++ b/mm/vmstat.c
+@@ -1120,8 +1120,12 @@ static void frag_stop(struct seq_file *m
+ {
+ }
+-/* Walk all the zones in a node and print using a callback */
++/*
++ * Walk zones in a node and print using a callback.
++ * If @assert_populated is true, only use callback for zones that are populated.
++ */
+ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
++              bool assert_populated,
+               void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
+ {
+       struct zone *zone;
+@@ -1129,7 +1133,7 @@ static void walk_zones_in_node(struct se
+       unsigned long flags;
+       for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
+-              if (!populated_zone(zone))
++              if (assert_populated && !populated_zone(zone))
+                       continue;
+               spin_lock_irqsave(&zone->lock, flags);
+@@ -1157,7 +1161,7 @@ static void frag_show_print(struct seq_f
+ static int frag_show(struct seq_file *m, void *arg)
+ {
+       pg_data_t *pgdat = (pg_data_t *)arg;
+-      walk_zones_in_node(m, pgdat, frag_show_print);
++      walk_zones_in_node(m, pgdat, true, frag_show_print);
+       return 0;
+ }
+@@ -1198,7 +1202,7 @@ static int pagetypeinfo_showfree(struct
+               seq_printf(m, "%6d ", order);
+       seq_putc(m, '\n');
+-      walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print);
++      walk_zones_in_node(m, pgdat, true, pagetypeinfo_showfree_print);
+       return 0;
+ }
+@@ -1250,7 +1254,7 @@ static int pagetypeinfo_showblockcount(s
+       for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
+               seq_printf(m, "%12s ", migratetype_names[mtype]);
+       seq_putc(m, '\n');
+-      walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print);
++      walk_zones_in_node(m, pgdat, true, pagetypeinfo_showblockcount_print);
+       return 0;
+ }
+@@ -1276,7 +1280,7 @@ static void pagetypeinfo_showmixedcount(
+               seq_printf(m, "%12s ", migratetype_names[mtype]);
+       seq_putc(m, '\n');
+-      walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print);
++      walk_zones_in_node(m, pgdat, true, pagetypeinfo_showmixedcount_print);
+ #endif /* CONFIG_PAGE_OWNER */
+ }
+@@ -1432,12 +1436,15 @@ static void zoneinfo_show_print(struct s
+ }
+ /*
+- * Output information about zones in @pgdat.
++ * Output information about zones in @pgdat.  All zones are printed regardless
++ * of whether they are populated or not: lowmem_reserve_ratio operates on the
++ * set of all zones and userspace would not be aware of such zones if they are
++ * suppressed here (zoneinfo displays the effect of lowmem_reserve_ratio).
+  */
+ static int zoneinfo_show(struct seq_file *m, void *arg)
+ {
+       pg_data_t *pgdat = (pg_data_t *)arg;
+-      walk_zones_in_node(m, pgdat, zoneinfo_show_print);
++      walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
+       return 0;
+ }
+@@ -1865,7 +1872,7 @@ static int unusable_show(struct seq_file
+       if (!node_state(pgdat->node_id, N_MEMORY))
+               return 0;
+-      walk_zones_in_node(m, pgdat, unusable_show_print);
++      walk_zones_in_node(m, pgdat, true, unusable_show_print);
+       return 0;
+ }
+@@ -1917,7 +1924,7 @@ static int extfrag_show(struct seq_file
+ {
+       pg_data_t *pgdat = (pg_data_t *)arg;
+-      walk_zones_in_node(m, pgdat, extfrag_show_print);
++      walk_zones_in_node(m, pgdat, true, extfrag_show_print);
+       return 0;
+ }
diff --git a/queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch b/queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch
new file mode 100644 (file)
index 0000000..08aad9e
--- /dev/null
@@ -0,0 +1,52 @@
+From c91261437985d481c472639d4397931d77f5d4e9 Mon Sep 17 00:00:00 2001
+From: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Date: Sat, 2 Sep 2017 23:13:55 +0300
+Subject: serial: sccnxp: Fix error handling in sccnxp_probe()
+
+From: Alexey Khoroshilov <khoroshilov@ispras.ru>
+
+commit c91261437985d481c472639d4397931d77f5d4e9 upstream.
+
+sccnxp_probe() returns result of regulator_disable() that may lead
+to returning zero, while device is not properly initialized.
+Also the driver enables clocks, but it does not disable it.
+
+Found by Linux Driver Verification project (linuxtesting.org).
+
+Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/sccnxp.c |   13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/sccnxp.c
++++ b/drivers/tty/serial/sccnxp.c
+@@ -889,7 +889,16 @@ static int sccnxp_probe(struct platform_
+                       goto err_out;
+               uartclk = 0;
+       } else {
+-              clk_prepare_enable(clk);
++              ret = clk_prepare_enable(clk);
++              if (ret)
++                      goto err_out;
++
++              ret = devm_add_action_or_reset(&pdev->dev,
++                              (void(*)(void *))clk_disable_unprepare,
++                              clk);
++              if (ret)
++                      goto err_out;
++
+               uartclk = clk_get_rate(clk);
+       }
+@@ -988,7 +997,7 @@ static int sccnxp_probe(struct platform_
+       uart_unregister_driver(&s->uart);
+ err_out:
+       if (!IS_ERR(s->regulator))
+-              return regulator_disable(s->regulator);
++              regulator_disable(s->regulator);
+       return ret;
+ }
index cc8e702163ba9dc33884d8994fb3da9c69d90114..24c3a93232b071a846ef4794ba0e8a9e64d4cd20 100644 (file)
@@ -23,3 +23,6 @@ bonding-send-learning-packets-for-vlans-on-slave.patch
 tcp-ignore-fast-open-on-repair-mode.patch
 sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch
 sctp-delay-the-authentication-for-the-duplicated-cookie-echo-chunk.patch
+mm-vmstat-print-non-populated-zones-in-zoneinfo.patch
+serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch
+futex-remove-duplicated-code-and-fix-undefined-behaviour.patch