]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Feb 2020 10:40:08 +0000 (11:40 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Feb 2020 10:40:08 +0000 (11:40 +0100)
added patches:
dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch
of-add-of_dma_default_coherent-select-it-on-powerpc.patch

queue-4.9/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch [new file with mode: 0644]
queue-4.9/of-add-of_dma_default_coherent-select-it-on-powerpc.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch b/queue-4.9/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch
new file mode 100644 (file)
index 0000000..589e4b6
--- /dev/null
@@ -0,0 +1,122 @@
+From 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 Mon Sep 17 00:00:00 2001
+From: Joe Thornber <ejt@redhat.com>
+Date: Tue, 7 Jan 2020 11:58:42 +0000
+Subject: dm space map common: fix to ensure new block isn't already in use
+
+From: Joe Thornber <ejt@redhat.com>
+
+commit 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 upstream.
+
+The space-maps track the reference counts for disk blocks allocated by
+both the thin-provisioning and cache targets.  There are variants for
+tracking metadata blocks and data blocks.
+
+Transactionality is implemented by never touching blocks from the
+previous transaction, so we can rollback in the event of a crash.
+
+When allocating a new block we need to ensure the block is free (has
+reference count of 0) in both the current and previous transaction.
+Prior to this fix we were doing this by searching for a free block in
+the previous transaction, and relying on a 'begin' counter to track
+where the last allocation in the current transaction was.  This
+'begin' field was not being updated in all code paths (eg, increment
+of a data block reference count due to breaking sharing of a neighbour
+block in the same btree leaf).
+
+This fix keeps the 'begin' field, but now it's just a hint to speed up
+the search.  Instead the current transaction is searched for a free
+block, and then the old transaction is double checked to ensure it's
+free.  Much simpler.
+
+This fixes reports of sm_disk_new_block()'s BUG_ON() triggering when
+DM thin-provisioning's snapshots are heavily used.
+
+Reported-by: Eric Wheeler <dm-devel@lists.ewheeler.net>
+Cc: stable@vger.kernel.org
+Signed-off-by: Joe Thornber <ejt@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/persistent-data/dm-space-map-common.c   |   27 +++++++++++++++++++++
+ drivers/md/persistent-data/dm-space-map-common.h   |    2 +
+ drivers/md/persistent-data/dm-space-map-disk.c     |    6 +++-
+ drivers/md/persistent-data/dm-space-map-metadata.c |    5 +++
+ 4 files changed, 37 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/persistent-data/dm-space-map-common.c
++++ b/drivers/md/persistent-data/dm-space-map-common.c
+@@ -382,6 +382,33 @@ int sm_ll_find_free_block(struct ll_disk
+       return -ENOSPC;
+ }
++int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
++                               dm_block_t begin, dm_block_t end, dm_block_t *b)
++{
++      int r;
++      uint32_t count;
++
++      do {
++              r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b);
++              if (r)
++                      break;
++
++              /* double check this block wasn't used in the old transaction */
++              if (*b >= old_ll->nr_blocks)
++                      count = 0;
++              else {
++                      r = sm_ll_lookup(old_ll, *b, &count);
++                      if (r)
++                              break;
++
++                      if (count)
++                              begin = *b + 1;
++              }
++      } while (count);
++
++      return r;
++}
++
+ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
+                       int (*mutator)(void *context, uint32_t old, uint32_t *new),
+                       void *context, enum allocation_event *ev)
+--- a/drivers/md/persistent-data/dm-space-map-common.h
++++ b/drivers/md/persistent-data/dm-space-map-common.h
+@@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *
+ int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+                         dm_block_t end, dm_block_t *result);
++int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
++                               dm_block_t begin, dm_block_t end, dm_block_t *result);
+ int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
+ int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+ int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+--- a/drivers/md/persistent-data/dm-space-map-disk.c
++++ b/drivers/md/persistent-data/dm-space-map-disk.c
+@@ -167,8 +167,10 @@ static int sm_disk_new_block(struct dm_s
+       enum allocation_event ev;
+       struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+-      /* FIXME: we should loop round a couple of times */
+-      r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
++      /*
++       * Any block we allocate has to be free in both the old and current ll.
++       */
++      r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);
+       if (r)
+               return r;
+--- a/drivers/md/persistent-data/dm-space-map-metadata.c
++++ b/drivers/md/persistent-data/dm-space-map-metadata.c
+@@ -447,7 +447,10 @@ static int sm_metadata_new_block_(struct
+       enum allocation_event ev;
+       struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+-      r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
++      /*
++       * Any block we allocate has to be free in both the old and current ll.
++       */
++      r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);
+       if (r)
+               return r;
diff --git a/queue-4.9/of-add-of_dma_default_coherent-select-it-on-powerpc.patch b/queue-4.9/of-add-of_dma_default_coherent-select-it-on-powerpc.patch
new file mode 100644 (file)
index 0000000..5d5d385
--- /dev/null
@@ -0,0 +1,80 @@
+From dabf6b36b83a18d57e3d4b9d50544ed040d86255 Mon Sep 17 00:00:00 2001
+From: Michael Ellerman <mpe@ellerman.id.au>
+Date: Sun, 26 Jan 2020 22:52:47 +1100
+Subject: of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
+
+From: Michael Ellerman <mpe@ellerman.id.au>
+
+commit dabf6b36b83a18d57e3d4b9d50544ed040d86255 upstream.
+
+There's an OF helper called of_dma_is_coherent(), which checks if a
+device has a "dma-coherent" property to see if the device is coherent
+for DMA.
+
+But on some platforms devices are coherent by default, and on some
+platforms it's not possible to update existing device trees to add the
+"dma-coherent" property.
+
+So add a Kconfig symbol to allow arch code to tell
+of_dma_is_coherent() that devices are coherent by default, regardless
+of the presence of the property.
+
+Select that symbol on powerpc when NOT_COHERENT_CACHE is not set, ie.
+when the system has a coherent cache.
+
+Fixes: 92ea637edea3 ("of: introduce of_dma_is_coherent() helper")
+Cc: stable@vger.kernel.org # v3.16+
+Reported-by: Christian Zigotzky <chzigotzky@xenosoft.de>
+Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/Kconfig |    1 +
+ drivers/of/Kconfig   |    4 ++++
+ drivers/of/address.c |    6 +++++-
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -85,6 +85,7 @@ config PPC
+       select BINFMT_ELF
+       select ARCH_HAS_ELF_RANDOMIZE
+       select OF
++      select OF_DMA_DEFAULT_COHERENT          if !NOT_COHERENT_CACHE
+       select OF_EARLY_FLATTREE
+       select OF_RESERVED_MEM
+       select HAVE_FTRACE_MCOUNT_RECORD
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -112,4 +112,8 @@ config OF_OVERLAY
+ config OF_NUMA
+       bool
++config OF_DMA_DEFAULT_COHERENT
++      # arches should select this if DMA is coherent by default for OF devices
++      bool
++
+ endif # OF
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -896,12 +896,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);
+  * @np:       device node
+  *
+  * It returns true if "dma-coherent" property was found
+- * for this device in DT.
++ * for this device in the DT, or if DMA is coherent by
++ * default for OF devices on the current platform.
+  */
+ bool of_dma_is_coherent(struct device_node *np)
+ {
+       struct device_node *node = of_node_get(np);
++      if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
++              return true;
++
+       while (node) {
+               if (of_property_read_bool(node, "dma-coherent")) {
+                       of_node_put(node);
index f34855f1c6ce00cfd91a94bace33b880c97d7374..fd53c0f1ea5c696aa2bd9e58b02c07bc5cac28f3 100644 (file)
@@ -31,3 +31,5 @@ ubifs-fix-deadlock-in-concurrent-bulk-read-and-write.patch
 crypto-api-check-spawn-alg-under-lock-in-crypto_drop_spawn.patch
 scsi-qla2xxx-fix-mtcp-dump-collection-failure.patch
 power-supply-ltc2941-battery-gauge-fix-use-after-free.patch
+of-add-of_dma_default_coherent-select-it-on-powerpc.patch
+dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch