[PATCH 02/31] 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 takeover.
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>
Signed-off-by: Adam Kwolek <adam.kwolek@xxxxxxxxx>
---

 mdadm/mdadm/Grow.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/mdadm/mdadm/Grow.c b/mdadm/mdadm/Grow.c index 1054979..3721c9c 100644
--- a/mdadm/mdadm/Grow.c
+++ b/mdadm/mdadm/Grow.c
@@ -821,7 +821,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 			st->update_tail = &st->updates;
 	}
 
-	sra = sysfs_read(fd, 0, GET_VERSION | GET_LEVEL);
+	sra = sysfs_read(fd, 0, GET_VERSION | GET_LEVEL | GET_DEVS | 
+GET_STATE);
 	if (sra) {
 		if (st->ss->external && st->subarray[0] == 0) {
 			array.level = LEVEL_CONTAINER;
@@ -892,6 +892,76 @@ 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)) {
+		int max_disks;
+		int nr_of_copies, in_sync, copies;
+		struct mdinfo info;
+		struct mdinfo *sd_temp;
+
+		info.array.raid_disks = MD_SB_DISKS;
+		st->ss->getinfo_super(st, &info);
+		max_disks = info.array.raid_disks;
+
+		nr_of_copies = array.layout & 0xff;
+		in_sync = nr_of_copies;
+		copies = nr_of_copies;
+
+		/* Find devices that will be removed from the array */
+		d = 0;
+		sd_temp = sra->devs;
+		for (sd = sra->devs; sd; sd = sd->next, d++) {
+			int i, remove_all = 0;
+
+			if (sd->disk.state & (1<<MD_DISK_REMOVED))
+				continue;
+			if (!(sd->disk.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 */
+					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++, sd_temp = sd_temp->next) {
+					if (sd_temp == NULL) {
+						/* error, array is wrong built
+						 */
+						return 1;
+					}
+					if ((sd_temp->disk.state & (1<<MD_DISK_SYNC)) &&
+					    (remove_all == 0)) {
+						/* this will be the candidate for Raid 0,
+						 * leave it */
+						remove_all = 1;
+						continue;
+					} else {
+						/* this one will be removed */
+						sysfs_set_str(sra, sd_temp, "state", "faulty");
+						sysfs_set_str(sra, sd_temp, "slot", "none");
+						sysfs_set_str(sra, sd_temp, "state", "remove");
+
+					}
+				}
+				/* update in_sync and copies for the next set of devices */
+				in_sync =  nr_of_copies;
+				copies = nr_of_copies;
+				sd_temp = sd->next;
+			}
+		}
+	}
+
 	/* ======= set level =========== */
 	if (level != UnSet && level != array.level) {
 		/* Trying to change the level.

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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