aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-12-28 19:14:23 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-12 11:29:28 -0800
commit0889c179651f57c6fdf4ed72e5027c5dcc90bda2 (patch)
tree6f1405d1f95b7e6cac3baede1dc09ba092b21269
parent688485273b3173d2fdb590ff916b55c581da6ed0 (diff)
downloadvexpress-lsk-0889c179651f57c6fdf4ed72e5027c5dcc90bda2.tar.gz
ore: fix BUG_ON, too few sgs when reading
commit 361aba569f55dd159b850489a3538253afbb3973 upstream. 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. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-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 894f3e192e6..49cf230554a 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,
/* first/last seg is split */
num_raid_units += layout->group_width;
- sgs_per_dev = div_u64(num_raid_units, data_devs);
+ sgs_per_dev = div_u64(num_raid_units, data_devs) + 2;
} else {
/* For Writes add parity pages array. */
max_par_pages = num_raid_units * pages_in_unit *
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index 29c47e5c4a8..414a2dfd950 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,
unsigned cur_len)
{
if (ios->reading) {
- BUG_ON(per_dev->cur_sg >= ios->sgs_per_dev);
+ if (per_dev->cur_sg >= ios->sgs_per_dev) {
+ ORE_DBGMSG("cur_sg(%d) >= sgs_per_dev(%d)\n" ,
+ per_dev->cur_sg, ios->sgs_per_dev);
+ return -ENOMEM;
+ }
_ore_add_sg_seg(per_dev, cur_len, true);
} else {
struct __stripe_pages_2d *sp2d = ios->sp2d;