[PATCH 2/2] mdadm: Disk removal support for Raid10->Raid0 takeover

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Until now Raid10->Raid0 takeover was possible only if all the mirrors
where removed before md starts the takover.
Now mdadm, when performing Raid10->raid0 takeover, will remove all
unwanted mirrors from the array before actual md takeover is called.

Signed-off-by: Maciej Trela <maciej.trela@xxxxxxxxx>
---
 Grow.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 97 insertions(+), 1 deletions(-)

diff --git a/Grow.c b/Grow.c
index ff04fc0..284d31d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -540,7 +540,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			"       Please use a newer kernel\n");
 		return 1;
 	}
-	sra = sysfs_read(fd, 0, GET_VERSION | GET_LEVEL);
+	sra = sysfs_read(fd, 0, GET_VERSION | GET_LEVEL | GET_DEVS | GET_STATE);
 	frozen = freeze_array(sra);
 	if (frozen < 0) {
 		fprintf(stderr, Name ": %s is performing resync/recovery and cannot"
@@ -586,6 +586,102 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			size = array.size;
 	}
 
+	/* ========= check for Raid10 -> Raid0 conversion ===============
+	 * current implemenation assumes that following conditions must be met:
+	 * - far_copies == 1
+	 * - near_copies == 2
+	 * - disks number must be even
+	 */
+	if (level == 0 && array.level == 10 &&
+	    array.layout == ((1 << 8) + 2) && !(array.raid_disks & 1)) {
+		mdu_disk_info_t *disks;
+		int max_disks = MD_SB_DISKS;
+		int nr_of_copies, in_sync, copies;
+		
+		st = super_by_fd(fd);
+		if (st != NULL)
+			max_disks = st->max_devs;
+
+		/* Prepare temporary disk table */
+		disks = malloc(max_disks * sizeof(mdu_disk_info_t));
+		if (!disks) {
+			fprintf(stderr, Name ": malloc failed: grow aborted\n");
+			rv = 1;
+			goto release;
+		}
+		for (d = 0; d < max_disks; d++) {
+			disks[d].state = (1<<MD_DISK_REMOVED);
+			disks[d].major = disks[d].minor = 0;
+			disks[d].number = disks[d].raid_disk = d;
+		}
+
+		/* initialize temporary disk table with current devices*/
+		for (sd = sra->devs; sd; sd = sd->next)
+			if ((sd->disk.raid_disk >= 0) &&
+			    (sd->disk.raid_disk < array.raid_disks))
+				disks[sd->disk.raid_disk] = sd->disk;
+
+		nr_of_copies = array.layout & 0xff;
+		in_sync = nr_of_copies;
+		copies = nr_of_copies;
+
+		/* Find devices that will be removed from the array */
+		for (d = 0; d < max_disks; d++) {
+			int i, remove_all = 0;
+
+			if (disks[d].state & (1<<MD_DISK_REMOVED))
+				continue;
+			if (!(disks[d].state & (1<<MD_DISK_SYNC)))
+				in_sync--;
+
+			copies--;
+			if (!copies) {
+				/* We reached end of "mirrored" set of devices */
+				if (!in_sync) {
+					/* The array is failed and cannot be reshaped */
+					free(disks);
+					return 1;
+				}
+
+				/* Now mark all disks to be removed as faulty
+				 * (leave only one in_sync disk) */
+				for (i = (d-nr_of_copies+1); i <= d; i++) {
+					if (remove_all) {
+						disks[i].state |= (1<<MD_DISK_FAULTY);
+						continue;
+					}
+					if (disks[i].state & (1<<MD_DISK_SYNC)) {
+						/* this will be the candidate for Raid 0,
+						 * leave it */
+						remove_all = 1;
+						continue;
+					} else {
+						/* this one will be removed */
+						disks[i].state |= (1<<MD_DISK_FAULTY);
+					}
+				}
+				/* update in_sync and copies for the next set of devices */
+				in_sync =  nr_of_copies;
+				copies = nr_of_copies;
+			}
+		}
+
+		/* Remove unwanted devices from the array */
+		for (sd = sra->devs; sd; sd = sd->next) {
+			d = sd->disk.raid_disk;
+			if (disks[d].state & (1<<MD_DISK_FAULTY)) {
+				sysfs_set_str(sra, sd, "state", "faulty");
+				sysfs_set_str(sra, sd, "slot", "none");
+				sysfs_set_str(sra, sd, "state", "remove");
+			}
+		}
+
+		if (disks) {
+			free(disks);
+			disks = NULL;
+		}
+	}
+
 	/* ======= set level =========== */
 	if (level != UnSet && level != array.level) {
 		/* Trying to change the level.

��.n��������+%������w��{.n�����{����w��ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f



[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux