浏览代码

md: allow array to be resized while bitmap is present.

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>
NeilBrown 13 年之前
父节点
当前提交
a4a6125a07
共有 4 个文件被更改,包括 28 次插入13 次删除
  1. 1 5
      drivers/md/md.c
  2. 9 2
      drivers/md/raid1.c
  3. 8 2
      drivers/md/raid10.c
  4. 10 4
      drivers/md/raid5.c

+ 1 - 5
drivers/md/md.c

@@ -6153,11 +6153,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
 	 */
 	 */
 	if (mddev->sync_thread)
 	if (mddev->sync_thread)
 		return -EBUSY;
 		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) {
 	rdev_for_each(rdev, mddev) {
 		sector_t avail = rdev->sectors;
 		sector_t avail = rdev->sectors;
 
 

+ 9 - 2
drivers/md/raid1.c

@@ -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
 	 * any io in the removed space completes, but it hardly seems
 	 * worth it.
 	 * 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;
 		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);
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	revalidate_disk(mddev->gendisk);
 	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors &&
 	if (sectors > mddev->dev_sectors &&

+ 8 - 2
drivers/md/raid10.c

@@ -3678,9 +3678,15 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)
 
 
 	oldsize = raid10_size(mddev, 0, 0);
 	oldsize = raid10_size(mddev, 0, 0);
 	size = raid10_size(mddev, sectors, 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;
 		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);
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	revalidate_disk(mddev->gendisk);
 	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors &&
 	if (sectors > mddev->dev_sectors &&

+ 10 - 4
drivers/md/raid5.c

@@ -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
 	 * any io in the removed space completes, but it hardly seems
 	 * worth it.
 	 * worth it.
 	 */
 	 */
+	sector_t newsize;
 	sectors &= ~((sector_t)mddev->chunk_sectors - 1);
 	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;
 		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);
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	revalidate_disk(mddev->gendisk);
 	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors &&
 	if (sectors > mddev->dev_sectors &&