From 2ba7a32df421b3138285ddac5ec6fde04518a266 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Feb 2020 13:55:55 +0100 Subject: [PATCH] 4.19-stable patches added patches: dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch --- ...-sequence-when-doing-ssd-mode-commit.patch | 166 ++++++++++++++++++ queue-4.19/series | 1 + 2 files changed, 167 insertions(+) create mode 100644 queue-4.19/dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch diff --git a/queue-4.19/dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch b/queue-4.19/dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch new file mode 100644 index 00000000000..67c15102fe8 --- /dev/null +++ b/queue-4.19/dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch @@ -0,0 +1,166 @@ +From aa9509209c5ac2f0b35d01a922bf9ae072d0c2fc Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 8 Jan 2020 10:46:05 -0500 +Subject: dm writecache: fix incorrect flush sequence when doing SSD mode commit + +From: Mikulas Patocka + +commit aa9509209c5ac2f0b35d01a922bf9ae072d0c2fc upstream. + +When committing state, the function writecache_flush does the following: +1. write metadata (writecache_commit_flushed) +2. flush disk cache (writecache_commit_flushed) +3. wait for data writes to complete (writecache_wait_for_ios) +4. increase superblock seq_count +5. write the superblock +6. flush disk cache + +It may happen that at step 3, when we wait for some write to finish, the +disk may report the write as finished, but the write only hit the disk +cache and it is not yet stored in persistent storage. At step 5 we write +the superblock - it may happen that the superblock is written before the +write that we waited for in step 3. If the machine crashes, it may result +in incorrect data being returned after reboot. + +In order to fix the bug, we must swap steps 2 and 3 in the above sequence, +so that we first wait for writes to complete and then flush the disk +cache. + +Fixes: 48debafe4f2f ("dm: add writecache target") +Cc: stable@vger.kernel.org # 4.18+ +Signed-off-by: Mikulas Patocka +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-writecache.c | 41 +++++++++++++++++++++-------------------- + 1 file changed, 21 insertions(+), 20 deletions(-) + +--- a/drivers/md/dm-writecache.c ++++ b/drivers/md/dm-writecache.c +@@ -447,7 +447,13 @@ static void writecache_notify_io(unsigne + complete(&endio->c); + } + +-static void ssd_commit_flushed(struct dm_writecache *wc) ++static void writecache_wait_for_ios(struct dm_writecache *wc, int direction) ++{ ++ wait_event(wc->bio_in_progress_wait[direction], ++ !atomic_read(&wc->bio_in_progress[direction])); ++} ++ ++static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios) + { + struct dm_io_region region; + struct dm_io_request req; +@@ -493,17 +499,20 @@ static void ssd_commit_flushed(struct dm + writecache_notify_io(0, &endio); + wait_for_completion_io(&endio.c); + ++ if (wait_for_ios) ++ writecache_wait_for_ios(wc, WRITE); ++ + writecache_disk_flush(wc, wc->ssd_dev); + + memset(wc->dirty_bitmap, 0, wc->dirty_bitmap_size); + } + +-static void writecache_commit_flushed(struct dm_writecache *wc) ++static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios) + { + if (WC_MODE_PMEM(wc)) + wmb(); + else +- ssd_commit_flushed(wc); ++ ssd_commit_flushed(wc, wait_for_ios); + } + + static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev) +@@ -527,12 +536,6 @@ static void writecache_disk_flush(struct + writecache_error(wc, r, "error flushing metadata: %d", r); + } + +-static void writecache_wait_for_ios(struct dm_writecache *wc, int direction) +-{ +- wait_event(wc->bio_in_progress_wait[direction], +- !atomic_read(&wc->bio_in_progress[direction])); +-} +- + #define WFE_RETURN_FOLLOWING 1 + #define WFE_LOWEST_SEQ 2 + +@@ -730,14 +733,12 @@ static void writecache_flush(struct dm_w + e = e2; + cond_resched(); + } +- writecache_commit_flushed(wc); +- +- writecache_wait_for_ios(wc, WRITE); ++ writecache_commit_flushed(wc, true); + + wc->seq_count++; + pmem_assign(sb(wc)->seq_count, cpu_to_le64(wc->seq_count)); + writecache_flush_region(wc, &sb(wc)->seq_count, sizeof sb(wc)->seq_count); +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + + wc->overwrote_committed = false; + +@@ -761,7 +762,7 @@ static void writecache_flush(struct dm_w + } + + if (need_flush_after_free) +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + } + + static void writecache_flush_work(struct work_struct *work) +@@ -814,7 +815,7 @@ static void writecache_discard(struct dm + } + + if (discarded_something) +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + } + + static bool writecache_wait_for_writeback(struct dm_writecache *wc) +@@ -963,7 +964,7 @@ erase_this: + + if (need_flush) { + writecache_flush_all_metadata(wc); +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + } + + wc_unlock(wc); +@@ -1347,7 +1348,7 @@ static void __writecache_endio_pmem(stru + wc->writeback_size--; + n_walked++; + if (unlikely(n_walked >= ENDIO_LATENCY)) { +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + wc_unlock(wc); + wc_lock(wc); + n_walked = 0; +@@ -1428,7 +1429,7 @@ pop_from_list: + writecache_wait_for_ios(wc, READ); + } + +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + + wc_unlock(wc); + } +@@ -1759,10 +1760,10 @@ static int init_memory(struct dm_writeca + write_original_sector_seq_count(wc, &wc->entries[b], -1, -1); + + writecache_flush_all_metadata(wc); +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + pmem_assign(sb(wc)->magic, cpu_to_le32(MEMORY_SUPERBLOCK_MAGIC)); + writecache_flush_region(wc, &sb(wc)->magic, sizeof sb(wc)->magic); +- writecache_commit_flushed(wc); ++ writecache_commit_flushed(wc, false); + + return 0; + } diff --git a/queue-4.19/series b/queue-4.19/series index 7f8c873fec3..028fdc9c05a 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -87,3 +87,4 @@ dm-zoned-support-zone-sizes-smaller-than-128mib.patch dm-space-map-common-fix-to-ensure-new-block-isn-t-already-in-use.patch dm-crypt-fix-benbi-iv-constructor-crash-if-used-in-authenticated-mode.patch dm-fix-potential-for-q-make_request_fn-null-pointer.patch +dm-writecache-fix-incorrect-flush-sequence-when-doing-ssd-mode-commit.patch -- 2.47.3