Skip to content

Commit 9b59482

Browse files
Mikulas Patockasnitm
authored andcommitted
dm integrity: fix flush with external metadata device
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>
1 parent 0378c62 commit 9b59482

3 files changed

Lines changed: 56 additions & 11 deletions

File tree

drivers/md/dm-bufio.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,12 @@ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
15341534
}
15351535
EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
15361536

1537+
struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c)
1538+
{
1539+
return c->dm_io;
1540+
}
1541+
EXPORT_SYMBOL_GPL(dm_bufio_get_dm_io_client);
1542+
15371543
sector_t dm_bufio_get_block_number(struct dm_buffer *b)
15381544
{
15391545
return b->block;

drivers/md/dm-integrity.c

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,12 +1379,52 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se
13791379
#undef MAY_BE_HASH
13801380
}
13811381

1382-
static void dm_integrity_flush_buffers(struct dm_integrity_c *ic)
1382+
struct flush_request {
1383+
struct dm_io_request io_req;
1384+
struct dm_io_region io_reg;
1385+
struct dm_integrity_c *ic;
1386+
struct completion comp;
1387+
};
1388+
1389+
static void flush_notify(unsigned long error, void *fr_)
1390+
{
1391+
struct flush_request *fr = fr_;
1392+
if (unlikely(error != 0))
1393+
dm_integrity_io_error(fr->ic, "flusing disk cache", -EIO);
1394+
complete(&fr->comp);
1395+
}
1396+
1397+
static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_data)
13831398
{
13841399
int r;
1400+
1401+
struct flush_request fr;
1402+
1403+
if (!ic->meta_dev)
1404+
flush_data = false;
1405+
if (flush_data) {
1406+
fr.io_req.bi_op = REQ_OP_WRITE,
1407+
fr.io_req.bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
1408+
fr.io_req.mem.type = DM_IO_KMEM,
1409+
fr.io_req.mem.ptr.addr = NULL,
1410+
fr.io_req.notify.fn = flush_notify,
1411+
fr.io_req.notify.context = &fr;
1412+
fr.io_req.client = dm_bufio_get_dm_io_client(ic->bufio),
1413+
fr.io_reg.bdev = ic->dev->bdev,
1414+
fr.io_reg.sector = 0,
1415+
fr.io_reg.count = 0,
1416+
fr.ic = ic;
1417+
init_completion(&fr.comp);
1418+
r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL);
1419+
BUG_ON(r);
1420+
}
1421+
13851422
r = dm_bufio_write_dirty_buffers(ic->bufio);
13861423
if (unlikely(r))
13871424
dm_integrity_io_error(ic, "writing tags", r);
1425+
1426+
if (flush_data)
1427+
wait_for_completion(&fr.comp);
13881428
}
13891429

13901430
static void sleep_on_endio_wait(struct dm_integrity_c *ic)
@@ -2110,7 +2150,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
21102150

21112151
if (unlikely(dio->op == REQ_OP_DISCARD) && likely(ic->mode != 'D')) {
21122152
integrity_metadata(&dio->work);
2113-
dm_integrity_flush_buffers(ic);
2153+
dm_integrity_flush_buffers(ic, false);
21142154

21152155
dio->in_flight = (atomic_t)ATOMIC_INIT(1);
21162156
dio->completion = NULL;
@@ -2195,7 +2235,7 @@ static void integrity_commit(struct work_struct *w)
21952235
flushes = bio_list_get(&ic->flush_bio_list);
21962236
if (unlikely(ic->mode != 'J')) {
21972237
spin_unlock_irq(&ic->endio_wait.lock);
2198-
dm_integrity_flush_buffers(ic);
2238+
dm_integrity_flush_buffers(ic, true);
21992239
goto release_flush_bios;
22002240
}
22012241

@@ -2409,7 +2449,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
24092449
complete_journal_op(&comp);
24102450
wait_for_completion_io(&comp.comp);
24112451

2412-
dm_integrity_flush_buffers(ic);
2452+
dm_integrity_flush_buffers(ic, true);
24132453
}
24142454

24152455
static void integrity_writer(struct work_struct *w)
@@ -2451,7 +2491,7 @@ static void recalc_write_super(struct dm_integrity_c *ic)
24512491
{
24522492
int r;
24532493

2454-
dm_integrity_flush_buffers(ic);
2494+
dm_integrity_flush_buffers(ic, false);
24552495
if (dm_integrity_failed(ic))
24562496
return;
24572497

@@ -2654,7 +2694,7 @@ static void bitmap_flush_work(struct work_struct *work)
26542694
unsigned long limit;
26552695
struct bio *bio;
26562696

2657-
dm_integrity_flush_buffers(ic);
2697+
dm_integrity_flush_buffers(ic, false);
26582698

26592699
range.logical_sector = 0;
26602700
range.n_sectors = ic->provided_data_sectors;
@@ -2663,9 +2703,7 @@ static void bitmap_flush_work(struct work_struct *work)
26632703
add_new_range_and_wait(ic, &range);
26642704
spin_unlock_irq(&ic->endio_wait.lock);
26652705

2666-
dm_integrity_flush_buffers(ic);
2667-
if (ic->meta_dev)
2668-
blkdev_issue_flush(ic->dev->bdev, GFP_NOIO);
2706+
dm_integrity_flush_buffers(ic, true);
26692707

26702708
limit = ic->provided_data_sectors;
26712709
if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
@@ -2934,11 +2972,11 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
29342972
if (ic->meta_dev)
29352973
queue_work(ic->writer_wq, &ic->writer_work);
29362974
drain_workqueue(ic->writer_wq);
2937-
dm_integrity_flush_buffers(ic);
2975+
dm_integrity_flush_buffers(ic, true);
29382976
}
29392977

29402978
if (ic->mode == 'B') {
2941-
dm_integrity_flush_buffers(ic);
2979+
dm_integrity_flush_buffers(ic, true);
29422980
#if 1
29432981
/* set to 0 to test bitmap replay code */
29442982
init_journal(ic, 0, ic->journal_sections, 0);

include/linux/dm-bufio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n);
150150

151151
unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
152152
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
153+
struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c);
153154
sector_t dm_bufio_get_block_number(struct dm_buffer *b);
154155
void *dm_bufio_get_block_data(struct dm_buffer *b);
155156
void *dm_bufio_get_aux_data(struct dm_buffer *b);

0 commit comments

Comments
 (0)