aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 20f7e4ef5342..45abb54037fc 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1155,12 +1155,14 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
1155EXPORT_SYMBOL_GPL(dm_accept_partial_bio); 1155EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
1156 1156
1157/* 1157/*
1158 * The zone descriptors obtained with a zone report indicate 1158 * The zone descriptors obtained with a zone report indicate zone positions
1159 * zone positions within the target device. The zone descriptors 1159 * within the target backing device, regardless of that device is a partition
1160 * must be remapped to match their position within the dm device. 1160 * and regardless of the target mapping start sector on the device or partition.
1161 * A target may call dm_remap_zone_report after completion of a 1161 * The zone descriptors start sector and write pointer position must be adjusted
1162 * REQ_OP_ZONE_REPORT bio to remap the zone descriptors obtained 1162 * to match their relative position within the dm device.
1163 * from the target device mapping to the dm device. 1163 * A target may call dm_remap_zone_report() after completion of a
1164 * REQ_OP_ZONE_REPORT bio to remap the zone descriptors obtained from the
1165 * backing device.
1164 */ 1166 */
1165void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start) 1167void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
1166{ 1168{
@@ -1171,6 +1173,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
1171 struct blk_zone *zone; 1173 struct blk_zone *zone;
1172 unsigned int nr_rep = 0; 1174 unsigned int nr_rep = 0;
1173 unsigned int ofst; 1175 unsigned int ofst;
1176 sector_t part_offset;
1174 struct bio_vec bvec; 1177 struct bio_vec bvec;
1175 struct bvec_iter iter; 1178 struct bvec_iter iter;
1176 void *addr; 1179 void *addr;
@@ -1179,6 +1182,15 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
1179 return; 1182 return;
1180 1183
1181 /* 1184 /*
1185 * bio sector was incremented by the request size on completion. Taking
1186 * into account the original request sector, the target start offset on
1187 * the backing device and the target mapping offset (ti->begin), the
1188 * start sector of the backing device. The partition offset is always 0
1189 * if the target uses a whole device.
1190 */
1191 part_offset = bio->bi_iter.bi_sector + ti->begin - (start + bio_end_sector(report_bio));
1192
1193 /*
1182 * Remap the start sector of the reported zones. For sequential zones, 1194 * Remap the start sector of the reported zones. For sequential zones,
1183 * also remap the write pointer position. 1195 * also remap the write pointer position.
1184 */ 1196 */
@@ -1195,6 +1207,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
1195 /* Set zones start sector */ 1207 /* Set zones start sector */
1196 while (hdr->nr_zones && ofst < bvec.bv_len) { 1208 while (hdr->nr_zones && ofst < bvec.bv_len) {
1197 zone = addr + ofst; 1209 zone = addr + ofst;
1210 zone->start -= part_offset;
1198 if (zone->start >= start + ti->len) { 1211 if (zone->start >= start + ti->len) {
1199 hdr->nr_zones = 0; 1212 hdr->nr_zones = 0;
1200 break; 1213 break;
@@ -1206,7 +1219,7 @@ void dm_remap_zone_report(struct dm_target *ti, struct bio *bio, sector_t start)
1206 else if (zone->cond == BLK_ZONE_COND_EMPTY) 1219 else if (zone->cond == BLK_ZONE_COND_EMPTY)
1207 zone->wp = zone->start; 1220 zone->wp = zone->start;
1208 else 1221 else
1209 zone->wp = zone->wp + ti->begin - start; 1222 zone->wp = zone->wp + ti->begin - start - part_offset;
1210 } 1223 }
1211 ofst += sizeof(struct blk_zone); 1224 ofst += sizeof(struct blk_zone);
1212 hdr->nr_zones--; 1225 hdr->nr_zones--;