Commit 9864cd5d authored by Damien Le Moal's avatar Damien Le Moal Committed by Mike Snitzer

dm: fix report zone remapping to account for partition offset

If dm-linear or dm-flakey are layered on top of a partition of a zoned
block device, remapping of the start sector and write pointer position
of the zones reported by a report zones BIO must be modified to account
for the target table entry mapping (start offset within the device and
entry mapping with the dm device).  If the target's backing device is a
partition of a whole disk, the start sector on the physical device of
the partition must also be accounted for when modifying the zone
information.  However, dm_remap_zone_report() was not considering this
last case, resulting in incorrect zone information remapping with
targets using disk partitions.

Fix this by calculating the target backing device start sector using
the position of the completed report zones BIO and the unchanged
position and size of the original report zone BIO. With this value
calculated, the start sector and write pointer position of the target
zones can be correctly remapped.

Fixes: 10999307 ("dm: introduce dm_remap_zone_report()")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent c7cd5550
...@@ -1155,12 +1155,14 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) ...@@ -1155,12 +1155,14 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
EXPORT_SYMBOL_GPL(dm_accept_partial_bio); EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
/* /*
* The zone descriptors obtained with a zone report indicate * The zone descriptors obtained with a zone report indicate zone positions
* zone positions within the target device. The zone descriptors * within the target backing device, regardless of that device is a partition
* must be remapped to match their position within the dm device. * and regardless of the target mapping start sector on the device or partition.
* A target may call dm_remap_zone_report after completion of a * The zone descriptors start sector and write pointer position must be adjusted
* REQ_OP_ZONE_REPORT bio to remap the zone descriptors obtained * to match their relative position within the dm device.
* from the target device mapping to the dm device. * A target may call dm_remap_zone_report() after completion of a
* REQ_OP_ZONE_REPORT bio to remap the zone descriptors obtained from the
* backing device.
*/ */
void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
{ {
...@@ -1171,6 +1173,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) ...@@ -1171,6 +1173,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
struct blk_zone *zone; struct blk_zone *zone;
unsigned int nr_rep = 0; unsigned int nr_rep = 0;
unsigned int ofst; unsigned int ofst;
sector_t part_offset;
struct bio_vec bvec; struct bio_vec bvec;
struct bvec_iter iter; struct bvec_iter iter;
void *addr; void *addr;
...@@ -1178,6 +1181,15 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) ...@@ -1178,6 +1181,15 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
if (bio->bi_status) if (bio->bi_status)
return; return;
/*
* bio sector was incremented by the request size on completion. Taking
* into account the original request sector, the target start offset on
* the backing device and the target mapping offset (ti->begin), the
* start sector of the backing device. The partition offset is always 0
* if the target uses a whole device.
*/
part_offset = bio->bi_iter.bi_sector + ti->begin - (start + bio_end_sector(report_bio));
/* /*
* Remap the start sector of the reported zones. For sequential zones, * Remap the start sector of the reported zones. For sequential zones,
* also remap the write pointer position. * also remap the write pointer position.
...@@ -1195,6 +1207,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) ...@@ -1195,6 +1207,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
/* Set zones start sector */ /* Set zones start sector */
while (hdr->nr_zones && ofst < bvec.bv_len) { while (hdr->nr_zones && ofst < bvec.bv_len) {
zone = addr + ofst; zone = addr + ofst;
zone->start -= part_offset;
if (zone->start >= start + ti->len) { if (zone->start >= start + ti->len) {
hdr->nr_zones = 0; hdr->nr_zones = 0;
break; break;
...@@ -1206,7 +1219,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) ...@@ -1206,7 +1219,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
else if (zone->cond == BLK_ZONE_COND_EMPTY) else if (zone->cond == BLK_ZONE_COND_EMPTY)
zone->wp = zone->start; zone->wp = zone->start;
else else
zone->wp = zone->wp + ti->begin - start; zone->wp = zone->wp + ti->begin - start - part_offset;
} }
ofst += sizeof(struct blk_zone); ofst += sizeof(struct blk_zone);
hdr->nr_zones--; hdr->nr_zones--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment