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>

authored by Mikulas Patocka and committed by Alasdair G Kergon 7b76ec11 a79245b3

+39
+39
drivers/md/dm-stripe.c
··· 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; ··· 231 230 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); 232 231 } 233 232 233 + static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, 234 + uint32_t target_stripe, sector_t *result) 235 + { 236 + uint32_t stripe; 237 + 238 + stripe_map_sector(sc, sector, &stripe, result); 239 + if (stripe == target_stripe) 240 + return; 241 + *result &= ~sc->chunk_mask; /* round down */ 242 + if (target_stripe < stripe) 243 + *result += sc->chunk_mask + 1; /* next chunk */ 244 + } 245 + 246 + static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, 247 + uint32_t target_stripe) 248 + { 249 + sector_t begin, end; 250 + 251 + stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin); 252 + stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio), 253 + target_stripe, &end); 254 + if (begin < end) { 255 + bio->bi_bdev = sc->stripe[target_stripe].dev->bdev; 256 + bio->bi_sector = begin + sc->stripe[target_stripe].physical_start; 257 + bio->bi_size = to_bytes(end - begin); 258 + return DM_MAPIO_REMAPPED; 259 + } else { 260 + /* The range doesn't map to the target stripe */ 261 + bio_endio(bio, 0); 262 + return DM_MAPIO_SUBMITTED; 263 + } 264 + } 265 + 234 266 static int stripe_map(struct dm_target *ti, struct bio *bio, 235 267 union map_info *map_context) 236 268 { ··· 276 242 BUG_ON(target_request_nr >= sc->stripes); 277 243 bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; 278 244 return DM_MAPIO_REMAPPED; 245 + } 246 + if (unlikely(bio->bi_rw & REQ_DISCARD)) { 247 + target_request_nr = map_context->target_request_nr; 248 + BUG_ON(target_request_nr >= sc->stripes); 249 + return stripe_map_discard(sc, bio, target_request_nr); 279 250 } 280 251 281 252 stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector);