aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-stripe.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2013-05-10 09:37:14 -0400
committerAlasdair G Kergon <agk@redhat.com>2013-05-10 09:37:14 -0400
commitd793e684277124d55c5d2444007e224635821346 (patch)
treee4ce5af71082bdec32105a68c8405405273c1f90 /drivers/md/dm-stripe.c
parentebb37277796269da36a8bc5d72ed1e8e1fb7d34b (diff)
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 range f14fa69 ("dm stripe: fix size test") to eb850de ("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>
Diffstat (limited to 'drivers/md/dm-stripe.c')
-rw-r--r--drivers/md/dm-stripe.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index ea5e878a30b9..d907ca6227ce 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -94,7 +94,7 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
94static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) 94static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
95{ 95{
96 struct stripe_c *sc; 96 struct stripe_c *sc;
97 sector_t width; 97 sector_t width, tmp_len;
98 uint32_t stripes; 98 uint32_t stripes;
99 uint32_t chunk_size; 99 uint32_t chunk_size;
100 int r; 100 int r;
@@ -116,15 +116,16 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
116 } 116 }
117 117
118 width = ti->len; 118 width = ti->len;
119 if (sector_div(width, chunk_size)) { 119 if (sector_div(width, stripes)) {
120 ti->error = "Target length not divisible by " 120 ti->error = "Target length not divisible by "
121 "chunk size"; 121 "number of stripes";
122 return -EINVAL; 122 return -EINVAL;
123 } 123 }
124 124
125 if (sector_div(width, stripes)) { 125 tmp_len = width;
126 if (sector_div(tmp_len, chunk_size)) {
126 ti->error = "Target length not divisible by " 127 ti->error = "Target length not divisible by "
127 "number of stripes"; 128 "chunk size";
128 return -EINVAL; 129 return -EINVAL;
129 } 130 }
130 131