]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 May 2017 10:33:26 +0000 (12:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 May 2017 10:33:26 +0000 (12:33 +0200)
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

queue-4.11/dax-fix-data-corruption-when-fault-races-with-write.patch [new file with mode: 0644]
queue-4.11/edac-amd64-fix-reporting-of-chip-select-sizes-on-fam17h.patch [new file with mode: 0644]
queue-4.11/libnvdimm-fix-clear-length-of-nvdimm_forget_poison.patch [new file with mode: 0644]
queue-4.11/series

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 (file)
index 0000000..104ac47
--- /dev/null
@@ -0,0 +1,129 @@
+From 13e451fdc1af05568ea379d71c02a126295d2244 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 12 May 2017 15:46:57 -0700
+Subject: dax: fix data corruption when fault races with write
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
+Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+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>
+
+---
+ 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 (file)
index 0000000..0be8d08
--- /dev/null
@@ -0,0 +1,101 @@
+From eb77e6b80f3bed262c7773236f0fb84649fd3091 Mon Sep 17 00:00:00 2001
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+Date: Thu, 27 Apr 2017 12:11:54 -0500
+Subject: EDAC, amd64: Fix reporting of Chip Select sizes on Fam17h
+
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+
+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 <benbennett@gmail.com>
+Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+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 <bp@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..731f83d
--- /dev/null
@@ -0,0 +1,41 @@
+From 8d13c0290655b883df9083a2a0af0d782bc38aef Mon Sep 17 00:00:00 2001
+From: Toshi Kani <toshi.kani@hpe.com>
+Date: Thu, 27 Apr 2017 16:57:05 -0600
+Subject: libnvdimm: fix clear length of nvdimm_forget_poison()
+
+From: Toshi Kani <toshi.kani@hpe.com>
+
+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 <dave.jiang@intel.com>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index 53156510fb71ec9f64deea68d5aab139ecb83c27..e9103ccf5bcea61a8b5799e7217675f31467c151 100644 (file)
@@ -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