From 05373156fbd495466e869be77cf394d37cea6379 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Thu, 21 Feb 2013 13:28:10 +1100 Subject: [PATCH] --- yaml --- r: 360739 b: refs/heads/master c: 9a3152ab024867100f2f50d124b998d05fb1c3f6 h: refs/heads/master i: 360737: 4cfccda6c5d2587dd62896c01ef71c3302b584fc 360735: c866dafdbb345bb19f038c929f0e5c6f23da61e6 v: v3 --- [refs] | 2 +- trunk/drivers/md/raid10.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index a9776257a0e2..becbf8e235ca 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 475901aff15841fb0a81e7546517407779a9b061 +refs/heads/master: 9a3152ab024867100f2f50d124b998d05fb1c3f6 diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 70b58b4bcf89..61ed150bd0cf 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -550,6 +550,13 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) sector_t stripe; int dev; int slot = 0; + int last_far_set_start, last_far_set_size; + + last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; + last_far_set_start *= geo->far_set_size; + + last_far_set_size = geo->far_set_size; + last_far_set_size += (geo->raid_disks % geo->far_set_size); /* now calculate first sector/dev */ chunk = r10bio->sector >> geo->chunk_shift; @@ -575,9 +582,16 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) for (f = 1; f < geo->far_copies; f++) { set = d / geo->far_set_size; d += geo->near_copies; - d %= geo->far_set_size; - d += geo->far_set_size * set; + if ((geo->raid_disks % geo->far_set_size) && + (d > last_far_set_start)) { + d -= last_far_set_start; + d %= last_far_set_size; + d += last_far_set_start; + } else { + d %= geo->far_set_size; + d += geo->far_set_size * set; + } s += geo->stride; r10bio->devs[slot].devnum = d; r10bio->devs[slot].addr = s; @@ -615,6 +629,18 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) struct geom *geo = &conf->geo; int far_set_start = (dev / geo->far_set_size) * geo->far_set_size; int far_set_size = geo->far_set_size; + int last_far_set_start; + + if (geo->raid_disks % geo->far_set_size) { + last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; + last_far_set_start *= geo->far_set_size; + + if (dev >= last_far_set_start) { + far_set_size = geo->far_set_size; + far_set_size += (geo->raid_disks % geo->far_set_size); + far_set_start = last_far_set_start; + } + } offset = sector & geo->chunk_mask; if (geo->far_offset) {