For this update prepare_update() allocates memory to relink imsm (bigger) device imsm structures. It calculates new /bigger/ anchor size. Process update applies update in to imsm structures. If necessary for first array in container it turns spares in to raid disks in metadata. active_array receives information about number of added devices (reshape_delta_disks) state_of_array is turned in to reshape_is_starting (this triggers managemon action) Signed-off-by: Adam Kwolek <adam.kwolek@xxxxxxxxx> --- super-intel.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 156 insertions(+), 0 deletions(-) diff --git a/super-intel.c b/super-intel.c index 183b82c..48e26b1 100644 --- a/super-intel.c +++ b/super-intel.c @@ -5310,6 +5310,111 @@ static void imsm_process_update(struct supertype *st, switch (type) { case update_reshape: { + struct imsm_update_reshape *u = (void *)update->buf; + struct dl *new_disk; + struct active_array *a; + int i; + __u32 new_mpb_size; + int new_disk_num; + struct intel_dev *current_dev; + + dprintf("imsm: imsm_process_update() for update_reshape "\ + "[u->update_prepared = %i]\n", + u->update_prepared); + if ((u->update_prepared == -1) || + (u->devnum < 0)) { + dprintf("imsm: Error: update_reshape not prepared\n"); + goto update_reshape_exit; + } + + if (u->spares_in_update) { + new_disk_num = mpb->num_disks + u->reshape_delta_disks; + new_mpb_size = disks_to_mpb_size(new_disk_num); + if (mpb->mpb_size < new_mpb_size) + mpb->mpb_size = new_mpb_size; + + /* enable spares to use in array + */ + for (i = 0; i < u->reshape_delta_disks; i++) { + char buf[PATH_MAX]; + + new_disk = super->disks; + while (new_disk) { + if ((new_disk->major == + u->upd_disks[i].major) && + (new_disk->minor == + u->upd_disks[i].minor)) + break; + new_disk = new_disk->next; + } + if (new_disk == NULL) { + u->update_prepared = -1; + goto update_reshape_exit; + } + if (new_disk->index < 0) { + new_disk->index = i + mpb->num_disks; + /* slot to fill in autolayout */ + new_disk->raiddisk = new_disk->index; + new_disk->disk.status |= + CONFIGURED_DISK; + new_disk->disk.status &= ~SPARE_DISK; + } + sprintf(buf, + "%d:%d", + new_disk->major, + new_disk->minor); + if (new_disk->fd < 0) + new_disk->fd = dev_open(buf, O_RDWR); + fd2devname(new_disk->fd , buf); + new_disk->devname = strdup(buf); + } + } + + dprintf("imsm: process_update(): update_reshape: volume set"\ + " mpb->num_raid_devs = %i\n", mpb->num_raid_devs); + /* manage changes in volumes + */ + /* check if array is in RESHAPE_NOT_ACTIVE reshape state + */ + for (a = st->arrays; a; a = a->next) + if (a->devnum == u->devnum) + break; + if ((a == NULL) || (a->reshape_state != reshape_not_active)) { + u->update_prepared = -1; + goto update_reshape_exit; + } + /* find current dev in intel_super + */ + dprintf("\t\tLooking for volume %s\n", + (char *)u->devs_mem.dev->volume); + current_dev = super->devlist; + while (current_dev) { + if (strcmp((char *)current_dev->dev->volume, + (char *)u->devs_mem.dev->volume) == 0) + break; + current_dev = current_dev->next; + } + if (current_dev == NULL) { + u->update_prepared = -1; + goto update_reshape_exit; + } + + dprintf("Found volume %s\n", (char *)current_dev->dev->volume); + /* replace current device with provided in update + */ + free(current_dev->dev); + current_dev->dev = u->devs_mem.dev; + u->devs_mem.dev = NULL; + + /* set reshape_delta_disks + */ + a->reshape_delta_disks = u->reshape_delta_disks; + a->reshape_state = reshape_is_starting; + + super->updates_pending++; +update_reshape_exit: + if (u->devs_mem.dev) + free(u->devs_mem.dev); break; } case update_activate_spare: { @@ -5632,6 +5737,57 @@ static void imsm_prepare_update(struct supertype *st, switch (type) { case update_reshape: { + struct imsm_update_reshape *u = (void *)update->buf; + struct dl *dl = NULL; + void *upd_devs; + + u->update_prepared = -1; + u->devs_mem.dev = NULL; + dprintf("imsm: imsm_prepare_update() for update_reshape\n"); + if (u->devnum < 0) { + dprintf("imsm: No passed device.\n"); + break; + } + dprintf("imsm: reshape delta disks is = %i\n", + u->reshape_delta_disks); + if (u->reshape_delta_disks < 0) + break; + u->update_prepared = 1; + if (u->reshape_delta_disks == 0) { + /* for non growing reshape buffers sizes + * are not affected but check some parameters + */ + break; + } + /* count HDDs + */ + u->disks_count = 0; + for (dl = super->disks; dl; dl = dl->next) + if (dl->index >= 0) + u->disks_count++; + + /* set pointer in monitor address space + */ + upd_devs = (struct imsm_dev *)((void *)u + u->upd_devs_offset); + /* allocate memory for new volumes */ + if (((struct imsm_dev *)(upd_devs))->vol.migr_type != + MIGR_GEN_MIGR) { + dprintf("imsm: Error.Device is not in "\ + "migration state.\n"); + u->update_prepared = -1; + break; + } + dprintf("passed device : %s\n", + ((struct imsm_dev *)(upd_devs))->volume); + u->devs_mem.dev = calloc(1, u->device_size); + if (u->devs_mem.dev == NULL) { + u->update_prepared = -1; + break; + } + dprintf("METADATA Copy - using it.\n"); + memcpy(u->devs_mem.dev, upd_devs, u->device_size); + len = disks_to_mpb_size(u->spares_in_update + mpb->num_disks); + dprintf("New anchor length is %llu\n", (unsigned long long)len); break; } case update_create_array: { -- 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