aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-stripe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-stripe.c')
-rw-r--r--drivers/md/dm-stripe.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 1559fdfd2073..c297f6da91ea 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -176,6 +176,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
176 176
177 ti->split_io = chunk_size; 177 ti->split_io = chunk_size;
178 ti->num_flush_requests = stripes; 178 ti->num_flush_requests = stripes;
179 ti->num_discard_requests = stripes;
179 180
180 sc->chunk_shift = ffs(chunk_size) - 1; 181 sc->chunk_shift = ffs(chunk_size) - 1;
181 sc->chunk_mask = ((sector_t) chunk_size) - 1; 182 sc->chunk_mask = ((sector_t) chunk_size) - 1;
@@ -230,6 +231,39 @@ static void stripe_map_sector(struct stripe_c *sc, sector_t sector,
230 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); 231 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask);
231} 232}
232 233
234static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector,
235 uint32_t target_stripe, sector_t *result)
236{
237 uint32_t stripe;
238
239 stripe_map_sector(sc, sector, &stripe, result);
240 if (stripe == target_stripe)
241 return;
242 *result &= ~sc->chunk_mask; /* round down */
243 if (target_stripe < stripe)
244 *result += sc->chunk_mask + 1; /* next chunk */
245}
246
247static int stripe_map_discard(struct stripe_c *sc, struct bio *bio,
248 uint32_t target_stripe)
249{
250 sector_t begin, end;
251
252 stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin);
253 stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio),
254 target_stripe, &end);
255 if (begin < end) {
256 bio->bi_bdev = sc->stripe[target_stripe].dev->bdev;
257 bio->bi_sector = begin + sc->stripe[target_stripe].physical_start;
258 bio->bi_size = to_bytes(end - begin);
259 return DM_MAPIO_REMAPPED;
260 } else {
261 /* The range doesn't map to the target stripe */
262 bio_endio(bio, 0);
263 return DM_MAPIO_SUBMITTED;
264 }
265}
266
233static int stripe_map(struct dm_target *ti, struct bio *bio, 267static int stripe_map(struct dm_target *ti, struct bio *bio,
234 union map_info *map_context) 268 union map_info *map_context)
235{ 269{
@@ -243,6 +277,11 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
243 bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; 277 bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
244 return DM_MAPIO_REMAPPED; 278 return DM_MAPIO_REMAPPED;
245 } 279 }
280 if (unlikely(bio->bi_rw & REQ_DISCARD)) {
281 target_request_nr = map_context->target_request_nr;
282 BUG_ON(target_request_nr >= sc->stripes);
283 return stripe_map_discard(sc, bio, target_request_nr);
284 }
246 285
247 stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); 286 stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector);
248 287