From: Greg Kroah-Hartman Date: Fri, 7 Feb 2020 10:39:44 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.19.103~94 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5f5f57b8e29493f283f0d9309177364785427723;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches 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 --- diff --git a/queue-4.4/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch b/queue-4.4/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch new file mode 100644 index 00000000000..589e4b64d66 --- /dev/null +++ b/queue-4.4/dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch @@ -0,0 +1,122 @@ +From 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 Mon Sep 17 00:00:00 2001 +From: Joe Thornber +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 + +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 +Cc: stable@vger.kernel.org +Signed-off-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + 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.4/of-add-of_dma_default_coherent-select-it-on-powerpc.patch b/queue-4.4/of-add-of_dma_default_coherent-select-it-on-powerpc.patch new file mode 100644 index 00000000000..b7467ffa616 --- /dev/null +++ b/queue-4.4/of-add-of_dma_default_coherent-select-it-on-powerpc.patch @@ -0,0 +1,80 @@ +From dabf6b36b83a18d57e3d4b9d50544ed040d86255 Mon Sep 17 00:00:00 2001 +From: Michael Ellerman +Date: Sun, 26 Jan 2020 22:52:47 +1100 +Subject: of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc + +From: Michael Ellerman + +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 +Tested-by: Christian Zigotzky +Signed-off-by: Michael Ellerman +Reviewed-by: Ulf Hansson +Signed-off-by: Rob Herring +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -93,6 +93,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 + While this option is selected automatically when needed, you can + enable it manually to improve device tree unit test coverage. + ++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 +@@ -1009,12 +1009,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); diff --git a/queue-4.4/series b/queue-4.4/series index 09acde4b2ca..b5b960d4400 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -22,3 +22,5 @@ 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 revert-ovl-modify-ovl_permission-to-do-checks-on-two-inodes.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