[PATCH 09/23] imsm: update metadata implementation for update_grow_array

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

 



(Online Capacity Expansion for IMSM)
When mdadm post update uptate_grow_array mdmon has to perform 3 operations:
1. In prepare_update() calculate new anchor size in the way that greater disks
   number will fit allocated area. This is done by setting new value of len variable.
2. In process_update() device configuration prepared by mdadm is copied
   in to mdmon, and metadata update is triggered.
3. In process_update() general migration is started.

Signed-off-by: Adam Kwolek <adam.kwolek@xxxxxxxxx>
---

 super-intel.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 123 insertions(+), 1 deletions(-)

diff --git a/super-intel.c b/super-intel.c index b4a1f14..2f3c02d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5167,7 +5167,6 @@ int imsm_grow_array(struct active_array *a,  int new_raid_disks)
 		 * metadata
 		 */
 		di->disk.number = dl->index;
-
 		dl->disk.status |= CONFIGURED_DISK;
 		dl->disk.status &= ~SPARE_DISK;
 
@@ -5341,6 +5340,108 @@ static void imsm_process_update(struct supertype *st,
 		break;
 	}
 	case update_grow_array: {
+		/* every update is valid for adding single disk only
+		 * if you want to add mmore disks, post update list
+		 */
+		struct imsm_update_grow_array *u = (void *)update->buf;
+		struct imsm_dev *dev = NULL;
+		struct imsm_dev *dev_new = NULL;
+		struct imsm_map *map = NULL;
+		struct imsm_map *migr_map = NULL;
+		struct imsm_map *migr_map_src = NULL;
+		struct dl *dl = NULL;
+		__u8 to_state;
+		int hdd_count = 0;
+		struct active_array *a = NULL;
+		int slot;
+		int update_grow_array_status = -1;
+
+		slot = u->slot;
+		if (u->reshape_delta_disks <= 0) {
+			fprintf(stderr, "error:(imsm) "\
+				"Wrong update is passed\n");
+			goto update_grow_array_exit;
+		}
+
+		/* get active array that update applies to
+		 */
+		for (a = st->arrays; a; a = a->next) {
+			if (a->devnum == u->devnum)
+				break;
+		}
+
+		if (a == NULL) {
+			fprintf(stderr, "error:(imsm) "\
+				"Cannot find requested array\n");
+			goto update_grow_array_exit;
+		}
+
+		dev = get_imsm_dev(super, a->info.container_member);
+		if (dev == NULL) {
+			fprintf(stderr, "error:(imsm) "\
+				"Cannot find requested device\n");
+			goto update_grow_array_exit;
+		}
+
+		/* get map
+		 */
+		map = get_imsm_map(&u->dev, 0);
+		if (map == NULL) {
+			fprintf(stderr,
+				"error:(imsm) "\
+				"Invalid map for requested device.\n");
+			goto update_grow_array_exit;
+		}
+
+		/* count HDDs
+		 */
+		for (dl = super->disks; dl; dl = dl->next) {
+			if (dl->index >= 0)
+				hdd_count++;
+		}
+		if (hdd_count > map->num_members) {
+			fprintf(stderr, "error:(imsm) "\
+				"Received update doesn't match raid configuration\n");
+			goto update_grow_array_exit;
+		}
+
+		dev_new = &u->dev;
+		/* verify new device
+		 */
+		migr_map = get_imsm_map(dev_new, 1);
+		if (migr_map == NULL) {
+			fprintf(stderr, "error:(imsm) "\
+				"Received update has corrupted device\n");
+			goto update_grow_array_exit;
+		}
+
+		/* it seams that everything is ok, copy device
+		 * new size has to be reserved in managemon during
+		 * grow detection
+		 */
+		memcpy(dev, dev_new, sizeof_imsm_dev(dev_new, 1));
+		/* get migration map and backup it
+		 */
+		map = get_imsm_map(dev, 0);
+
+		/* set migration/ no migration in progress */
+		to_state = imsm_check_degraded(super, dev, 0);
+		migrate(dev, to_state, MIGR_GEN_MIGR);
+		migr_map = get_imsm_map(dev, 1);
+		/* get source map
+		 */
+		migr_map_src = get_imsm_map(dev_new, 1);
+		memcpy(migr_map, migr_map_src, sizeof_imsm_map(migr_map_src));
+
+		super->updates_pending++;
+
+		/* operatio succed - no exit with error
+		 */
+		update_grow_array_status = 1;
+
+update_grow_array_exit:
+		if (update_grow_array_status < 0)
+			return;
 		break;
 	}
 	case update_activate_spare: {
@@ -5619,6 +5720,27 @@ static void imsm_prepare_update(struct supertype *st,
 		break;
 	}
 	case update_grow_array: {
+		struct imsm_update_grow_array *u = (void *) update->buf;
+		struct imsm_dev *dev = &u->dev;
+		struct imsm_map *map = get_imsm_map(dev, 1);
+
+		dprintf("prepare_update(): update_grow_array\n");
+
+		if (u->reshape_delta_disks <= 0)
+			break;
+
+		/* add place for device in device list
+		 */
+		len += u->reshape_delta_disks * sizeof(struct imsm_disk);
+
+		/* add place in first map
+		 */
+		len += u->reshape_delta_disks * sizeof(__u32);
+
+		/* add second map
+		 */
+		len += sizeof(struct imsm_map) + (map->num_members - 1) * 
+sizeof(__u32);
+
 		break;
 	}
 	case update_create_array: {

��.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