From 061d7da34cb6a551219afb726b2ed66af83e72ca Mon Sep 17 00:00:00 2001
From: Lukasz Orlowski <lukasz.orlowski@intel.com>
Date: Sat, 22 Oct 2011 11:38:56 +1100
Subject: [PATCH 114/115] imsm: Moves metadata update code for spare
 activation to separate function

The metadata update code during spare activation is moved to a separate
function for clarity of code, as a prework for the next patch fixing
the bug.

Signed-off-by: Lukasz Orlowski <lukasz.orlowski@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 super-intel.c |  197 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 104 insertions(+), 93 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index dfa85aa..c8765a4 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6982,6 +6982,108 @@ error_disk_add:
 	return ret_val;
 }
 
+static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
+				       struct intel_super *super,	
+				       struct active_array *active_array)
+{
+	struct imsm_super *mpb = super->anchor;
+	struct imsm_dev *dev = get_imsm_dev(super, u->array);
+	struct imsm_map *map = get_imsm_map(dev, 0);
+	struct imsm_map *migr_map;
+	struct active_array *a;
+	struct imsm_disk *disk;
+	__u8 to_state;
+	struct dl *dl;
+	unsigned int found;
+	int failed;
+	int victim = get_imsm_disk_idx(dev, u->slot, -1);
+	int i;
+
+	for (dl = super->disks; dl; dl = dl->next)
+		if (dl == u->dl)
+			break;
+
+	if (!dl) {
+		fprintf(stderr, "error: imsm_activate_spare passed "
+			"an unknown disk (index: %d)\n",
+			u->dl->index);
+		return 0;
+	}
+
+	/* count failures (excluding rebuilds and the victim)
+	 * to determine map[0] state
+	 */
+	failed = 0;
+	for (i = 0; i < map->num_members; i++) {
+		if (i == u->slot)
+			continue;
+		disk = get_imsm_disk(super,
+				     get_imsm_disk_idx(dev, i, -1));
+		if (!disk || is_failed(disk))
+			failed++;
+	}
+
+	/* adding a pristine spare, assign a new index */
+	if (dl->index < 0) {
+		dl->index = super->anchor->num_disks;
+		super->anchor->num_disks++;
+	}
+	disk = &dl->disk;
+	disk->status |= CONFIGURED_DISK;
+	disk->status &= ~SPARE_DISK;
+
+	/* mark rebuild */
+	to_state = imsm_check_degraded(super, dev, failed);
+	map->map_state = IMSM_T_STATE_DEGRADED;
+	migrate(dev, super, to_state, MIGR_REBUILD);
+	migr_map = get_imsm_map(dev, 1);
+	set_imsm_ord_tbl_ent(map, u->slot, dl->index);
+	set_imsm_ord_tbl_ent(migr_map, u->slot,
+			     dl->index | IMSM_ORD_REBUILD);
+
+	/* update the family_num to mark a new container
+	 * generation, being careful to record the existing
+	 * family_num in orig_family_num to clean up after
+	 * earlier mdadm versions that neglected to set it.
+	 */
+	if (mpb->orig_family_num == 0)
+		mpb->orig_family_num = mpb->family_num;
+	mpb->family_num += super->random;
+
+	/* count arrays using the victim in the metadata */
+	found = 0;
+	for (a = active_array; a ; a = a->next) {
+		dev = get_imsm_dev(super, a->info.container_member);
+		map = get_imsm_map(dev, 0);
+
+		if (get_imsm_disk_slot(map, victim) >= 0)
+			found++;
+	}
+
+	/* delete the victim if it is no longer being
+	 * utilized anywhere
+	 */
+	if (!found) {
+		struct dl **dlp;
+
+		/* We know that 'manager' isn't touching anything,
+		 * so it is safe to delete
+		 */
+		for (dlp = &super->disks; *dlp; dlp = &(*dlp)->next)
+			if ((*dlp)->index == victim)
+				break;
+
+		/* victim may be on the missing list */
+		if (!*dlp)
+			for (dlp = &super->missing; *dlp;
+			     dlp = &(*dlp)->next)
+				if ((*dlp)->index == victim)
+					break;
+		imsm_delete(super, dlp, victim);
+	}
+
+	return 1;
+}
 
 static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
 						struct intel_super *super,
