From: Greg Kroah-Hartman Date: Tue, 7 Feb 2017 11:01:56 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v3.18.48~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f2821404a602ebf5a843f8a19f35e0154422891;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch --- 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 index 00000000000..9dc2651c92b --- /dev/null +++ b/queue-4.4/base-memory-hotplug-fix-a-kernel-oops-in-show_valid_zones.patch @@ -0,0 +1,161 @@ +From a96dfddbcc04336bbed50dc2b24823e45e09e80c Mon Sep 17 00:00:00 2001 +From: Toshi Kani +Date: Fri, 3 Feb 2017 13:13:23 -0800 +Subject: base/memory, hotplug: fix a kernel oops in show_valid_zones() + +From: Toshi Kani + +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 +Cc: Greg Kroah-Hartman +Cc: Zhang Zhen +Cc: Reza Arbab +Cc: David Rientjes +Cc: Dan Williams +Cc: [4.4+] +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 0a2e2aac659..00000000000 --- a/queue-4.4/libata-fix-ata-request-sense.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 2dae99558e86894e9e5dbf097477baaa5eb70134 Mon Sep 17 00:00:00 2001 -From: Damien Le Moal -Date: Mon, 19 Dec 2016 10:17:40 +0900 -Subject: libata: Fix ATA request sense - -From: Damien Le Moal - -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 -Signed-off-by: Tejun Heo -Signed-off-by: Greg Kroah-Hartman - ---- - 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 */ diff --git a/queue-4.4/series b/queue-4.4/series index 8fb3684ef01..662cc470c28 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -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