Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ea9c07c authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[PATCH] md: cause md/raid1 to "repack" working devices when number of drives is changed



i.e.  missing or failed drives are moved to the end of the list.  The means
a 3 drive md array with the first drive missing can be shrunk to a two
drive array.  Currently that isn't possible.

Also, the "last_used" device number might be out-of-range after the number
of devices is reduced, so we set it to 0.

Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 58a60643
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -1349,17 +1349,26 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
	 * We allocate a new r1bio_pool if we can.
	 * Then raise a device barrier and wait until all IO stops.
	 * Then resize conf->mirrors and swap in the new r1bio pool.
	 *
	 * At the same time, we "pack" the devices so that all the missing
	 * devices have the higher raid_disk numbers.
	 */
	mempool_t *newpool, *oldpool;
	struct pool_info *newpoolinfo;
	mirror_info_t *newmirrors;
	conf_t *conf = mddev_to_conf(mddev);
	int cnt;

	int d;
	int d, d2;

	for (d= raid_disks; d < conf->raid_disks; d++)
	if (raid_disks < conf->raid_disks) {
		cnt=0;
		for (d= 0; d < conf->raid_disks; d++)
			if (conf->mirrors[d].rdev)
				cnt++;
		if (cnt > raid_disks)
			return -EBUSY;
	}

	newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
	if (!newpoolinfo)
@@ -1390,8 +1399,12 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
	/* ok, everything is stopped */
	oldpool = conf->r1bio_pool;
	conf->r1bio_pool = newpool;
	for (d=0; d < raid_disks && d < conf->raid_disks; d++)
		newmirrors[d] = conf->mirrors[d];

	for (d=d2=0; d < conf->raid_disks; d++)
		if (conf->mirrors[d].rdev) {
			conf->mirrors[d].rdev->raid_disk = d2;
			newmirrors[d2++].rdev = conf->mirrors[d].rdev;
		}
	kfree(conf->mirrors);
	conf->mirrors = newmirrors;
	kfree(conf->poolinfo);
@@ -1400,6 +1413,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
	mddev->degraded += (raid_disks - conf->raid_disks);
	conf->raid_disks = mddev->raid_disks = raid_disks;

	conf->last_used = 0; /* just make sure it is in-range */
	spin_lock_irq(&conf->resync_lock);
	conf->barrier--;
	spin_unlock_irq(&conf->resync_lock);