Skip to content

Commit c45e8bc

Browse files
committed
Merge tag 'for-5.7/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer: - Document DM integrity allow_discard feature that was added during 5.7 merge window. - Fix potential for DM writecache data corruption during DM table reloads. - Fix DM verity's FEC support's hash block number calculation in verity_fec_decode(). - Fix bio-based DM multipath crash due to use of stale copy of MPATHF_QUEUE_IO flag state in __map_bio(). * tag 'for-5.7/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm multipath: use updated MPATHF_QUEUE_IO on mapping for bio-based mpath dm verity fec: fix hash block number in verity_fec_decode dm writecache: fix data corruption when reloading the target dm integrity: document allow_discard option
2 parents 39e16d9 + 5686dee commit c45e8bc

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

Documentation/admin-guide/device-mapper/dm-integrity.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,15 @@ fix_padding
182182
space-efficient. If this option is not present, large padding is
183183
used - that is for compatibility with older kernels.
184184

185-
186-
The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can
187-
be changed when reloading the target (load an inactive table and swap the
188-
tables with suspend and resume). The other arguments should not be changed
189-
when reloading the target because the layout of disk data depend on them
190-
and the reloaded target would be non-functional.
185+
allow_discards
186+
Allow block discard requests (a.k.a. TRIM) for the integrity device.
187+
Discards are only allowed to devices using internal hash.
188+
189+
The journal mode (D/J), buffer_sectors, journal_watermark, commit_time and
190+
allow_discards can be changed when reloading the target (load an inactive
191+
table and swap the tables with suspend and resume). The other arguments
192+
should not be changed when reloading the target because the layout of disk
193+
data depend on them and the reloaded target would be non-functional.
191194

192195

193196
The layout of the formatted block device:

drivers/md/dm-mpath.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,10 +585,12 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
585585

586586
/* Do we need to select a new pgpath? */
587587
pgpath = READ_ONCE(m->current_pgpath);
588-
queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
589-
if (!pgpath || !queue_io)
588+
if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
590589
pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
591590

591+
/* MPATHF_QUEUE_IO might have been cleared by choose_pgpath. */
592+
queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
593+
592594
if ((pgpath && queue_io) ||
593595
(!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
594596
/* Queue for the daemon to resubmit */

drivers/md/dm-verity-fec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
435435
fio->level++;
436436

437437
if (type == DM_VERITY_BLOCK_TYPE_METADATA)
438-
block += v->data_blocks;
438+
block = block - v->hash_start + v->data_blocks;
439439

440440
/*
441441
* For RS(M, N), the continuous FEC data is divided into blocks of N

drivers/md/dm-writecache.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,24 @@ static int writecache_alloc_entries(struct dm_writecache *wc)
931931
return 0;
932932
}
933933

934+
static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors)
935+
{
936+
struct dm_io_region region;
937+
struct dm_io_request req;
938+
939+
region.bdev = wc->ssd_dev->bdev;
940+
region.sector = wc->start_sector;
941+
region.count = n_sectors;
942+
req.bi_op = REQ_OP_READ;
943+
req.bi_op_flags = REQ_SYNC;
944+
req.mem.type = DM_IO_VMA;
945+
req.mem.ptr.vma = (char *)wc->memory_map;
946+
req.client = wc->dm_io;
947+
req.notify.fn = NULL;
948+
949+
return dm_io(&req, 1, &region, NULL);
950+
}
951+
934952
static void writecache_resume(struct dm_target *ti)
935953
{
936954
struct dm_writecache *wc = ti->private;
@@ -941,8 +959,18 @@ static void writecache_resume(struct dm_target *ti)
941959

942960
wc_lock(wc);
943961

944-
if (WC_MODE_PMEM(wc))
962+
if (WC_MODE_PMEM(wc)) {
945963
persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
964+
} else {
965+
r = writecache_read_metadata(wc, wc->metadata_sectors);
966+
if (r) {
967+
size_t sb_entries_offset;
968+
writecache_error(wc, r, "unable to read metadata: %d", r);
969+
sb_entries_offset = offsetof(struct wc_memory_superblock, entries);
970+
memset((char *)wc->memory_map + sb_entries_offset, -1,
971+
(wc->metadata_sectors << SECTOR_SHIFT) - sb_entries_offset);
972+
}
973+
}
946974

947975
wc->tree = RB_ROOT;
948976
INIT_LIST_HEAD(&wc->lru);
@@ -2102,6 +2130,12 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
21022130
ti->error = "Invalid block size";
21032131
goto bad;
21042132
}
2133+
if (wc->block_size < bdev_logical_block_size(wc->dev->bdev) ||
2134+
wc->block_size < bdev_logical_block_size(wc->ssd_dev->bdev)) {
2135+
r = -EINVAL;
2136+
ti->error = "Block size is smaller than device logical block size";
2137+
goto bad;
2138+
}
21052139
wc->block_size_bits = __ffs(wc->block_size);
21062140

21072141
wc->max_writeback_jobs = MAX_WRITEBACK_JOBS;
@@ -2200,8 +2234,6 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
22002234
goto bad;
22012235
}
22022236
} else {
2203-
struct dm_io_region region;
2204-
struct dm_io_request req;
22052237
size_t n_blocks, n_metadata_blocks;
22062238
uint64_t n_bitmap_bits;
22072239

@@ -2258,19 +2290,9 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
22582290
goto bad;
22592291
}
22602292

2261-
region.bdev = wc->ssd_dev->bdev;
2262-
region.sector = wc->start_sector;
2263-
region.count = wc->metadata_sectors;
2264-
req.bi_op = REQ_OP_READ;
2265-
req.bi_op_flags = REQ_SYNC;
2266-
req.mem.type = DM_IO_VMA;
2267-
req.mem.ptr.vma = (char *)wc->memory_map;
2268-
req.client = wc->dm_io;
2269-
req.notify.fn = NULL;
2270-
2271-
r = dm_io(&req, 1, &region, NULL);
2293+
r = writecache_read_metadata(wc, wc->block_size >> SECTOR_SHIFT);
22722294
if (r) {
2273-
ti->error = "Unable to read metadata";
2295+
ti->error = "Unable to read first block of metadata";
22742296
goto bad;
22752297
}
22762298
}

0 commit comments

Comments
 (0)