+
+ super = st->sb;
+ dev = get_imsm_dev(super, super->current_vol);
+ data_disks = imsm_num_data_members(dev , MAP_0);
+ /* compute current size per disk member
+ */
+ current_size = info.custom_array_size / data_disks;
+
+ if ((geo->size > 0) && (geo->size != MAX_SIZE)) {
+ /* align component size
+ */
+ geo->size = imsm_component_size_aligment_check(
+ get_imsm_raid_level(dev->vol.map),
+ chunk * 1024,
+ geo->size * 2);
+ if (geo->size == 0) {
+ pr_err("Error. Size expansion is " \
+ "supported only (current size is %llu, " \
+ "requested size /rounded/ is 0).\n",
+ current_size);
+ goto analyse_change_exit;
+ }
+ }
+
+ if ((current_size != geo->size) && (geo->size > 0)) {
+ if (change != -1) {
+ pr_err("Error. Size change should be the only "
+ "one at a time.\n");
+ change = -1;
+ goto analyse_change_exit;
+ }
+ if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
+ pr_err("Error. The last volume in container "
+ "can be expanded only (%i/%s).\n",
+ super->current_vol, st->devnm);
+ goto analyse_change_exit;
+ }
+ /* check the maximum available size
+ */
+ rv = imsm_get_free_size(st, dev->vol.map->num_members,
+ 0, chunk, &free_size);
+ if (rv == 0)
+ /* Cannot find maximum available space
+ */
+ max_size = 0;
+ else {
+ max_size = free_size + current_size;
+ /* align component size
+ */
+ max_size = imsm_component_size_aligment_check(
+ get_imsm_raid_level(dev->vol.map),
+ chunk * 1024,
+ max_size);
+ }
+ if (geo->size == MAX_SIZE) {
+ /* requested size change to the maximum available size
+ */
+ if (max_size == 0) {
+ pr_err("Error. Cannot find "
+ "maximum available space.\n");
+ change = -1;
+ goto analyse_change_exit;
+ } else
+ geo->size = max_size;
+ }
+
+ if ((direction == ROLLBACK_METADATA_CHANGES)) {
+ /* accept size for rollback only
+ */
+ } else {
+ /* round size due to metadata compatibility
+ */
+ geo->size = (geo->size >> SECT_PER_MB_SHIFT)
+ << SECT_PER_MB_SHIFT;
+ dprintf("Prepare update for size change to %llu\n",
+ geo->size );
+ if (current_size >= geo->size) {
+ pr_err("Error. Size expansion is "
+ "supported only (current size is %llu, "
+ "requested size /rounded/ is %llu).\n",
+ current_size, geo->size);
+ goto analyse_change_exit;
+ }
+ if (max_size && geo->size > max_size) {
+ pr_err("Error. Requested size is larger "
+ "than maximum available size (maximum "
+ "available size is %llu, "
+ "requested size /rounded/ is %llu).\n",
+ max_size, geo->size);
+ goto analyse_change_exit;
+ }
+ }
+ geo->size *= data_disks;
+ geo->raid_disks = dev->vol.map->num_members;
+ change = CH_ARRAY_SIZE;
+ }