@@ -7276,99 +7378,8 @@ static void imsm_process_update(struct supertype *st,
 	}
 	case update_activate_spare: {
 		struct imsm_update_activate_spare *u = (void *) update->buf; 
-		struct imsm_dev *dev = get_imsm_dev(super, u->array);
-		struct imsm_map *map = get_imsm_map(dev, 0);
-		struct imsm_map *migr_map;
-		struct active_array *a;
-		struct imsm_disk *disk;
-		__u8 to_state;
-		struct dl *dl;
-		unsigned int found;
-		int failed;
-		int victim = get_imsm_disk_idx(dev, u->slot, -1);
-		int i;
-
-		for (dl = super->disks; dl; dl = dl->next)
-			if (dl == u->dl)
-				break;
-
-		if (!dl) {
-			fprintf(stderr, "error: imsm_activate_spare passed "
-				"an unknown disk (index: %d)\n",
-				u->dl->index);
-			return;
-		}
-
-		super->updates_pending++;
-		/* count failures (excluding rebuilds and the victim)
-		 * to determine map[0] state
-		 */
-		failed = 0;
-		for (i = 0; i < map->num_members; i++) {
-			if (i == u->slot)
-				continue;
-			disk = get_imsm_disk(super,
-					     get_imsm_disk_idx(dev, i, -1));
-			if (!disk || is_failed(disk))
-				failed++;
-		}
-
-		/* adding a pristine spare, assign a new index */
-		if (dl->index < 0) {
-			dl->index = super->anchor->num_disks;
-			super->anchor->num_disks++;
-		}
-		disk = &dl->disk;
-		disk->status |= CONFIGURED_DISK;
-		disk->status &= ~SPARE_DISK;
-
-		/* mark rebuild */
-		to_state = imsm_check_degraded(super, dev, failed);
-		map->map_state = IMSM_T_STATE_DEGRADED;
-		migrate(dev, super, to_state, MIGR_REBUILD);
-		migr_map = get_imsm_map(dev, 1);
-		set_imsm_ord_tbl_ent(map, u->slot, dl->index);
-		set_imsm_ord_tbl_ent(migr_map, u->slot, dl->index | IMSM_ORD_REBUILD);
-
-		/* update the family_num to mark a new container
-		 * generation, being careful to record the existing
-		 * family_num in orig_family_num to clean up after
-		 * earlier mdadm versions that neglected to set it.
-		 */
-		if (mpb->orig_family_num == 0)
-			mpb->orig_family_num = mpb->family_num;
-		mpb->family_num += super->random;
-
-		/* count arrays using the victim in the metadata */
-		found = 0;
-		for (a = st->arrays; a ; a = a->next) {
-			dev = get_imsm_dev(super, a->info.container_member);
-			map = get_imsm_map(dev, 0);
-
-			if (get_imsm_disk_slot(map, victim) >= 0)
-				found++;
-		}
-
-		/* delete the victim if it is no longer being
-		 * utilized anywhere
-		 */
-		if (!found) {
-			struct dl **dlp;
-
-			/* We know that 'manager' isn't touching anything,
-			 * so it is safe to delete
-			 */
-			for (dlp = &super->disks; *dlp; dlp = &(*dlp)->next)
-				if ((*dlp)->index == victim)
-					break;
-
-			/* victim may be on the missing list */
-			if (!*dlp)
-				for (dlp = &super->missing; *dlp; dlp = &(*dlp)->next)
-					if ((*dlp)->index == victim)
-						break;
-			imsm_delete(super, dlp, victim);
-		}
+		if (apply_update_activate_spare(u, super, st->arrays))
+			super->updates_pending++;
 		break;
 	}
 	case update_create_array: {
-- 
1.7.7

