dm stripe: fix regression in stripe_width calculation
Fix a regression in the calculation of the stripe_width in the dm stripe target which led to incorrect processing of device limits. The stripe_width is the stripe device length divided by the number of stripes. The group of commits in the rangef14fa69
("dm stripe: fix size test") toeb850de
("dm stripe: support for non power of 2 chunksize") interfered with each other (a merging error) and led to the stripe_width being set incorrectly to the stripe device length divided by chunk_size * stripe_count. For example, a stripe device's table with: 0 33553920 striped 3 512 ... should result in a stripe_width of 11184640 (33553920 / 3), but due to the bug it was getting set to 21845 (33553920 / (512 * 3)). The impact of this bug is that device topologies that previously worked fine with the stripe target are no longer considered valid. In particular, there is a higher risk of seeing this issue if one of the stripe devices has a 4K logical block size. Resulting in an error message like this: "device-mapper: table: 253:4: len=21845 not aligned to h/w logical block size 4096 of dm-1" The fix is to swap the order of the divisions and to use a temporary variable for the second one, so that width retains the intended value. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@vger.kernel.org # 3.6+ Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
Родитель
ebb3727779
Коммит
d793e68427
|
@ -94,7 +94,7 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
|
|||
static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
{
|
||||
struct stripe_c *sc;
|
||||
sector_t width;
|
||||
sector_t width, tmp_len;
|
||||
uint32_t stripes;
|
||||
uint32_t chunk_size;
|
||||
int r;
|
||||
|
@ -116,18 +116,19 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
}
|
||||
|
||||
width = ti->len;
|
||||
if (sector_div(width, chunk_size)) {
|
||||
ti->error = "Target length not divisible by "
|
||||
"chunk size";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sector_div(width, stripes)) {
|
||||
ti->error = "Target length not divisible by "
|
||||
"number of stripes";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp_len = width;
|
||||
if (sector_div(tmp_len, chunk_size)) {
|
||||
ti->error = "Target length not divisible by "
|
||||
"chunk size";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we have enough arguments for that many stripes ?
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче