.raid_disk = -1,
.state = 0,
};
- /* nothing to do if super type handler does not support
- * remove disk primitive
- */
- if (!st->ss->remove_from_super)
- return;
dprintf("%s: remove %d:%d from container\n",
__func__, sd->disk.major, sd->disk.minor);
st->update_tail = &update;
st->ss->remove_from_super(st, &dk);
+ /* FIXME this write_init_super shouldn't be here.
+ * We have it after add_to_super to write to new device,
+ * but with 'remove' we don't ant to write to that device!
+ */
st->ss->write_init_super(st);
queue_metadata_update(update);
st->update_tail = NULL;
*/
char buf[64];
int frozen;
+ struct supertype *container = a->container;
+
+ if (container == NULL)
+ /* Raced with something */
+ return;
// FIXME
a->info.array.raid_disks = mdstat->raid_disks;
if (mdstat->level) {
int level = map_name(pers, mdstat->level);
- if (a->info.array.level != level && level >= 0) {
+ if (level == 0 || level == LEVEL_LINEAR) {
+ a->container = NULL;
+ wakeup_monitor();
+ return;
+ }
+ else if (a->info.array.level != level && level > 0) {
struct active_array *newa = duplicate_aa(a);
if (newa) {
newa->info.array.level = level;
- replace_array(a->container, a, newa);
+ replace_array(container, a, newa);
a = newa;
}
}
}
- if (a->check_degraded && !frozen) {
+ /* We don't check the array while any update is pending, as it
+ * might container a change (such as a spare assignment) which
+ * could affect our decisions.
+ */
+ if (a->check_degraded && !frozen &&
+ update_queue == NULL && update_queue_pending == NULL) {
struct metadata_update *updates = NULL;
struct mdinfo *newdev = NULL;
struct active_array *newa;
/* The array may not be degraded, this is just a good time
* to check.
*/
- newdev = a->container->ss->activate_spare(a, &updates);
+ newdev = container->ss->activate_spare(a, &updates);
if (!newdev)
return;
}
queue_metadata_update(updates);
updates = NULL;
- replace_array(a->container, a, newa);
+ replace_array(container, a, newa);
sysfs_set_str(&a->info, NULL, "sync_action", "recover");
out:
while (newdev) {
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) {
+ && a->info.custom_array_size > array_size*2) {
sysfs_set_num(info, NULL, "array_size",
- a->info.custom_array_size);
+ a->info.custom_array_size/2);
}
out2:
sysfs_free(info);
if (newa)
- replace_array(a->container, a, newa);
+ replace_array(container, a, newa);
}
}
char *inst;
int i;
int failed = 0;
+ char buf[40];
/* check if array is ready to be monitored */
- if (!mdstat->active)
+ if (!mdstat->active || !mdstat->level)
+ return;
+ if (strcmp(mdstat->level, "raid0") == 0 ||
+ strcmp(mdstat->level, "linear") == 0)
return;
mdi = sysfs_read(-1, mdstat->devnum,
dprintf("%s: inst: %d action: %d state: %d\n", __func__, atoi(inst),
new->action_fd, new->info.state_fd);
+ /* reshape_position is set by mdadm in sysfs
+ * read this information for new arrays only (empty victim)
+ */
+ if ((victim == NULL) &&
+ (sysfs_get_str(mdi, NULL, "sync_action", buf, 40) > 0) &&
+ (strncmp(buf, "reshape", 7) == 0)) {
+ if (sysfs_get_ll(mdi, NULL, "reshape_position",
+ &new->last_checkpoint) != 0)
+ new->last_checkpoint = 0;
+ else {
+ int data_disks = mdi->array.raid_disks;
+ if (mdi->array.level == 4 || mdi->array.level == 5)
+ data_disks--;
+ if (mdi->array.level == 6)
+ data_disks -= 2;
+
+ new->last_checkpoint /= data_disks;
+ }
+ dprintf("mdmon: New monitored array is under reshape.\n"
+ " Last checkpoint is: %llu\n",
+ new->last_checkpoint);
+ }
+
sysfs_free(mdi);
/* if everything checks out tell the metadata handler we want to