md: allow array to be resized while bitmap is present.
authorNeilBrown <neilb@suse.de>
Tue, 22 May 2012 03:55:27 +0000 (13:55 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 22 May 2012 03:55:27 +0000 (13:55 +1000)
Now that bitmaps can be resized, we can allow an array to be resized
while the bitmap is present.

This only covers resizing that involves changing the effective size
of member devices, not resizing that changes the number of devices.

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c

index 9e2336fbbd314ac629b8531028e5fa3233094647..86adf4ac46cf79f45ae806761aaf8ab8828ae3b2 100644 (file)
@@ -6153,11 +6153,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
         */
        if (mddev->sync_thread)
                return -EBUSY;
-       if (mddev->bitmap)
-               /* Sorry, cannot grow a bitmap yet, just remove it,
-                * grow, and re-add.
-                */
-               return -EBUSY;
+
        rdev_for_each(rdev, mddev) {
                sector_t avail = rdev->sectors;
 
index 22cfc6660b188ffa6b2099783560e193b9d5f0f8..8e717bd518e7c712087748286175380a1078f550 100644 (file)
@@ -2752,9 +2752,16 @@ static int raid1_resize(struct mddev *mddev, sector_t sectors)
         * any io in the removed space completes, but it hardly seems
         * worth it.
         */
-       md_set_array_sectors(mddev, raid1_size(mddev, sectors, 0));
-       if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
+       sector_t newsize = raid1_size(mddev, sectors, 0);
+       if (mddev->external_size &&
+           mddev->array_sectors > newsize)
                return -EINVAL;
+       if (mddev->bitmap) {
+               int ret = bitmap_resize(mddev->bitmap, newsize, 0, 0);
+               if (ret)
+                       return ret;
+       }
+       md_set_array_sectors(mddev, newsize);
        set_capacity(mddev->gendisk, mddev->array_sectors);
        revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&
index fb9062b5022c7bb002700cdd003490f0dd5b67c4..8fe3aa469987ce98d932e6c2469b0778ace9c4a2 100644 (file)
@@ -3678,9 +3678,15 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
 
        oldsize = raid10_size(mddev, 0, 0);
        size = raid10_size(mddev, sectors, 0);
-       md_set_array_sectors(mddev, size);
-       if (mddev->array_sectors > size)
+       if (mddev->external_size &&
+           mddev->array_sectors > size)
                return -EINVAL;
+       if (mddev->bitmap) {
+               int ret = bitmap_resize(mddev->bitmap, size, 0, 0);
+               if (ret)
+                       return ret;
+       }
+       md_set_array_sectors(mddev, size);
        set_capacity(mddev->gendisk, mddev->array_sectors);
        revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&
index 7bfd59b313d756f67fe392b6d0bb020ab7098cf6..eab6168bb7f46fa5110369311de7dacdb732fa7a 100644 (file)
@@ -5503,12 +5503,18 @@ static int raid5_resize(struct mddev *mddev, sector_t sectors)
         * any io in the removed space completes, but it hardly seems
         * worth it.
         */
+       sector_t newsize;
        sectors &= ~((sector_t)mddev->chunk_sectors - 1);
-       md_set_array_sectors(mddev, raid5_size(mddev, sectors,
-                                              mddev->raid_disks));
-       if (mddev->array_sectors >
-           raid5_size(mddev, sectors, mddev->raid_disks))
+       newsize = raid5_size(mddev, sectors, mddev->raid_disks);
+       if (mddev->external_size &&
+           mddev->array_sectors > newsize)
                return -EINVAL;
+       if (mddev->bitmap) {
+               int ret = bitmap_resize(mddev->bitmap, sectors, 0, 0);
+               if (ret)
+                       return ret;
+       }
+       md_set_array_sectors(mddev, newsize);
        set_capacity(mddev->gendisk, mddev->array_sectors);
        revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&