aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-stripe.c26
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
217static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, 234static 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 */