* and look for new stuff.
*/
struct mdinfo *info, *d, *d2, *newd;
+ unsigned long long array_size;
struct active_array *newa = NULL;
a->check_reshape = 0;
info = sysfs_read(-1, mdstat->devnum,
continue;
disk_init_and_add(newd, d, newa);
}
+ if (sysfs_get_ll(info, NULL, "array_size", &array_size) == 0
+ && a->info.custom_array_size > array_size) {
+ sysfs_set_num(info, NULL, "array_size",
+ a->info.custom_array_size);
+ }
out2:
sysfs_free(info);
if (newa)
/* Check for recovery checkpoint notifications. We need to be a
* minimum distance away from the last checkpoint to prevent
- * over checkpointing. Note reshape checkpointing is not
- * handled here.
+ * over checkpointing. Note reshape checkpointing is handled
+ * in the second branch.
*/
if (sync_completed > a->last_checkpoint &&
sync_completed - a->last_checkpoint > a->info.component_size >> 4 &&
*/
a->last_checkpoint = sync_completed;
a->container->ss->set_array_state(a, a->curr_state <= clean);
- } else if (sync_completed > a->last_checkpoint)
+ } else if ((a->curr_action == idle && a->prev_action == reshape) ||
+ (a->curr_action == reshape
+ && sync_completed > a->last_checkpoint) ) {
+ /* Reshape has progressed or completed so we need to
+ * update the array state - and possibly the array size
+ */
+ a->last_checkpoint = sync_completed;
+ a->container->ss->set_array_state(a, a->curr_state <= clean);
+ }
+
+ if (sync_completed > a->last_checkpoint)
a->last_checkpoint = sync_completed;
a->container->ss->sync_metadata(a->container);
return migr_chunk * stripes_per_unit;
}
case MIGR_GEN_MIGR:
+ /* FIXME I need a number here */
case MIGR_STATE_CHANGE:
default:
return 0;
static void imsm_set_disk(struct active_array *a, int n, int state);
-/* Handle dirty -> clean transititions and resync. Degraded and rebuild
+/* Handle dirty -> clean transititions, resync and reshape. Degraded and rebuild
* states are handled in imsm_set_disk() with one exception, when a
* resync is stopped due to a new failure this routine will set the
* 'degraded' state for the array.
if (dev->vol.migr_state &&
dev->vol.migr_type == MIGR_GEN_MIGR) {
/* array state change is blocked due to reshape action
- *
- * '1' is returned to indicate that array is clean
+ * We might need to
+ * - abort the reshape (if last_checkpoint is 0 and action!= reshape)
+ * - finish the reshape (if last_checkpoint is big and action != reshape)
+ * - update curr_migr_unit
*/
- dprintf("imsm: imsm_set_array_state() called "\
- "during reshape.\n");
- return 1;
+ if (a->curr_action == reshape) {
+ /* still reshaping, maybe update curr_migr_unit */
+ long long blocks_per_unit = blocks_per_migr_unit(dev);
+ long long unit = a->last_checkpoint;
+ unit /= blocks_per_unit;
+ if (unit > __le32_to_cpu(dev->vol.curr_migr_unit)) {
+ dev->vol.curr_migr_unit = __cpu_to_le32(unit);
+ super->updates_pending++;
+ }
+ } else {
+ if (a->last_checkpoint == 0 && a->prev_action == reshape) {
+ /* for some reason we aborted the reshape.
+ * Better clean up
+ */
+ struct imsm_map *map2 = get_imsm_map(dev, 1);
+ dev->vol.migr_state = 0;
+ dev->vol.migr_type = 0;
+ dev->vol.curr_migr_unit = 0;
+ memcpy(map, map2, sizeof_imsm_map(map2));
+ super->updates_pending++;
+ }
+ if (a->last_checkpoint >= a->info.component_size) {
+ unsigned long long array_blocks;
+ int used_disks;
+ /* it seems the reshape is all done */
+ dev->vol.migr_state = 0;
+ dev->vol.migr_type = 0;
+ dev->vol.curr_migr_unit = 0;
+
+ used_disks = imsm_num_data_members(dev);
+ array_blocks = map->blocks_per_member * used_disks;
+ /* round array size down to closest MB */
+ array_blocks = (array_blocks >> SECT_PER_MB_SHIFT)
+ << SECT_PER_MB_SHIFT;
+ dev->size_low = __cpu_to_le32((__u32) array_blocks);
+ dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32));
+ a->info.custom_array_size = array_blocks;
+ a->check_reshape = 1; /* encourage manager to update
+ * array size
+ */
+ super->updates_pending++;
+ }
+ }
+ return 0;
}
/* before we activate this array handle any missing disks */