aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-12-28 12:14:23 -0500
committerBoaz Harrosh <bharrosh@panasas.com>2012-01-06 09:49:07 -0500
commit361aba569f55dd159b850489a3538253afbb3973 (patch)
treee5a71f53908a67d8873f1a58ae8d83c64b2fdd7f /fs/exofs
parentffefb8eaa367e8a5c14f779233d9da1fbc23d164 (diff)
ore: fix BUG_ON, too few sgs when reading
When reading RAID5 files, in rare cases, we calculated too few sg segments. There should be two extra for the beginning and end partial units. Also "too few sg segments" should not be a BUG_ON there is all the mechanics in place to handle it, as a short read. So just return -ENOMEM and the rest of the code will gracefully split the IO. [Bug in 3.2.0 Kernel] CC: Stable Tree <stable@kernel.org> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs')
-rw-r--r--fs/exofs/ore.c2
-rw-r--r--fs/exofs/ore_raid.c6
2 files changed, 6 insertions, 2 deletions
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
index 894f3e192e6b..49cf230554a2 100644
--- a/fs/exofs/ore.c
+++ b/fs/exofs/ore.c
@@ -266,7 +266,7 @@ int ore_get_rw_state(struct ore_layout *layout, struct ore_components *oc,
266 266
267 /* first/last seg is split */ 267 /* first/last seg is split */
268 num_raid_units += layout->group_width; 268 num_raid_units += layout->group_width;
269 sgs_per_dev = div_u64(num_raid_units, data_devs); 269 sgs_per_dev = div_u64(num_raid_units, data_devs) + 2;
270 } else { 270 } else {
271 /* For Writes add parity pages array. */ 271 /* For Writes add parity pages array. */
272 max_par_pages = num_raid_units * pages_in_unit * 272 max_par_pages = num_raid_units * pages_in_unit *
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index 29c47e5c4a86..414a2dfd9500 100644
--- a/fs/exofs/ore_raid.c
+++ b/fs/exofs/ore_raid.c
@@ -551,7 +551,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
551 unsigned cur_len) 551 unsigned cur_len)
552{ 552{
553 if (ios->reading) { 553 if (ios->reading) {
554 BUG_ON(per_dev->cur_sg >= ios->sgs_per_dev); 554 if (per_dev->cur_sg >= ios->sgs_per_dev) {
555 ORE_DBGMSG("cur_sg(%d) >= sgs_per_dev(%d)\n" ,
556 per_dev->cur_sg, ios->sgs_per_dev);
557 return -ENOMEM;
558 }
555 _ore_add_sg_seg(per_dev, cur_len, true); 559 _ore_add_sg_seg(per_dev, cur_len, true);
556 } else { 560 } else {
557 struct __stripe_pages_2d *sp2d = ios->sp2d; 561 struct __stripe_pages_2d *sp2d = ios->sp2d;