--- /dev/null
+From 7cdf6a0aae1cccf5167f3f04ecddcf648b78e289 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 19 Feb 2020 10:25:45 -0500
+Subject: dm cache: fix a crash due to incorrect work item cancelling
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 7cdf6a0aae1cccf5167f3f04ecddcf648b78e289 upstream.
+
+The crash can be reproduced by running the lvm2 testsuite test
+lvconvert-thin-external-cache.sh for several minutes, e.g.:
+ while :; do make check T=shell/lvconvert-thin-external-cache.sh; done
+
+The crash happens in this call chain:
+do_waker -> policy_tick -> smq_tick -> end_hotspot_period -> clear_bitset
+-> memset -> __memset -- which accesses an invalid pointer in the vmalloc
+area.
+
+The work entry on the workqueue is executed even after the bitmap was
+freed. The problem is that cancel_delayed_work doesn't wait for the
+running work item to finish, so the work item can continue running and
+re-submitting itself even after cache_postsuspend. In order to make sure
+that the work item won't be running, we must use cancel_delayed_work_sync.
+
+Also, change flush_workqueue to drain_workqueue, so that if some work item
+submits itself or another work item, we are properly waiting for both of
+them.
+
+Fixes: c6b4fcbad044 ("dm: add cache target")
+Cc: stable@vger.kernel.org # v3.9
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-cache-target.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-cache-target.c
++++ b/drivers/md/dm-cache-target.c
+@@ -2846,8 +2846,8 @@ static void cache_postsuspend(struct dm_
+ prevent_background_work(cache);
+ BUG_ON(atomic_read(&cache->nr_io_migrations));
+
+- cancel_delayed_work(&cache->waker);
+- flush_workqueue(cache->wq);
++ cancel_delayed_work_sync(&cache->waker);
++ drain_workqueue(cache->wq);
+ WARN_ON(cache->tracker.in_flight);
+
+ /*
--- /dev/null
+From 974f51e8633f0f3f33e8f86bbb5ae66758aa63c7 Mon Sep 17 00:00:00 2001
+From: Hou Tao <houtao1@huawei.com>
+Date: Tue, 3 Mar 2020 16:45:01 +0800
+Subject: dm: fix congested_fn for request-based device
+
+From: Hou Tao <houtao1@huawei.com>
+
+commit 974f51e8633f0f3f33e8f86bbb5ae66758aa63c7 upstream.
+
+We neither assign congested_fn for requested-based blk-mq device nor
+implement it correctly. So fix both.
+
+Also, remove incorrect comment from dm_init_normal_md_queue and rename
+it to dm_init_congested_fn.
+
+Fixes: 4aa9c692e052 ("bdi: separate out congested state into a separate struct")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -1788,7 +1788,8 @@ static int dm_any_congested(void *conges
+ * With request-based DM we only need to check the
+ * top-level queue for congestion.
+ */
+- r = md->queue->backing_dev_info->wb.state & bdi_bits;
++ struct backing_dev_info *bdi = md->queue->backing_dev_info;
++ r = bdi->wb.congested->state & bdi_bits;
+ } else {
+ map = dm_get_live_table_fast(md);
+ if (map)
+@@ -1854,15 +1855,6 @@ static const struct dax_operations dm_da
+
+ static void dm_wq_work(struct work_struct *work);
+
+-static void dm_init_normal_md_queue(struct mapped_device *md)
+-{
+- /*
+- * Initialize aspects of queue that aren't relevant for blk-mq
+- */
+- md->queue->backing_dev_info->congested_data = md;
+- md->queue->backing_dev_info->congested_fn = dm_any_congested;
+-}
+-
+ static void cleanup_mapped_device(struct mapped_device *md)
+ {
+ if (md->wq)
+@@ -2249,6 +2241,12 @@ struct queue_limits *dm_get_queue_limits
+ }
+ EXPORT_SYMBOL_GPL(dm_get_queue_limits);
+
++static void dm_init_congested_fn(struct mapped_device *md)
++{
++ md->queue->backing_dev_info->congested_data = md;
++ md->queue->backing_dev_info->congested_fn = dm_any_congested;
++}
++
+ /*
+ * Setup the DM device's queue based on md's type
+ */
+@@ -2265,11 +2263,12 @@ int dm_setup_md_queue(struct mapped_devi
+ DMERR("Cannot initialize queue for request-based dm-mq mapped device");
+ return r;
+ }
++ dm_init_congested_fn(md);
+ break;
+ case DM_TYPE_BIO_BASED:
+ case DM_TYPE_DAX_BIO_BASED:
+ case DM_TYPE_NVME_BIO_BASED:
+- dm_init_normal_md_queue(md);
++ dm_init_congested_fn(md);
+ break;
+ case DM_TYPE_NONE:
+ WARN_ON_ONCE(true);
--- /dev/null
+From 53770f0ec5fd417429775ba006bc4abe14002335 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 17 Feb 2020 07:43:03 -0500
+Subject: dm integrity: fix a deadlock due to offloading to an incorrect workqueue
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 53770f0ec5fd417429775ba006bc4abe14002335 upstream.
+
+If we need to perform synchronous I/O in dm_integrity_map_continue(),
+we must make sure that we are not in the map function - in order to
+avoid the deadlock due to bio queuing in generic_make_request. To
+avoid the deadlock, we offload the request to metadata_wq.
+
+However, metadata_wq also processes metadata updates for write requests.
+If there are too many requests that get offloaded to metadata_wq at the
+beginning of dm_integrity_map_continue, the workqueue metadata_wq
+becomes clogged and the system is incapable of processing any metadata
+updates.
+
+This causes a deadlock because all the requests that need to do metadata
+updates wait for metadata_wq to proceed and metadata_wq waits inside
+wait_and_add_new_range until some existing request releases its range
+lock (which doesn't happen because the range lock is released after
+metadata update).
+
+In order to fix the deadlock, we create a new workqueue offload_wq and
+offload requests to it - so that processing of offload_wq is independent
+from processing of metadata_wq.
+
+Fixes: 7eada909bfd7 ("dm: add integrity target")
+Cc: stable@vger.kernel.org # v4.12+
+Reported-by: Heinz Mauelshagen <heinzm@redhat.com>
+Tested-by: Heinz Mauelshagen <heinzm@redhat.com>
+Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-integrity.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -212,6 +212,7 @@ struct dm_integrity_c {
+ struct list_head wait_list;
+ wait_queue_head_t endio_wait;
+ struct workqueue_struct *wait_wq;
++ struct workqueue_struct *offload_wq;
+
+ unsigned char commit_seq;
+ commit_id_t commit_ids[N_COMMIT_IDS];
+@@ -1439,7 +1440,7 @@ static void dec_in_flight(struct dm_inte
+ dio->range.logical_sector += dio->range.n_sectors;
+ bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT);
+ INIT_WORK(&dio->work, integrity_bio_wait);
+- queue_work(ic->wait_wq, &dio->work);
++ queue_work(ic->offload_wq, &dio->work);
+ return;
+ }
+ do_endio_flush(ic, dio);
+@@ -1865,7 +1866,7 @@ static void dm_integrity_map_continue(st
+
+ if (need_sync_io && from_map) {
+ INIT_WORK(&dio->work, integrity_bio_wait);
+- queue_work(ic->metadata_wq, &dio->work);
++ queue_work(ic->offload_wq, &dio->work);
+ return;
+ }
+
+@@ -2501,7 +2502,7 @@ static void bitmap_block_work(struct wor
+ dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) {
+ remove_range(ic, &dio->range);
+ INIT_WORK(&dio->work, integrity_bio_wait);
+- queue_work(ic->wait_wq, &dio->work);
++ queue_work(ic->offload_wq, &dio->work);
+ } else {
+ block_bitmap_op(ic, ic->journal, dio->range.logical_sector,
+ dio->range.n_sectors, BITMAP_OP_SET);
+@@ -2524,7 +2525,7 @@ static void bitmap_block_work(struct wor
+
+ remove_range(ic, &dio->range);
+ INIT_WORK(&dio->work, integrity_bio_wait);
+- queue_work(ic->wait_wq, &dio->work);
++ queue_work(ic->offload_wq, &dio->work);
+ }
+
+ queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval);
+@@ -3843,6 +3844,14 @@ static int dm_integrity_ctr(struct dm_ta
+ goto bad;
+ }
+
++ ic->offload_wq = alloc_workqueue("dm-integrity-offload", WQ_MEM_RECLAIM,
++ METADATA_WORKQUEUE_MAX_ACTIVE);
++ if (!ic->offload_wq) {
++ ti->error = "Cannot allocate workqueue";
++ r = -ENOMEM;
++ goto bad;
++ }
++
+ ic->commit_wq = alloc_workqueue("dm-integrity-commit", WQ_MEM_RECLAIM, 1);
+ if (!ic->commit_wq) {
+ ti->error = "Cannot allocate workqueue";
+@@ -4147,6 +4156,8 @@ static void dm_integrity_dtr(struct dm_t
+ destroy_workqueue(ic->metadata_wq);
+ if (ic->wait_wq)
+ destroy_workqueue(ic->wait_wq);
++ if (ic->offload_wq)
++ destroy_workqueue(ic->offload_wq);
+ if (ic->commit_wq)
+ destroy_workqueue(ic->commit_wq);
+ if (ic->writer_wq)
--- /dev/null
+From 7fc2e47f40dd77ab1fcbda6db89614a0173d89c7 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 17 Feb 2020 08:11:35 -0500
+Subject: dm integrity: fix invalid table returned due to argument count mismatch
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 7fc2e47f40dd77ab1fcbda6db89614a0173d89c7 upstream.
+
+If the flag SB_FLAG_RECALCULATE is present in the superblock, but it was
+not specified on the command line (i.e. ic->recalculate_flag is false),
+dm-integrity would return invalid table line - the reported number of
+arguments would not match the real number.
+
+Fixes: 468dfca38b1a ("dm integrity: add a bitmap mode")
+Cc: stable@vger.kernel.org # v5.2+
+Reported-by: Ondrej Kozina <okozina@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-integrity.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -2975,7 +2975,7 @@ static void dm_integrity_status(struct d
+ DMEMIT(" meta_device:%s", ic->meta_dev->name);
+ if (ic->sectors_per_block != 1)
+ DMEMIT(" block_size:%u", ic->sectors_per_block << SECTOR_SHIFT);
+- if (ic->recalculate_flag)
++ if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
+ DMEMIT(" recalculate");
+ DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS);
+ DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
--- /dev/null
+From d5bdf66108419cdb39da361b58ded661c29ff66e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 7 Feb 2020 11:42:30 -0500
+Subject: dm integrity: fix recalculation when moving from journal mode to bitmap mode
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit d5bdf66108419cdb39da361b58ded661c29ff66e upstream.
+
+If we resume a device in bitmap mode and the on-disk format is in journal
+mode, we must recalculate anything above ic->sb->recalc_sector. Otherwise,
+there would be non-recalculated blocks which would cause I/O errors.
+
+Fixes: 468dfca38b1a ("dm integrity: add a bitmap mode")
+Cc: stable@vger.kernel.org # v5.2+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-integrity.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -2888,17 +2888,24 @@ static void dm_integrity_resume(struct d
+ } else {
+ replay_journal(ic);
+ if (ic->mode == 'B') {
+- int mode;
+ ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
+ ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit;
+ r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
+ if (unlikely(r))
+ dm_integrity_io_error(ic, "writing superblock", r);
+
+- mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR;
+- block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode);
+- block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode);
+- block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode);
++ block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
++ block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
++ block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
++ if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
++ le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors) {
++ block_bitmap_op(ic, ic->journal, le64_to_cpu(ic->sb->recalc_sector),
++ ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
++ block_bitmap_op(ic, ic->recalc_bitmap, le64_to_cpu(ic->sb->recalc_sector),
++ ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
++ block_bitmap_op(ic, ic->may_write_bitmap, le64_to_cpu(ic->sb->recalc_sector),
++ ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
++ }
+ rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
+ ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
+ }
--- /dev/null
+From adc0daad366b62ca1bce3e2958a40b0b71a8b8b3 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 24 Feb 2020 10:20:28 +0100
+Subject: dm: report suspended device during destroy
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit adc0daad366b62ca1bce3e2958a40b0b71a8b8b3 upstream.
+
+The function dm_suspended returns true if the target is suspended.
+However, when the target is being suspended during unload, it returns
+false.
+
+An example where this is a problem: the test "!dm_suspended(wc->ti)" in
+writecache_writeback is not sufficient, because dm_suspended returns
+zero while writecache_suspend is in progress. As is, without an
+enhanced dm_suspended, simply switching from flush_workqueue to
+drain_workqueue still emits warnings:
+workqueue writecache-writeback: drain_workqueue() isn't complete after 10 tries
+workqueue writecache-writeback: drain_workqueue() isn't complete after 100 tries
+workqueue writecache-writeback: drain_workqueue() isn't complete after 200 tries
+workqueue writecache-writeback: drain_workqueue() isn't complete after 300 tries
+workqueue writecache-writeback: drain_workqueue() isn't complete after 400 tries
+
+writecache_suspend calls flush_workqueue(wc->writeback_wq) - this function
+flushes the current work. However, the workqueue may re-queue itself and
+flush_workqueue doesn't wait for re-queued works to finish. Because of
+this - the function writecache_writeback continues execution after the
+device was suspended and then concurrently with writecache_dtr, causing
+a crash in writecache_writeback.
+
+We must use drain_workqueue - that waits until the work and all re-queued
+works finish.
+
+As a prereq for switching to drain_workqueue, this commit fixes
+dm_suspended to return true after the presuspend hook and before the
+postsuspend hook - just like during a normal suspend. It allows
+simplifying the dm-integrity and dm-writecache targets so that they
+don't have to maintain suspended flags on their own.
+
+With this change use of drain_workqueue() can be used effectively. This
+change was tested with the lvm2 testsuite and cryptsetup testsuite and
+the are no regressions.
+
+Fixes: 48debafe4f2f ("dm: add writecache target")
+Cc: stable@vger.kernel.org # 4.18+
+Reported-by: Corey Marthaler <cmarthal@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-integrity.c | 12 +++++-------
+ drivers/md/dm-writecache.c | 2 +-
+ drivers/md/dm.c | 1 +
+ 3 files changed, 7 insertions(+), 8 deletions(-)
+
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -201,12 +201,13 @@ struct dm_integrity_c {
+ __u8 log2_blocks_per_bitmap_bit;
+
+ unsigned char mode;
+- int suspending;
+
+ int failed;
+
+ struct crypto_shash *internal_hash;
+
++ struct dm_target *ti;
++
+ /* these variables are locked with endio_wait.lock */
+ struct rb_root in_progress;
+ struct list_head wait_list;
+@@ -2316,7 +2317,7 @@ static void integrity_writer(struct work
+ unsigned prev_free_sectors;
+
+ /* the following test is not needed, but it tests the replay code */
+- if (READ_ONCE(ic->suspending) && !ic->meta_dev)
++ if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev)
+ return;
+
+ spin_lock_irq(&ic->endio_wait.lock);
+@@ -2377,7 +2378,7 @@ static void integrity_recalc(struct work
+
+ next_chunk:
+
+- if (unlikely(READ_ONCE(ic->suspending)))
++ if (unlikely(dm_suspended(ic->ti)))
+ goto unlock_ret;
+
+ range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
+@@ -2805,8 +2806,6 @@ static void dm_integrity_postsuspend(str
+
+ del_timer_sync(&ic->autocommit_timer);
+
+- WRITE_ONCE(ic->suspending, 1);
+-
+ if (ic->recalc_wq)
+ drain_workqueue(ic->recalc_wq);
+
+@@ -2835,8 +2834,6 @@ static void dm_integrity_postsuspend(str
+ #endif
+ }
+
+- WRITE_ONCE(ic->suspending, 0);
+-
+ BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
+
+ ic->journal_uptodate = true;
+@@ -3631,6 +3628,7 @@ static int dm_integrity_ctr(struct dm_ta
+ }
+ ti->private = ic;
+ ti->per_io_data_size = sizeof(struct dm_integrity_io);
++ ic->ti = ti;
+
+ ic->in_progress = RB_ROOT;
+ INIT_LIST_HEAD(&ic->wait_list);
+--- a/drivers/md/dm-writecache.c
++++ b/drivers/md/dm-writecache.c
+@@ -838,7 +838,7 @@ static void writecache_suspend(struct dm
+ }
+ wc_unlock(wc);
+
+- flush_workqueue(wc->writeback_wq);
++ drain_workqueue(wc->writeback_wq);
+
+ wc_lock(wc);
+ if (flush_on_suspend)
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2368,6 +2368,7 @@ static void __dm_destroy(struct mapped_d
+ map = dm_get_live_table(md, &srcu_idx);
+ if (!dm_suspended_md(md)) {
+ dm_table_presuspend_targets(map);
++ set_bit(DMF_SUSPENDED, &md->flags);
+ dm_table_postsuspend_targets(map);
+ }
+ /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
--- /dev/null
+From 41c526c5af46d4c4dab7f72c99000b7fac0b9702 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 24 Feb 2020 10:20:30 +0100
+Subject: dm writecache: verify watermark during resume
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 41c526c5af46d4c4dab7f72c99000b7fac0b9702 upstream.
+
+Verify the watermark upon resume - so that if the target is reloaded
+with lower watermark, it will start the cleanup process immediately.
+
+Fixes: 48debafe4f2f ("dm: add writecache target")
+Cc: stable@vger.kernel.org # 4.18+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-writecache.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-writecache.c
++++ b/drivers/md/dm-writecache.c
+@@ -625,6 +625,12 @@ static void writecache_add_to_freelist(s
+ wc->freelist_size++;
+ }
+
++static inline void writecache_verify_watermark(struct dm_writecache *wc)
++{
++ if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
++ queue_work(wc->writeback_wq, &wc->writeback_work);
++}
++
+ static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc)
+ {
+ struct wc_entry *e;
+@@ -646,8 +652,8 @@ static struct wc_entry *writecache_pop_f
+ list_del(&e->lru);
+ }
+ wc->freelist_size--;
+- if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
+- queue_work(wc->writeback_wq, &wc->writeback_work);
++
++ writecache_verify_watermark(wc);
+
+ return e;
+ }
+@@ -961,6 +967,8 @@ erase_this:
+ writecache_commit_flushed(wc, false);
+ }
+
++ writecache_verify_watermark(wc);
++
+ wc_unlock(wc);
+ }
+
--- /dev/null
+From ee63634bae02e13c8c0df1209a6a0ca5326f3189 Mon Sep 17 00:00:00 2001
+From: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Date: Thu, 27 Feb 2020 09:18:52 +0900
+Subject: dm zoned: Fix reference counter initial value of chunk works
+
+From: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+
+commit ee63634bae02e13c8c0df1209a6a0ca5326f3189 upstream.
+
+Dm-zoned initializes reference counters of new chunk works with zero
+value and refcount_inc() is called to increment the counter. However, the
+refcount_inc() function handles the addition to zero value as an error
+and triggers the warning as follows:
+
+refcount_t: addition on 0; use-after-free.
+WARNING: CPU: 7 PID: 1506 at lib/refcount.c:25 refcount_warn_saturate+0x68/0xf0
+...
+CPU: 7 PID: 1506 Comm: systemd-udevd Not tainted 5.4.0+ #134
+...
+Call Trace:
+ dmz_map+0x2d2/0x350 [dm_zoned]
+ __map_bio+0x42/0x1a0
+ __split_and_process_non_flush+0x14a/0x1b0
+ __split_and_process_bio+0x83/0x240
+ ? kmem_cache_alloc+0x165/0x220
+ dm_process_bio+0x90/0x230
+ ? generic_make_request_checks+0x2e7/0x680
+ dm_make_request+0x3e/0xb0
+ generic_make_request+0xcf/0x320
+ ? memcg_drain_all_list_lrus+0x1c0/0x1c0
+ submit_bio+0x3c/0x160
+ ? guard_bio_eod+0x2c/0x130
+ mpage_readpages+0x182/0x1d0
+ ? bdev_evict_inode+0xf0/0xf0
+ read_pages+0x6b/0x1b0
+ __do_page_cache_readahead+0x1ba/0x1d0
+ force_page_cache_readahead+0x93/0x100
+ generic_file_read_iter+0x83a/0xe40
+ ? __seccomp_filter+0x7b/0x670
+ new_sync_read+0x12a/0x1c0
+ vfs_read+0x9d/0x150
+ ksys_read+0x5f/0xe0
+ do_syscall_64+0x5b/0x180
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+...
+
+After this warning, following refcount API calls for the counter all fail
+to change the counter value.
+
+Fix this by setting the initial reference counter value not zero but one
+for the new chunk works. Instead, do not call refcount_inc() via
+dmz_get_chunk_work() for the new chunks works.
+
+The failure was observed with linux version 5.4 with CONFIG_REFCOUNT_FULL
+enabled. Refcount rework was merged to linux version 5.5 by the
+commit 168829ad09ca ("Merge branch 'locking-core-for-linus' of
+git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip"). After this
+commit, CONFIG_REFCOUNT_FULL was removed and the failure was observed
+regardless of kernel configuration.
+
+Linux version 4.20 merged the commit 092b5648760a ("dm zoned: target: use
+refcount_t for dm zoned reference counters"). Before this commit, dm
+zoned used atomic_t APIs which does not check addition to zero, then this
+fix is not necessary.
+
+Fixes: 092b5648760a ("dm zoned: target: use refcount_t for dm zoned reference counters")
+Cc: stable@vger.kernel.org # 5.4+
+Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-zoned-target.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/md/dm-zoned-target.c
++++ b/drivers/md/dm-zoned-target.c
+@@ -533,8 +533,9 @@ static int dmz_queue_chunk_work(struct d
+
+ /* Get the BIO chunk work. If one is not active yet, create one */
+ cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
+- if (!cw) {
+-
++ if (cw) {
++ dmz_get_chunk_work(cw);
++ } else {
+ /* Create a new chunk work */
+ cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
+ if (unlikely(!cw)) {
+@@ -543,7 +544,7 @@ static int dmz_queue_chunk_work(struct d
+ }
+
+ INIT_WORK(&cw->work, dmz_chunk_work);
+- refcount_set(&cw->refcount, 0);
++ refcount_set(&cw->refcount, 1);
+ cw->target = dmz;
+ cw->chunk = chunk;
+ bio_list_init(&cw->bio_list);
+@@ -556,7 +557,6 @@ static int dmz_queue_chunk_work(struct d
+ }
+
+ bio_list_add(&cw->bio_list, bio);
+- dmz_get_chunk_work(cw);
+
+ dmz_reclaim_bio_acc(dmz->reclaim);
+ if (queue_work(dmz->chunk_wq, &cw->work))
--- /dev/null
+From 94788af4ed039476ff3527b0e6a12c1dc42cb022 Mon Sep 17 00:00:00 2001
+From: Dmitry Osipenko <digetx@gmail.com>
+Date: Sun, 9 Feb 2020 19:33:38 +0300
+Subject: dmaengine: tegra-apb: Fix use-after-free
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+commit 94788af4ed039476ff3527b0e6a12c1dc42cb022 upstream.
+
+I was doing some experiments with I2C and noticed that Tegra APB DMA
+driver crashes sometime after I2C DMA transfer termination. The crash
+happens because tegra_dma_terminate_all() bails out immediately if pending
+list is empty, and thus, it doesn't release the half-completed descriptors
+which are getting re-used before ISR tasklet kicks-in.
+
+ tegra-i2c 7000c400.i2c: DMA transfer timeout
+ elants_i2c 0-0010: elants_i2c_irq: failed to read data: -110
+ ------------[ cut here ]------------
+ WARNING: CPU: 0 PID: 142 at lib/list_debug.c:45 __list_del_entry_valid+0x45/0xac
+ list_del corruption, ddbaac44->next is LIST_POISON1 (00000100)
+ Modules linked in:
+ CPU: 0 PID: 142 Comm: kworker/0:2 Not tainted 5.5.0-rc2-next-20191220-00175-gc3605715758d-dirty #538
+ Hardware name: NVIDIA Tegra SoC (Flattened Device Tree)
+ Workqueue: events_freezable_power_ thermal_zone_device_check
+ [<c010e5c5>] (unwind_backtrace) from [<c010a1c5>] (show_stack+0x11/0x14)
+ [<c010a1c5>] (show_stack) from [<c0973925>] (dump_stack+0x85/0x94)
+ [<c0973925>] (dump_stack) from [<c011f529>] (__warn+0xc1/0xc4)
+ [<c011f529>] (__warn) from [<c011f7e9>] (warn_slowpath_fmt+0x61/0x78)
+ [<c011f7e9>] (warn_slowpath_fmt) from [<c042497d>] (__list_del_entry_valid+0x45/0xac)
+ [<c042497d>] (__list_del_entry_valid) from [<c047a87f>] (tegra_dma_tasklet+0x5b/0x154)
+ [<c047a87f>] (tegra_dma_tasklet) from [<c0124799>] (tasklet_action_common.constprop.0+0x41/0x7c)
+ [<c0124799>] (tasklet_action_common.constprop.0) from [<c01022ab>] (__do_softirq+0xd3/0x2a8)
+ [<c01022ab>] (__do_softirq) from [<c0124683>] (irq_exit+0x7b/0x98)
+ [<c0124683>] (irq_exit) from [<c0168c19>] (__handle_domain_irq+0x45/0x80)
+ [<c0168c19>] (__handle_domain_irq) from [<c043e429>] (gic_handle_irq+0x45/0x7c)
+ [<c043e429>] (gic_handle_irq) from [<c0101aa5>] (__irq_svc+0x65/0x94)
+ Exception stack(0xde2ebb90 to 0xde2ebbd8)
+
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Acked-by: Jon Hunter <jonathanh@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200209163356.6439-2-digetx@gmail.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma/tegra20-apb-dma.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/dma/tegra20-apb-dma.c
++++ b/drivers/dma/tegra20-apb-dma.c
+@@ -756,10 +756,6 @@ static int tegra_dma_terminate_all(struc
+ bool was_busy;
+
+ spin_lock_irqsave(&tdc->lock, flags);
+- if (list_empty(&tdc->pending_sg_req)) {
+- spin_unlock_irqrestore(&tdc->lock, flags);
+- return 0;
+- }
+
+ if (!tdc->busy)
+ goto skip_dma_stop;
--- /dev/null
+From c33ee1301c393a241d6424e36eff1071811b1064 Mon Sep 17 00:00:00 2001
+From: Dmitry Osipenko <digetx@gmail.com>
+Date: Sun, 9 Feb 2020 19:33:39 +0300
+Subject: dmaengine: tegra-apb: Prevent race conditions of tasklet vs free list
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+commit c33ee1301c393a241d6424e36eff1071811b1064 upstream.
+
+The interrupt handler puts a half-completed DMA descriptor on a free list
+and then schedules tasklet to process bottom half of the descriptor that
+executes client's callback, this creates possibility to pick up the busy
+descriptor from the free list. Thus, let's disallow descriptor's re-use
+until it is fully processed.
+
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Acked-by: Jon Hunter <jonathanh@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200209163356.6439-3-digetx@gmail.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma/tegra20-apb-dma.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/dma/tegra20-apb-dma.c
++++ b/drivers/dma/tegra20-apb-dma.c
+@@ -281,7 +281,7 @@ static struct tegra_dma_desc *tegra_dma_
+
+ /* Do not allocate if desc are waiting for ack */
+ list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
+- if (async_tx_test_ack(&dma_desc->txd)) {
++ if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) {
+ list_del(&dma_desc->node);
+ spin_unlock_irqrestore(&tdc->lock, flags);
+ dma_desc->txd.flags = 0;
drm-amd-powerplay-fix-pre-check-condition-for-setting-clock-range.patch
dmaengine-imx-sdma-fix-context-cache.patch
dmaengine-imx-sdma-fix-the-event-id-check-to-include-rx-event-for-uart6.patch
+dmaengine-tegra-apb-fix-use-after-free.patch
+dmaengine-tegra-apb-prevent-race-conditions-of-tasklet-vs-free-list.patch
+dm-integrity-fix-recalculation-when-moving-from-journal-mode-to-bitmap-mode.patch
+dm-integrity-fix-a-deadlock-due-to-offloading-to-an-incorrect-workqueue.patch
+dm-integrity-fix-invalid-table-returned-due-to-argument-count-mismatch.patch
+dm-cache-fix-a-crash-due-to-incorrect-work-item-cancelling.patch
+dm-report-suspended-device-during-destroy.patch
+dm-writecache-verify-watermark-during-resume.patch
+dm-zoned-fix-reference-counter-initial-value-of-chunk-works.patch
+dm-fix-congested_fn-for-request-based-device.patch