Commit 7b76ec11fec40203836b488496d2df082d5b2022
Committed by
Alasdair G Kergon
1 parent
a79245b3e5
Exists in
master
and in
7 other branches
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); |