[dm-devel] dm-writecache: allow the underlying device to be shrunk

Mike Snitzer snitzer at redhat.com
Tue Feb 9 21:51:59 UTC 2021


On Tue, Feb 09 2021 at 10:56am -0500,
Mikulas Patocka <mpatocka at redhat.com> wrote:

> Allow shrinking the underlying data device (dm-writecache must be
> suspended when the device is shrunk).
> 
> This patch modifies dm-writecache, so that it doesn't attempt to write any
> data beyond the end of the data device.
> 
> Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
> Cc: stable at vger.kernel.org
> 
> ---
>  drivers/md/dm-writecache.c |   18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> Index: linux-2.6/drivers/md/dm-writecache.c
> ===================================================================
> --- linux-2.6.orig/drivers/md/dm-writecache.c	2021-02-05 20:30:35.000000000 +0100
> +++ linux-2.6/drivers/md/dm-writecache.c	2021-02-09 16:50:36.000000000 +0100
> @@ -148,6 +148,7 @@ struct dm_writecache {
>  	size_t metadata_sectors;
>  	size_t n_blocks;
>  	uint64_t seq_count;
> +	uint64_t data_device_sectors;
>  	void *block_start;
>  	struct wc_entry *entries;
>  	unsigned block_size;
> @@ -969,6 +970,8 @@ static void writecache_resume(struct dm_
>  
>  	wc_lock(wc);
>  
> +	wc->data_device_sectors = i_size_read(wc->dev->bdev->bd_inode) >> SECTOR_SHIFT;
> +

I switched it to using bdev_nr_sectors() (and sector_t instead of uint64_t) instead.

>  	if (WC_MODE_PMEM(wc)) {
>  		persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
>  	} else {
> @@ -1638,6 +1641,10 @@ static bool wc_add_block(struct writebac
>  	void *address = memory_data(wc, e);
>  
>  	persistent_memory_flush_cache(address, block_size);
> +
> +	if (unlikely(wb->bio.bi_iter.bi_sector + bio_sectors(&wb->bio) >= wc->data_device_sectors))
> +		return true;
> +

I updated it to use bio_end_sector()

Otherwise looks good.

diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index d9c0d41e29f3..844c4be11768 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -148,7 +148,7 @@ struct dm_writecache {
        size_t metadata_sectors;
        size_t n_blocks;
        uint64_t seq_count;
-       uint64_t data_device_sectors;
+       sector_t data_device_sectors;
        void *block_start;
        struct wc_entry *entries;
        unsigned block_size;
@@ -978,7 +978,7 @@ static void writecache_resume(struct dm_target *ti)

        wc_lock(wc);

-       wc->data_device_sectors = i_size_read(wc->dev->bdev->bd_inode) >> SECTOR_SHIFT;
+       wc->data_device_sectors = bdev_nr_sectors(wc->dev->bdev);

        if (WC_MODE_PMEM(wc)) {
                persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
@@ -1650,7 +1650,7 @@ static bool wc_add_block(struct writeback_struct *wb, struct wc_entry *e, gfp_t

        persistent_memory_flush_cache(address, block_size);

-       if (unlikely(wb->bio.bi_iter.bi_sector + bio_sectors(&wb->bio) >= wc->data_device_sectors))
+       if (unlikely(bio_end_sector(&wb->bio) >= wc->data_device_sectors))
                return true;

        return bio_add_page(&wb->bio, persistent_memory_page(address),


BUT, it should be noted bdev_nr_sectors is pretty recent, introduced
with commit a782483cc1f8 ("block: remove the nr_sects field in struct
hd_struct").  SO using bdev_nr_sectors creates problems with stable at ... 
given that I'll revert back to open-coding it in the tsable@ patch and
then apply a quick change to use bdev_nr_sectors().

Mike




More information about the dm-devel mailing list