Commit 7b76ec11fec40203836b488496d2df082d5b2022

Authored by Mikulas Patocka
Committed by Alasdair G Kergon
1 parent a79245b3e5

dm stripe: support discards

The DM core will submit a discard bio to the stripe target for each
stripe in a striped DM device.  The stripe target will determine
stripe-specific portions of the supplied bio to be remapped into
individual (at most 'num_discard_requests' extents).  If a given
stripe-specific discard bio doesn't touch a particular stripe the bio
will be dropped.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 1 changed file with 39 additions and 0 deletions Side-by-side Diff

drivers/md/dm-stripe.c
... ... @@ -176,6 +176,7 @@
176 176  
177 177 ti->split_io = chunk_size;
178 178 ti->num_flush_requests = stripes;
  179 + ti->num_discard_requests = stripes;
179 180  
180 181 sc->chunk_shift = ffs(chunk_size) - 1;
181 182 sc->chunk_mask = ((sector_t) chunk_size) - 1;
... ... @@ -230,6 +231,39 @@
230 231 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask);
231 232 }
232 233  
  234 +static 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 +
  247 +static 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 +
233 267 static int stripe_map(struct dm_target *ti, struct bio *bio,
234 268 union map_info *map_context)
235 269 {
... ... @@ -242,6 +276,11 @@
242 276 BUG_ON(target_request_nr >= sc->stripes);
243 277 bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
244 278 return DM_MAPIO_REMAPPED;
  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);
245 284 }
246 285  
247 286 stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector);