提交 a129d917 编写于 作者: M Mikulas Patocka 提交者: Yang Yingliang

dm integrity: fix flush with external metadata device

stable inclusion
from linux-4.19.170
commit f9f5547bf02a8ec1a9240b8ab6fece5b28d74d1b

--------------------------------

commit 9b594826 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: NLukas Straub <lukasstraub2@web.de>
Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: NMike Snitzer <snitzer@redhat.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 3778ea0c
...@@ -1471,6 +1471,12 @@ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c) ...@@ -1471,6 +1471,12 @@ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
} }
EXPORT_SYMBOL_GPL(dm_bufio_get_device_size); 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) sector_t dm_bufio_get_block_number(struct dm_buffer *b)
{ {
return b->block; return b->block;
......
...@@ -1154,12 +1154,52 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se ...@@ -1154,12 +1154,52 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se
return 0; 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; 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); r = dm_bufio_write_dirty_buffers(ic->bufio);
if (unlikely(r)) if (unlikely(r))
dm_integrity_io_error(ic, "writing tags", 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) static void sleep_on_endio_wait(struct dm_integrity_c *ic)
...@@ -1859,7 +1899,7 @@ static void integrity_commit(struct work_struct *w) ...@@ -1859,7 +1899,7 @@ static void integrity_commit(struct work_struct *w)
flushes = bio_list_get(&ic->flush_bio_list); flushes = bio_list_get(&ic->flush_bio_list);
if (unlikely(ic->mode != 'J')) { if (unlikely(ic->mode != 'J')) {
spin_unlock_irq(&ic->endio_wait.lock); spin_unlock_irq(&ic->endio_wait.lock);
dm_integrity_flush_buffers(ic); dm_integrity_flush_buffers(ic, true);
goto release_flush_bios; goto release_flush_bios;
} }
...@@ -2070,7 +2110,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start, ...@@ -2070,7 +2110,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
complete_journal_op(&comp); complete_journal_op(&comp);
wait_for_completion_io(&comp.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) static void integrity_writer(struct work_struct *w)
...@@ -2112,7 +2152,7 @@ static void recalc_write_super(struct dm_integrity_c *ic) ...@@ -2112,7 +2152,7 @@ static void recalc_write_super(struct dm_integrity_c *ic)
{ {
int r; int r;
dm_integrity_flush_buffers(ic); dm_integrity_flush_buffers(ic, false);
if (dm_integrity_failed(ic)) if (dm_integrity_failed(ic))
return; return;
...@@ -2422,7 +2462,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti) ...@@ -2422,7 +2462,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
if (ic->meta_dev) if (ic->meta_dev)
queue_work(ic->writer_wq, &ic->writer_work); queue_work(ic->writer_wq, &ic->writer_work);
drain_workqueue(ic->writer_wq); drain_workqueue(ic->writer_wq);
dm_integrity_flush_buffers(ic); dm_integrity_flush_buffers(ic, true);
} }
BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress)); BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
......
...@@ -138,6 +138,7 @@ void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n); ...@@ -138,6 +138,7 @@ void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n);
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c); unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
sector_t dm_bufio_get_device_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); 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_block_data(struct dm_buffer *b);
void *dm_bufio_get_aux_data(struct dm_buffer *b); void *dm_bufio_get_aux_data(struct dm_buffer *b);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册