summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-12-28 17:14:23 (GMT)
committerBoaz Harrosh <bharrosh@panasas.com>2012-01-06 14:49:07 (GMT)
commit361aba569f55dd159b850489a3538253afbb3973 (patch)
treee5a71f53908a67d8873f1a58ae8d83c64b2fdd7f
parentffefb8eaa367e8a5c14f779233d9da1fbc23d164 (diff)
downloadlinux-361aba569f55dd159b850489a3538253afbb3973.tar.xz
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>
-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 894f3e1..49cf230 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 29c47e5..414a2df 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;