From: Greg Kroah-Hartman Date: Tue, 23 May 2017 10:33:26 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.55~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f3cf278173626e6b238195689c3130842560e375;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: dax-fix-data-corruption-when-fault-races-with-write.patch edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch --- diff --git a/queue-4.11/dax-fix-data-corruption-when-fault-races-with-write.patch b/queue-4.11/dax-fix-data-corruption-when-fault-races-with-write.patch new file mode 100644 index 00000000000..104ac47d2f6 --- /dev/null +++ b/queue-4.11/dax-fix-data-corruption-when-fault-races-with-write.patch @@ -0,0 +1,129 @@ +From 13e451fdc1af05568ea379d71c02a126295d2244 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 12 May 2017 15:46:57 -0700 +Subject: dax: fix data corruption when fault races with write + +From: Jan Kara + +commit 13e451fdc1af05568ea379d71c02a126295d2244 upstream. + +Currently DAX read fault can race with write(2) in the following way: + +CPU1 - write(2) CPU2 - read fault + dax_iomap_pte_fault() + ->iomap_begin() - sees hole +dax_iomap_rw() + iomap_apply() + ->iomap_begin - allocates blocks + dax_iomap_actor() + invalidate_inode_pages2_range() + - there's nothing to invalidate + grab_mapping_entry() + - we add zero page in the radix tree + and map it to page tables + +The result is that hole page is mapped into page tables (and thus zeros +are seen in mmap) while file has data written in that place. + +Fix the problem by locking exception entry before mapping blocks for the +fault. That way we are sure invalidate_inode_pages2_range() call for +racing write will either block on entry lock waiting for the fault to +finish (and unmap stale page tables after that) or read fault will see +already allocated blocks by write(2). + +Fixes: 9f141d6ef6258a3a37a045842d9ba7e68f368956 +Link: http://lkml.kernel.org/r/20170510085419.27601-5-jack@suse.cz +Signed-off-by: Jan Kara +Signed-off-by: Ross Zwisler +Reviewed-by: Ross Zwisler +Cc: Dan Williams +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/dax.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +--- a/fs/dax.c ++++ b/fs/dax.c +@@ -1124,23 +1124,23 @@ static int dax_iomap_pte_fault(struct vm + if ((vmf->flags & FAULT_FLAG_WRITE) && !vmf->cow_page) + flags |= IOMAP_WRITE; + ++ entry = grab_mapping_entry(mapping, vmf->pgoff, 0); ++ if (IS_ERR(entry)) ++ return dax_fault_return(PTR_ERR(entry)); ++ + /* + * Note that we don't bother to use iomap_apply here: DAX required + * the file system block size to be equal the page size, which means + * that we never have to deal with more than a single extent here. + */ + error = ops->iomap_begin(inode, pos, PAGE_SIZE, flags, &iomap); +- if (error) +- return dax_fault_return(error); +- if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) { +- vmf_ret = dax_fault_return(-EIO); /* fs corruption? */ +- goto finish_iomap; ++ if (error) { ++ vmf_ret = dax_fault_return(error); ++ goto unlock_entry; + } +- +- entry = grab_mapping_entry(mapping, vmf->pgoff, 0); +- if (IS_ERR(entry)) { +- vmf_ret = dax_fault_return(PTR_ERR(entry)); +- goto finish_iomap; ++ if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) { ++ error = -EIO; /* fs corruption? */ ++ goto error_finish_iomap; + } + + sector = dax_iomap_sector(&iomap, pos); +@@ -1162,13 +1162,13 @@ static int dax_iomap_pte_fault(struct vm + } + + if (error) +- goto error_unlock_entry; ++ goto error_finish_iomap; + + __SetPageUptodate(vmf->cow_page); + vmf_ret = finish_fault(vmf); + if (!vmf_ret) + vmf_ret = VM_FAULT_DONE_COW; +- goto unlock_entry; ++ goto finish_iomap; + } + + switch (iomap.type) { +@@ -1188,7 +1188,7 @@ static int dax_iomap_pte_fault(struct vm + case IOMAP_HOLE: + if (!(vmf->flags & FAULT_FLAG_WRITE)) { + vmf_ret = dax_load_hole(mapping, &entry, vmf); +- goto unlock_entry; ++ goto finish_iomap; + } + /*FALLTHRU*/ + default: +@@ -1197,10 +1197,8 @@ static int dax_iomap_pte_fault(struct vm + break; + } + +- error_unlock_entry: ++ error_finish_iomap: + vmf_ret = dax_fault_return(error) | major; +- unlock_entry: +- put_locked_mapping_entry(mapping, vmf->pgoff, entry); + finish_iomap: + if (ops->iomap_end) { + int copied = PAGE_SIZE; +@@ -1215,6 +1213,8 @@ static int dax_iomap_pte_fault(struct vm + */ + ops->iomap_end(inode, pos, PAGE_SIZE, copied, flags, &iomap); + } ++ unlock_entry: ++ put_locked_mapping_entry(mapping, vmf->pgoff, entry); + return vmf_ret; + } + diff --git a/queue-4.11/edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch b/queue-4.11/edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch new file mode 100644 index 00000000000..0be8d085739 --- /dev/null +++ b/queue-4.11/edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch @@ -0,0 +1,101 @@ +From eb77e6b80f3bed262c7773236f0fb84649fd3091 Mon Sep 17 00:00:00 2001 +From: Yazen Ghannam +Date: Thu, 27 Apr 2017 12:11:54 -0500 +Subject: EDAC, amd64: Fix reporting of Chip Select sizes on Fam17h + +From: Yazen Ghannam + +commit eb77e6b80f3bed262c7773236f0fb84649fd3091 upstream. + +The wrong index into the csbases/csmasks arrays was being passed to +the function to compute the chip select sizes, which resulted in the +wrong size being computed. Address that so that the correct values are +computed and printed. + +Also, redo how we calculate the number of pages in a CS row. + +Reported-by: Benjamin Bennett +Signed-off-by: Yazen Ghannam +Cc: linux-edac +Link: http://lkml.kernel.org/r/1493313114-11260-1-git-send-email-Yazen.Ghannam@amd.com +[ Remove unneeded integer math comment, minor cleanups. ] +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/edac/amd64_edac.c | 40 +++++++++++++++++++--------------------- + 1 file changed, 19 insertions(+), 21 deletions(-) + +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struc + + static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl) + { +- u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases; +- int dimm, size0, size1; ++ int dimm, size0, size1, cs0, cs1; + + edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); + + for (dimm = 0; dimm < 4; dimm++) { + size0 = 0; ++ cs0 = dimm * 2; + +- if (dcsb[dimm*2] & DCSB_CS_ENABLE) +- size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm); ++ if (csrow_enabled(cs0, ctrl, pvt)) ++ size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0); + + size1 = 0; +- if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) +- size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm); ++ cs1 = dimm * 2 + 1; ++ ++ if (csrow_enabled(cs1, ctrl, pvt)) ++ size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1); + + amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", +- dimm * 2, size0, +- dimm * 2 + 1, size1); ++ cs0, size0, ++ cs1, size1); + } + } + +@@ -2756,26 +2758,22 @@ skip: + * encompasses + * + */ +-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) ++static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) + { +- u32 cs_mode, nr_pages; + u32 dbam = dct ? pvt->dbam1 : pvt->dbam0; ++ int csrow_nr = csrow_nr_orig; ++ u32 cs_mode, nr_pages; + ++ if (!pvt->umc) ++ csrow_nr >>= 1; + +- /* +- * The math on this doesn't look right on the surface because x/2*4 can +- * be simplified to x*2 but this expression makes use of the fact that +- * it is integral math where 1/2=0. This intermediate value becomes the +- * number of bits to shift the DBAM register to extract the proper CSROW +- * field. +- */ +- cs_mode = DBAM_DIMM(csrow_nr / 2, dbam); ++ cs_mode = DBAM_DIMM(csrow_nr, dbam); + +- nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2)) +- << (20 - PAGE_SHIFT); ++ nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr); ++ nr_pages <<= 20 - PAGE_SHIFT; + + edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n", +- csrow_nr, dct, cs_mode); ++ csrow_nr_orig, dct, cs_mode); + edac_dbg(0, "nr_pages/channel: %u\n", nr_pages); + + return nr_pages; diff --git a/queue-4.11/libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch b/queue-4.11/libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch new file mode 100644 index 00000000000..731f83db7a1 --- /dev/null +++ b/queue-4.11/libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch @@ -0,0 +1,41 @@ +From 8d13c0290655b883df9083a2a0af0d782bc38aef Mon Sep 17 00:00:00 2001 +From: Toshi Kani +Date: Thu, 27 Apr 2017 16:57:05 -0600 +Subject: libnvdimm: fix clear length of nvdimm_forget_poison() + +From: Toshi Kani + +commit 8d13c0290655b883df9083a2a0af0d782bc38aef upstream. + +ND_CMD_CLEAR_ERROR command returns 'clear_err.cleared', the length +of error actually cleared, which may be smaller than its requested +'len'. + +Change nvdimm_clear_poison() to call nvdimm_forget_poison() with +'clear_err.cleared' when this value is valid. + +Fixes: e046114af5fc ("libnvdimm: clear the internal poison_list when clearing badblocks") +Cc: Dave Jiang +Cc: Vishal Verma +Signed-off-by: Toshi Kani +Signed-off-by: Dan Williams +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nvdimm/bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/nvdimm/bus.c ++++ b/drivers/nvdimm/bus.c +@@ -218,7 +218,10 @@ long nvdimm_clear_poison(struct device * + if (cmd_rc < 0) + return cmd_rc; + +- nvdimm_clear_from_poison_list(nvdimm_bus, phys, len); ++ if (clear_err.cleared > 0) ++ nvdimm_clear_from_poison_list(nvdimm_bus, phys, ++ clear_err.cleared); ++ + return clear_err.cleared; + } + EXPORT_SYMBOL_GPL(nvdimm_clear_poison); diff --git a/queue-4.11/series b/queue-4.11/series index 53156510fb7..e9103ccf5bc 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -81,3 +81,6 @@ usb-serial-ftdi_sio-fix-setting-latency-for-unprivileged-users.patch usb-serial-ftdi_sio-add-olimex-arm-usb-tiny-h-pids.patch usb-chaoskey-fix-alea-quirk-on-big-endian-hosts.patch make-stat-lstat-fstatat-pass-at_no_automount-to-vfs_statx.patch +libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch +dax-fix-data-corruption-when-fault-races-with-write.patch +edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch