aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-03-18 21:46:40 -0400
committerNeilBrown <neilb@suse.de>2012-03-18 21:46:40 -0400
commit006a09a0ae0a494473a8cd82c8d1d653e37e6663 (patch)
tree169c59f77ef89e1c7cfb727249d60de88370fe79 /drivers/md
parent6b740b8d79252f13bcb7e5d3c1d43157e78a81e7 (diff)
md/raid10 - support resizing some RAID10 arrays.
'resizing' an array in this context means making use of extra space that has become available in component devices, not adding new devices. It also includes shrinking the array to take up less space of component devices. This is not supported for array with a 'far' layout. However for 'near' and 'offset' layout arrays, adding and removing space at the end of the devices is easy to support, and this patch provides that support. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid10.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e4a66ab6b0fb..3540316886f2 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3436,6 +3436,43 @@ static void raid10_quiesce(struct mddev *mddev, int state)
3436 } 3436 }
3437} 3437}
3438 3438
3439static int raid10_resize(struct mddev *mddev, sector_t sectors)
3440{
3441 /* Resize of 'far' arrays is not supported.
3442 * For 'near' and 'offset' arrays we can set the
3443 * number of sectors used to be an appropriate multiple
3444 * of the chunk size.
3445 * For 'offset', this is far_copies*chunksize.
3446 * For 'near' the multiplier is the LCM of
3447 * near_copies and raid_disks.
3448 * So if far_copies > 1 && !far_offset, fail.
3449 * Else find LCM(raid_disks, near_copy)*far_copies and
3450 * multiply by chunk_size. Then round to this number.
3451 * This is mostly done by raid10_size()
3452 */
3453 struct r10conf *conf = mddev->private;
3454 sector_t oldsize, size;
3455
3456 if (conf->far_copies > 1 && !conf->far_offset)
3457 return -EINVAL;
3458
3459 oldsize = raid10_size(mddev, 0, 0);
3460 size = raid10_size(mddev, sectors, 0);
3461 md_set_array_sectors(mddev, size);
3462 if (mddev->array_sectors > size)
3463 return -EINVAL;
3464 set_capacity(mddev->gendisk, mddev->array_sectors);
3465 revalidate_disk(mddev->gendisk);
3466 if (sectors > mddev->dev_sectors &&
3467 mddev->recovery_cp > oldsize) {
3468 mddev->recovery_cp = oldsize;
3469 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
3470 }
3471 mddev->dev_sectors = sectors;
3472 mddev->resync_max_sectors = size;
3473 return 0;
3474}
3475
3439static void *raid10_takeover_raid0(struct mddev *mddev) 3476static void *raid10_takeover_raid0(struct mddev *mddev)
3440{ 3477{
3441 struct md_rdev *rdev; 3478 struct md_rdev *rdev;
@@ -3505,6 +3542,7 @@ static struct md_personality raid10_personality =
3505 .sync_request = sync_request, 3542 .sync_request = sync_request,
3506 .quiesce = raid10_quiesce, 3543 .quiesce = raid10_quiesce,
3507 .size = raid10_size, 3544 .size = raid10_size,
3545 .resize = raid10_resize,
3508 .takeover = raid10_takeover, 3546 .takeover = raid10_takeover,
3509}; 3547};
3510 3548