]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Jan 2021 11:00:15 +0000 (12:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Jan 2021 11:00:15 +0000 (12:00 +0100)
added patches:
dm-integrity-fix-flush-with-external-metadata-device.patch

queue-4.19/dm-integrity-fix-flush-with-external-metadata-device.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/dm-integrity-fix-flush-with-external-metadata-device.patch b/queue-4.19/dm-integrity-fix-flush-with-external-metadata-device.patch
new file mode 100644 (file)
index 0000000..7821325
--- /dev/null
@@ -0,0 +1,146 @@
+From 9b5948267adc9e689da609eb61cf7ed49cae5fa8 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Fri, 8 Jan 2021 11:15:56 -0500
+Subject: dm integrity: fix flush with external metadata device
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 9b5948267adc9e689da609eb61cf7ed49cae5fa8 upstream.
+
+With external metadata device, flush requests are not passed down to the
+data device.
+
+Fix this by submitting the flush request in dm_integrity_flush_buffers. In
+order to not degrade performance, we overlap the data device flush with
+the metadata device flush.
+
+Reported-by: Lukas Straub <lukasstraub2@web.de>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/md/dm-bufio.c     |    6 +++++
+ drivers/md/dm-integrity.c |   50 +++++++++++++++++++++++++++++++++++++++++-----
+ include/linux/dm-bufio.h  |    1 
+ 3 files changed, 52 insertions(+), 5 deletions(-)
+
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1471,6 +1471,12 @@ sector_t dm_bufio_get_device_size(struct
+ }
+ EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
++struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c)
++{
++      return c->dm_io;
++}
++EXPORT_SYMBOL_GPL(dm_bufio_get_dm_io_client);
++
+ sector_t dm_bufio_get_block_number(struct dm_buffer *b)
+ {
+       return b->block;
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -1153,12 +1153,52 @@ static int dm_integrity_rw_tag(struct dm
+       return 0;
+ }
+-static void dm_integrity_flush_buffers(struct dm_integrity_c *ic)
++struct flush_request {
++      struct dm_io_request io_req;
++      struct dm_io_region io_reg;
++      struct dm_integrity_c *ic;
++      struct completion comp;
++};
++
++static void flush_notify(unsigned long error, void *fr_)
++{
++      struct flush_request *fr = fr_;
++      if (unlikely(error != 0))
++              dm_integrity_io_error(fr->ic, "flusing disk cache", -EIO);
++      complete(&fr->comp);
++}
++
++static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_data)
+ {
+       int r;
++
++      struct flush_request fr;
++
++      if (!ic->meta_dev)
++              flush_data = false;
++      if (flush_data) {
++              fr.io_req.bi_op = REQ_OP_WRITE,
++              fr.io_req.bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
++              fr.io_req.mem.type = DM_IO_KMEM,
++              fr.io_req.mem.ptr.addr = NULL,
++              fr.io_req.notify.fn = flush_notify,
++              fr.io_req.notify.context = &fr;
++              fr.io_req.client = dm_bufio_get_dm_io_client(ic->bufio),
++              fr.io_reg.bdev = ic->dev->bdev,
++              fr.io_reg.sector = 0,
++              fr.io_reg.count = 0,
++              fr.ic = ic;
++              init_completion(&fr.comp);
++              r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL);
++              BUG_ON(r);
++      }
++
+       r = dm_bufio_write_dirty_buffers(ic->bufio);
+       if (unlikely(r))
+               dm_integrity_io_error(ic, "writing tags", r);
++
++      if (flush_data)
++              wait_for_completion(&fr.comp);
+ }
+ static void sleep_on_endio_wait(struct dm_integrity_c *ic)
+@@ -1846,7 +1886,7 @@ static void integrity_commit(struct work
+       flushes = bio_list_get(&ic->flush_bio_list);
+       if (unlikely(ic->mode != 'J')) {
+               spin_unlock_irq(&ic->endio_wait.lock);
+-              dm_integrity_flush_buffers(ic);
++              dm_integrity_flush_buffers(ic, true);
+               goto release_flush_bios;
+       }
+@@ -2057,7 +2097,7 @@ skip_io:
+       complete_journal_op(&comp);
+       wait_for_completion_io(&comp.comp);
+-      dm_integrity_flush_buffers(ic);
++      dm_integrity_flush_buffers(ic, true);
+ }
+ static void integrity_writer(struct work_struct *w)
+@@ -2099,7 +2139,7 @@ static void recalc_write_super(struct dm
+ {
+       int r;
+-      dm_integrity_flush_buffers(ic);
++      dm_integrity_flush_buffers(ic, false);
+       if (dm_integrity_failed(ic))
+               return;
+@@ -2409,7 +2449,7 @@ static void dm_integrity_postsuspend(str
+               if (ic->meta_dev)
+                       queue_work(ic->writer_wq, &ic->writer_work);
+               drain_workqueue(ic->writer_wq);
+-              dm_integrity_flush_buffers(ic);
++              dm_integrity_flush_buffers(ic, true);
+       }
+       BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
+--- a/include/linux/dm-bufio.h
++++ b/include/linux/dm-bufio.h
+@@ -138,6 +138,7 @@ void dm_bufio_set_minimum_buffers(struct
+ unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
++struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c);
+ sector_t dm_bufio_get_block_number(struct dm_buffer *b);
+ void *dm_bufio_get_block_data(struct dm_buffer *b);
+ void *dm_bufio_get_aux_data(struct dm_buffer *b);
index ab3c52acd073f8c9dfec05a04f2fdbb6332b23d6..4307ae6dcb33ee61335fcbaf1ed882553f20ac38 100644 (file)
@@ -1,2 +1,3 @@
 usb-ohci-make-distrust_firmware-param-default-to-false.patch
 compiler.h-raise-minimum-version-of-gcc-to-5.1-for-arm64.patch
+dm-integrity-fix-flush-with-external-metadata-device.patch