dm stripe: optimize sector division

Optimize sector division: If the number of stripes is a power of two,
we can do shift and mask instead of division.

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 c96053b7 65988525

+18 -5
+18 -5
drivers/md/dm-stripe.c
··· 25 25 26 26 struct stripe_c { 27 27 uint32_t stripes; 28 + int stripes_shift; 29 + sector_t stripes_mask; 28 30 29 31 /* The size of this target / num. stripes */ 30 32 sector_t stripe_width; ··· 164 162 165 163 /* Set pointer to dm target; used in trigger_event */ 166 164 sc->ti = ti; 167 - 168 165 sc->stripes = stripes; 169 166 sc->stripe_width = width; 167 + 168 + if (stripes & (stripes - 1)) 169 + sc->stripes_shift = -1; 170 + else { 171 + sc->stripes_shift = ffs(stripes) - 1; 172 + sc->stripes_mask = ((sector_t) stripes) - 1; 173 + } 174 + 170 175 ti->split_io = chunk_size; 171 176 ti->num_flush_requests = stripes; 172 177 178 + sc->chunk_shift = ffs(chunk_size) - 1; 173 179 sc->chunk_mask = ((sector_t) chunk_size) - 1; 174 - for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) 175 - chunk_size >>= 1; 176 - sc->chunk_shift--; 177 180 178 181 /* 179 182 * Get the stripe destinations. ··· 220 213 sector_t offset = dm_target_offset(sc->ti, sector); 221 214 sector_t chunk = offset >> sc->chunk_shift; 222 215 223 - *stripe = sector_div(chunk, sc->stripes); 216 + if (sc->stripes_shift < 0) 217 + *stripe = sector_div(chunk, sc->stripes); 218 + else { 219 + *stripe = chunk & sc->stripes_mask; 220 + chunk >>= sc->stripes_shift; 221 + } 222 + 224 223 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); 225 224 } 226 225