]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Feb 2017 11:01:56 +0000 (12:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Feb 2017 11:01:56 +0000 (12:01 +0100)
added patches:
base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch

queue-4.4/base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch [new file with mode: 0644]
queue-4.4/libata-fix-ata-request-sense.patch [deleted file]
queue-4.4/series

diff --git a/queue-4.4/base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch b/queue-4.4/base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch
new file mode 100644 (file)
index 0000000..9dc2651
--- /dev/null
@@ -0,0 +1,161 @@
+From a96dfddbcc04336bbed50dc2b24823e45e09e80c Mon Sep 17 00:00:00 2001
+From: Toshi Kani <toshi.kani@hpe.com>
+Date: Fri, 3 Feb 2017 13:13:23 -0800
+Subject: base/memory, hotplug: fix a kernel oops in show_valid_zones()
+
+From: Toshi Kani <toshi.kani@hpe.com>
+
+commit a96dfddbcc04336bbed50dc2b24823e45e09e80c upstream.
+
+Reading a sysfs "memoryN/valid_zones" file leads to the following oops
+when the first page of a range is not backed by struct page.
+show_valid_zones() assumes that 'start_pfn' is always valid for
+page_zone().
+
+ BUG: unable to handle kernel paging request at ffffea017a000000
+ IP: show_valid_zones+0x6f/0x160
+
+This issue may happen on x86-64 systems with 64GiB or more memory since
+their memory block size is bumped up to 2GiB.  [1] An example of such
+systems is desribed below.  0x3240000000 is only aligned by 1GiB and
+this memory block starts from 0x3200000000, which is not backed by
+struct page.
+
+ BIOS-e820: [mem 0x0000003240000000-0x000000603fffffff] usable
+
+Since test_pages_in_a_zone() already checks holes, fix this issue by
+extending this function to return 'valid_start' and 'valid_end' for a
+given range.  show_valid_zones() then proceeds with the valid range.
+
+[1] 'Commit bdee237c0343 ("x86: mm: Use 2GB memory block size on
+    large-memory x86-64 systems")'
+
+Link: http://lkml.kernel.org/r/20170127222149.30893-3-toshi.kani@hpe.com
+Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Zhang Zhen <zhenzhang.zhang@huawei.com>
+Cc: Reza Arbab <arbab@linux.vnet.ibm.com>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: <stable@vger.kernel.org>   [4.4+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/memory.c          |   11 +++++------
+ include/linux/memory_hotplug.h |    3 ++-
+ mm/memory_hotplug.c            |   20 +++++++++++++++-----
+ 3 files changed, 22 insertions(+), 12 deletions(-)
+
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -388,30 +388,29 @@ static ssize_t show_valid_zones(struct d
+ {
+       struct memory_block *mem = to_memory_block(dev);
+       unsigned long start_pfn, end_pfn;
++      unsigned long valid_start, valid_end;
+       unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
+-      struct page *first_page;
+       struct zone *zone;
+       start_pfn = section_nr_to_pfn(mem->start_section_nr);
+       end_pfn = start_pfn + nr_pages;
+-      first_page = pfn_to_page(start_pfn);
+       /* The block contains more than one zone can not be offlined. */
+-      if (!test_pages_in_a_zone(start_pfn, end_pfn))
++      if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
+               return sprintf(buf, "none\n");
+-      zone = page_zone(first_page);
++      zone = page_zone(pfn_to_page(valid_start));
+       if (zone_idx(zone) == ZONE_MOVABLE - 1) {
+               /*The mem block is the last memoryblock of this zone.*/
+-              if (end_pfn == zone_end_pfn(zone))
++              if (valid_end == zone_end_pfn(zone))
+                       return sprintf(buf, "%s %s\n",
+                                       zone->name, (zone + 1)->name);
+       }
+       if (zone_idx(zone) == ZONE_MOVABLE) {
+               /*The mem block is the first memoryblock of ZONE_MOVABLE.*/
+-              if (start_pfn == zone->zone_start_pfn)
++              if (valid_start == zone->zone_start_pfn)
+                       return sprintf(buf, "%s %s\n",
+                                       zone->name, (zone - 1)->name);
+       }
+--- a/include/linux/memory_hotplug.h
++++ b/include/linux/memory_hotplug.h
+@@ -85,7 +85,8 @@ extern int zone_grow_waitqueues(struct z
+ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
+ /* VM interface that may be used by firmware interface */
+ extern int online_pages(unsigned long, unsigned long, int);
+-extern int test_pages_in_a_zone(unsigned long, unsigned long);
++extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
++      unsigned long *valid_start, unsigned long *valid_end);
+ extern void __offline_isolated_pages(unsigned long, unsigned long);
+ typedef void (*online_page_callback_t)(struct page *page);
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1372,10 +1372,13 @@ int is_mem_section_removable(unsigned lo
+ /*
+  * Confirm all pages in a range [start, end) belong to the same zone.
++ * When true, return its valid [start, end).
+  */
+-int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
++int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
++                       unsigned long *valid_start, unsigned long *valid_end)
+ {
+       unsigned long pfn, sec_end_pfn;
++      unsigned long start, end;
+       struct zone *zone = NULL;
+       struct page *page;
+       int i;
+@@ -1397,14 +1400,20 @@ int test_pages_in_a_zone(unsigned long s
+                       page = pfn_to_page(pfn + i);
+                       if (zone && page_zone(page) != zone)
+                               return 0;
++                      if (!zone)
++                              start = pfn + i;
+                       zone = page_zone(page);
++                      end = pfn + MAX_ORDER_NR_PAGES;
+               }
+       }
+-      if (zone)
++      if (zone) {
++              *valid_start = start;
++              *valid_end = end;
+               return 1;
+-      else
++      } else {
+               return 0;
++      }
+ }
+ /*
+@@ -1722,6 +1731,7 @@ static int __ref __offline_pages(unsigne
+       long offlined_pages;
+       int ret, drain, retry_max, node;
+       unsigned long flags;
++      unsigned long valid_start, valid_end;
+       struct zone *zone;
+       struct memory_notify arg;
+@@ -1732,10 +1742,10 @@ static int __ref __offline_pages(unsigne
+               return -EINVAL;
+       /* This makes hotplug much easier...and readable.
+          we assume this for now. .*/
+-      if (!test_pages_in_a_zone(start_pfn, end_pfn))
++      if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
+               return -EINVAL;
+-      zone = page_zone(pfn_to_page(start_pfn));
++      zone = page_zone(pfn_to_page(valid_start));
+       node = zone_to_nid(zone);
+       nr_pages = end_pfn - start_pfn;
diff --git a/queue-4.4/libata-fix-ata-request-sense.patch b/queue-4.4/libata-fix-ata-request-sense.patch
deleted file mode 100644 (file)
index 0a2e2aa..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 2dae99558e86894e9e5dbf097477baaa5eb70134 Mon Sep 17 00:00:00 2001
-From: Damien Le Moal <damien.lemoal@wdc.com>
-Date: Mon, 19 Dec 2016 10:17:40 +0900
-Subject: libata: Fix ATA request sense
-
-From: Damien Le Moal <damien.lemoal@wdc.com>
-
-commit 2dae99558e86894e9e5dbf097477baaa5eb70134 upstream.
-
-For an ATA device supporting the sense data reporting feature set, a
-failed command will trigger the execution of ata_eh_request_sense if
-the result task file of the failed command has the ATA_SENSE bit set
-(sense data available bit). ata_eh_request_sense executes the REQUEST
-SENSE DATA EXT command to retrieve the sense data of the failed
-command. On success of REQUEST SENSE DATA EXT, the ATA_SENSE bit will
-NOT be set (the command succeeded) but ata_eh_request_sense
-nevertheless tests the availability of sense data by testing that bit
-presence in the result tf of the REQUEST SENSE DATA EXT command.  This
-leads us to falsely assume that request sense data failed and to the
-warning message:
-
-atax.xx: request sense failed stat 50 emask 0
-
-Upon success of REQUEST SENSE DATA EXT, set the ATA_SENSE bit in the
-result task file command so that sense data can be returned by
-ata_eh_request_sense.
-
-Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
-Signed-off-by: Tejun Heo <tj@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/ata/libata-core.c |    2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -1692,6 +1692,8 @@ unsigned ata_exec_internal_sg(struct ata
-               if (qc->err_mask & ~AC_ERR_OTHER)
-                       qc->err_mask &= ~AC_ERR_OTHER;
-+      } else if (qc->tf.command == ATA_CMD_REQ_SENSE_DATA) {
-+              qc->result_tf.command |= ATA_SENSE;
-       }
-       /* finish up */
index 8fb3684ef0198f905814acf8265676102f8a3d65..662cc470c284b105d33614f3c705e12db748ce35 100644 (file)
@@ -7,7 +7,6 @@ crypto-arm64-aes-blk-honour-iv_out-requirement-in-cbc-and-ctr-modes.patch
 perf-core-fix-perf_record_mmap2-prot-flags-for-anonymous-memory.patch
 ata-sata_mv-handle-return-value-of-devm_ioremap.patch
 libata-apply-max_sec_1024-to-all-cx1-jb-hp-devices.patch
-libata-fix-ata-request-sense.patch
 powerpc-eeh-fix-wrong-flag-passed-to-eeh_unfreeze_pe.patch
 powerpc-add-missing-error-check-to-prom_find_boot_cpu.patch
 nfsd-fix-a-null-reference-case-in-find_or_create_lock_stateid.patch
@@ -27,3 +26,4 @@ usb-add-quirk-for-worlde-easykey.25-midi-keyboard.patch
 usb-gadget-f_fs-assorted-buffer-overflow-checks.patch
 usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch
 x86-irq-make-irq-activate-operations-symmetric.patch
+base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch