[dm-devel] [PATCH] dm-integrity: Fix flush with external metadata device

Lukas Straub lukasstraub2 at web.de
Sun Jan 10 10:04:22 UTC 2021


On Fri, 8 Jan 2021 11:15:56 -0500 (EST)
Mikulas Patocka <mpatocka at redhat.com> wrote:

> 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.
> 
> Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
> Reported-by: Lukas Straub <lukasstraub2 at web.de>
> Cc: stable at vger.kernel.org

Looks good to me.
Reviewed-by: Lukas Straub <lukasstraub2 at web.de>

Regards,
Lukas Straub

> ---
>  drivers/md/dm-bufio.c     |    6 ++++
>  drivers/md/dm-integrity.c |   60 +++++++++++++++++++++++++++++++++++++---------
>  include/linux/dm-bufio.h  |    1 
>  3 files changed, 56 insertions(+), 11 deletions(-)
> 
> Index: linux-2.6/drivers/md/dm-integrity.c
> ===================================================================
> --- linux-2.6.orig/drivers/md/dm-integrity.c	2021-01-07 17:22:39.000000000 +0100
> +++ linux-2.6/drivers/md/dm-integrity.c	2021-01-08 15:51:19.000000000 +0100
> @@ -1379,12 +1379,52 @@ thorough_test:
>  #undef MAY_BE_HASH
>  }
>  
> -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)
> @@ -2110,7 +2150,7 @@ offload_to_thread:
>  
>  	if (unlikely(dio->op == REQ_OP_DISCARD) && likely(ic->mode != 'D')) {
>  		integrity_metadata(&dio->work);
> -		dm_integrity_flush_buffers(ic);
> +		dm_integrity_flush_buffers(ic, false);
>  
>  		dio->in_flight = (atomic_t)ATOMIC_INIT(1);
>  		dio->completion = NULL;
> @@ -2195,7 +2235,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;
>  	}
>  
> @@ -2409,7 +2449,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)
> @@ -2451,7 +2491,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;
>  
> @@ -2654,7 +2694,7 @@ static void bitmap_flush_work(struct wor
>  	unsigned long limit;
>  	struct bio *bio;
>  
> -	dm_integrity_flush_buffers(ic);
> +	dm_integrity_flush_buffers(ic, false);
>  
>  	range.logical_sector = 0;
>  	range.n_sectors = ic->provided_data_sectors;
> @@ -2663,9 +2703,7 @@ static void bitmap_flush_work(struct wor
>  	add_new_range_and_wait(ic, &range);
>  	spin_unlock_irq(&ic->endio_wait.lock);
>  
> -	dm_integrity_flush_buffers(ic);
> -	if (ic->meta_dev)
> -		blkdev_issue_flush(ic->dev->bdev, GFP_NOIO);
> +	dm_integrity_flush_buffers(ic, true);
>  
>  	limit = ic->provided_data_sectors;
>  	if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
> @@ -2934,11 +2972,11 @@ 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);
>  	}
>  
>  	if (ic->mode == 'B') {
> -		dm_integrity_flush_buffers(ic);
> +		dm_integrity_flush_buffers(ic, true);
>  #if 1
>  		/* set to 0 to test bitmap replay code */
>  		init_journal(ic, 0, ic->journal_sections, 0);
> Index: linux-2.6/include/linux/dm-bufio.h
> ===================================================================
> --- linux-2.6.orig/include/linux/dm-bufio.h	2020-09-05 10:01:42.000000000 +0200
> +++ linux-2.6/include/linux/dm-bufio.h	2021-01-08 15:12:31.000000000 +0100
> @@ -150,6 +150,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: linux-2.6/drivers/md/dm-bufio.c
> ===================================================================
> --- linux-2.6.orig/drivers/md/dm-bufio.c	2021-01-08 15:11:20.000000000 +0100
> +++ linux-2.6/drivers/md/dm-bufio.c	2021-01-08 15:12:25.000000000 +0100
> @@ -1534,6 +1534,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;
> 



-- 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20210110/ff0c5955/attachment.sig>


More information about the dm-devel mailing list