From 4f1f847dc0563d85b05decd5128741c1103d4035 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Sun, 1 Apr 2012 23:48:38 +1000 Subject: md: Avoid OOPS when reshaping raid1 to raid0 commit 24b961f811a3e790a9b93604d2594bfb6cce4fa4 upstream. raid1 arrays do not have the notion of chunk size. Calculate the largest chunk sector size we can use to avoid a divide by zero OOPS when aligning the size of the new array to the chunk size. Signed-off-by: Jes Sorensen Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid0.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 7294bd115e34..ce454f045d6e 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -609,6 +609,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev) static void *raid0_takeover_raid1(struct mddev *mddev) { struct r0conf *priv_conf; + int chunksect; /* Check layout: * - (N - 1) mirror drives must be already faulty @@ -619,10 +620,25 @@ static void *raid0_takeover_raid1(struct mddev *mddev) return ERR_PTR(-EINVAL); } + /* + * a raid1 doesn't have the notion of chunk size, so + * figure out the largest suitable size we can use. + */ + chunksect = 64 * 2; /* 64K by default */ + + /* The array must be an exact multiple of chunksize */ + while (chunksect && (mddev->array_sectors & (chunksect - 1))) + chunksect >>= 1; + + if ((chunksect << 9) < PAGE_SIZE) + /* array size does not allow a suitable chunk size */ + return ERR_PTR(-EINVAL); + /* Set new parameters */ mddev->new_level = 0; mddev->new_layout = 0; - mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ + mddev->new_chunk_sectors = chunksect; + mddev->chunk_sectors = chunksect; mddev->delta_disks = 1 - mddev->raid_disks; mddev->raid_disks = 1; /* make sure it will be not marked as dirty */ -- cgit v1.2.3