diff options
-rw-r--r-- | drivers/md/dm-stripe.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 6a20e9ea0bfb..9e8f4cc63d6c 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -31,6 +31,7 @@ struct stripe_c { | |||
31 | sector_t stripe_width; | 31 | sector_t stripe_width; |
32 | 32 | ||
33 | uint32_t chunk_size; | 33 | uint32_t chunk_size; |
34 | int chunk_size_shift; | ||
34 | 35 | ||
35 | /* Needed for handling events */ | 36 | /* Needed for handling events */ |
36 | struct dm_target *ti; | 37 | struct dm_target *ti; |
@@ -163,6 +164,10 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
163 | ti->num_discard_requests = stripes; | 164 | ti->num_discard_requests = stripes; |
164 | 165 | ||
165 | sc->chunk_size = chunk_size; | 166 | sc->chunk_size = chunk_size; |
167 | if (chunk_size & (chunk_size - 1)) | ||
168 | sc->chunk_size_shift = -1; | ||
169 | else | ||
170 | sc->chunk_size_shift = __ffs(chunk_size); | ||
166 | 171 | ||
167 | /* | 172 | /* |
168 | * Get the stripe destinations. | 173 | * Get the stripe destinations. |
@@ -202,7 +207,14 @@ static void stripe_map_sector(struct stripe_c *sc, sector_t sector, | |||
202 | uint32_t *stripe, sector_t *result) | 207 | uint32_t *stripe, sector_t *result) |
203 | { | 208 | { |
204 | sector_t chunk = dm_target_offset(sc->ti, sector); | 209 | sector_t chunk = dm_target_offset(sc->ti, sector); |
205 | sector_t chunk_offset = sector_div(chunk, sc->chunk_size); | 210 | sector_t chunk_offset; |
211 | |||
212 | if (sc->chunk_size_shift < 0) | ||
213 | chunk_offset = sector_div(chunk, sc->chunk_size); | ||
214 | else { | ||
215 | chunk_offset = chunk & (sc->chunk_size - 1); | ||
216 | chunk >>= sc->chunk_size_shift; | ||
217 | } | ||
206 | 218 | ||
207 | if (sc->stripes_shift < 0) | 219 | if (sc->stripes_shift < 0) |
208 | *stripe = sector_div(chunk, sc->stripes); | 220 | *stripe = sector_div(chunk, sc->stripes); |
@@ -211,7 +223,12 @@ static void stripe_map_sector(struct stripe_c *sc, sector_t sector, | |||
211 | chunk >>= sc->stripes_shift; | 223 | chunk >>= sc->stripes_shift; |
212 | } | 224 | } |
213 | 225 | ||
214 | *result = (chunk * sc->chunk_size) + chunk_offset; | 226 | if (sc->chunk_size_shift < 0) |
227 | chunk *= sc->chunk_size; | ||
228 | else | ||
229 | chunk <<= sc->chunk_size_shift; | ||
230 | |||
231 | *result = chunk + chunk_offset; | ||
215 | } | 232 | } |
216 | 233 | ||
217 | static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, | 234 | static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, |
@@ -225,7 +242,10 @@ static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, | |||
225 | 242 | ||
226 | /* round down */ | 243 | /* round down */ |
227 | sector = *result; | 244 | sector = *result; |
228 | *result -= sector_div(sector, sc->chunk_size); | 245 | if (sc->chunk_size_shift < 0) |
246 | *result -= sector_div(sector, sc->chunk_size); | ||
247 | else | ||
248 | *result = sector & ~(sector_t)(sc->chunk_size - 1); | ||
229 | 249 | ||
230 | if (target_stripe < stripe) | 250 | if (target_stripe < stripe) |
231 | *result += sc->chunk_size; /* next chunk */ | 251 | *result += sc->chunk_size; /* next chunk */ |