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 <[email protected]>
Cc: [email protected]

---
 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;
+
        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;
+
        return bio_add_page(&wb->bio, persistent_memory_page(address),
                            block_size, persistent_memory_page_offset(address)) 
!= 0;
 }
@@ -1709,6 +1716,9 @@ static void __writecache_writeback_pmem(
                if (writecache_has_error(wc)) {
                        bio->bi_status = BLK_STS_IOERR;
                        bio_endio(bio);
+               } else if (unlikely(!bio_sectors(bio))) {
+                       bio->bi_status = BLK_STS_OK;
+                       bio_endio(bio);
                } else {
                        submit_bio(bio);
                }
@@ -1752,6 +1762,14 @@ static void __writecache_writeback_ssd(s
                        e = f;
                }
 
+               if (unlikely(to.sector + to.count > wc->data_device_sectors)) {
+                       if (to.sector >= wc->data_device_sectors) {
+                               writecache_copy_endio(0, 0, c);
+                               continue;
+                       }
+                       from.count = to.count = wc->data_device_sectors - 
to.sector;
+               }
+
                dm_kcopyd_copy(wc->dm_kcopyd, &from, 1, &to, 0, 
writecache_copy_endio, c);
 
                __writeback_throttle(wc, wbl);

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to