]> git.hungrycats.org Git - linux/commitdiff
md: Avoid OOPS when reshaping raid1 to raid0
authorJes Sorensen <Jes.Sorensen@redhat.com>
Sun, 1 Apr 2012 13:48:38 +0000 (23:48 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Jun 2012 07:15:55 +0000 (15:15 +0800)
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 <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/raid0.c

index 7294bd115e34ec1940a0b1f83c5610f029413289..ce454f045d6e822bb55ecfd930811d73f5040398 100644 (file)
@@ -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 */