for (d = aa->info.devs; d; d = d->next) {
close(d->recovery_fd);
close(d->state_fd);
+ close(d->bb_fd);
+ close(d->ubb_fd);
}
if (aa->action_fd >= 0)
close(aa->metadata_fd);
if (aa->sync_completed_fd >= 0)
close(aa->sync_completed_fd);
+ if (aa->safe_mode_delay_fd >= 0)
+ close(aa->safe_mode_delay_fd);
}
static void free_aa(struct active_array *aa)
/* Note that this doesn't close fds if they are being used
* by a clone. ->container will be set for a clone
*/
- dprintf("%s: devnum: %d\n", __func__, aa->devnum);
+ dprintf("sys_name: %s\n", aa->info.sys_name);
if (!aa->container)
close_aa(aa);
while (aa->info.devs) {
{
int dfd;
char nm[20];
- struct supertype *st2;
struct metadata_update *update = NULL;
- struct mdinfo info;
mdu_disk_info_t dk = {
.number = -1,
.major = sd->disk.major,
.state = 0,
};
- dprintf("%s: add %d:%d to container\n",
- __func__, sd->disk.major, sd->disk.minor);
+ dprintf("add %d:%d to container\n", sd->disk.major, sd->disk.minor);
sd->next = st->devs;
st->devs = sd;
if (dfd < 0)
return;
- /* Check the metadata and see if it is already part of this
- * array
- */
- st2 = dup_super(st);
- if (st2->ss->load_super(st2, dfd, NULL) == 0) {
- st2->ss->getinfo_super(st, &info, NULL);
- if (st->ss->compare_super(st, st2) == 0 &&
- info.disk.raid_disk >= 0) {
- /* Looks like a good member of array.
- * Just accept it.
- * mdadm will incorporate any parts into
- * active arrays.
- */
- st2->ss->free_super(st2);
- return;
- }
- }
- st2->ss->free_super(st2);
-
st->update_tail = &update;
st->ss->add_to_super(st, &dk, dfd, NULL, INVALID_SECTORS);
st->ss->write_init_super(st);
.raid_disk = -1,
.state = 0,
};
- dprintf("%s: remove %d:%d from container\n",
- __func__, sd->disk.major, sd->disk.minor);
+ dprintf("remove %d:%d from container\n",
+ sd->disk.major, sd->disk.minor);
st->update_tail = &update;
st->ss->remove_from_super(st, &dk);
struct supertype *container)
{
/* Of interest here are:
- * - if a new device has been added to the container, we
+ * - if a new device has been added to the container, we
* add it to the array ignoring any metadata on it.
* - if a device has been removed from the container, we
* remove it from the device list and update the metadata.
* To see what is removed and what is added.
* These need to be remove from, or added to, the array
*/
- mdi = sysfs_read(-1, mdstat->devnum, GET_DEVS);
+ mdi = sysfs_read(-1, mdstat->devnm, GET_DEVS);
if (!mdi) {
/* invalidate the current count so we can try again */
container->devcnt = -1;
}
}
+static int sysfs_open2(char *devnum, char *name, char *attr)
+{
+ int fd = sysfs_open(devnum, name, attr);
+ if (fd >= 0) {
+ /* seq_file in the kernel allocates buffer space
+ * on the first read. Do that now so 'monitor'
+ * never needs too.
+ */
+ char buf[200];
+ if (read(fd, buf, sizeof(buf)) < 0)
+ /* pretend not to ignore return value */
+ return fd;
+ }
+ return fd;
+}
+
static int disk_init_and_add(struct mdinfo *disk, struct mdinfo *clone,
struct active_array *aa)
{
return -1;
*disk = *clone;
- disk->recovery_fd = sysfs_open(aa->devnum, disk->sys_name, "recovery_start");
+ disk->recovery_fd = sysfs_open2(aa->info.sys_name, disk->sys_name,
+ "recovery_start");
if (disk->recovery_fd < 0)
return -1;
- disk->state_fd = sysfs_open(aa->devnum, disk->sys_name, "state");
+ disk->state_fd = sysfs_open2(aa->info.sys_name, disk->sys_name, "state");
if (disk->state_fd < 0) {
close(disk->recovery_fd);
return -1;
}
+ disk->bb_fd = sysfs_open2(aa->info.sys_name, disk->sys_name,
+ "bad_blocks");
+ if (disk->bb_fd < 0) {
+ close(disk->recovery_fd);
+ close(disk->state_fd);
+ return -1;
+ }
+ disk->ubb_fd = sysfs_open2(aa->info.sys_name, disk->sys_name,
+ "unacknowledged_bad_blocks");
+ if (disk->ubb_fd < 0) {
+ close(disk->recovery_fd);
+ close(disk->state_fd);
+ close(disk->bb_fd);
+ return -1;
+ }
disk->prev_state = read_dev_state(disk->state_fd);
disk->curr_state = disk->prev_state;
disk->next = aa->info.devs;
char buf[64];
int frozen;
struct supertype *container = a->container;
+ struct mdinfo *mdi;
if (container == NULL)
/* Raced with something */
return;
- // FIXME
- a->info.array.raid_disks = mdstat->raid_disks;
- // MORE
+ if (mdstat->active) {
+ // FIXME
+ a->info.array.raid_disks = mdstat->raid_disks;
+ // MORE
+ }
+
+ mdi = sysfs_read(-1, mdstat->devnm,
+ GET_COMPONENT|GET_CONSISTENCY_POLICY);
+ if (mdi) {
+ a->info.component_size = mdi->component_size;
+ a->info.consistency_policy = mdi->consistency_policy;
+ sysfs_free(mdi);
+ }
/* honor 'frozen' */
if (sysfs_get_str(&a->info, NULL, "metadata_version", buf, sizeof(buf)) > 0)
frozen = 1; /* can't read metadata_version assume the worst */
/* If sync_action is not 'idle' then don't try recovery now */
- if (!frozen
- && sysfs_get_str(&a->info, NULL, "sync_action", buf, sizeof(buf)) > 0
- && strncmp(buf, "idle", 4) != 0)
+ if (!frozen &&
+ sysfs_get_str(&a->info, NULL, "sync_action",
+ buf, sizeof(buf)) > 0 && strncmp(buf, "idle", 4) != 0)
frozen = 1;
if (mdstat->level) {
if (a->container == NULL)
return;
+ if (sigterm && a->info.safe_mode_delay != 1 &&
+ a->safe_mode_delay_fd >= 0) {
+ long int new_delay = 1;
+ char delay[10];
+ ssize_t len;
+
+ len = snprintf(delay, sizeof(delay), "0.%03ld\n", new_delay);
+ if (write(a->safe_mode_delay_fd, delay, len) == len)
+ a->info.safe_mode_delay = new_delay;
+ }
+
/* 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.
/* prevent the kernel from activating the disk(s) before we
* finish adding them
*/
+ dprintf("freezing %s\n", a->info.sys_name);
sysfs_set_str(&a->info, NULL, "sync_action", "frozen");
/* Add device to array and set offset/size/slot.
}
queue_metadata_update(updates);
updates = NULL;
+ while (update_queue_pending || update_queue) {
+ check_update_queue(container);
+ usleep(15*1000);
+ }
replace_array(container, a, newa);
- sysfs_set_str(&a->info, NULL, "sync_action", "recover");
+ if (sysfs_set_str(&a->info, NULL,
+ "sync_action", "recover") == 0)
+ newa->prev_action = recover;
+ dprintf("recovery started on %s\n", a->info.sys_name);
out:
while (newdev) {
d = newdev->next;
unsigned long long array_size;
struct active_array *newa = NULL;
a->check_reshape = 0;
- info = sysfs_read(-1, mdstat->devnum,
+ info = sysfs_read(-1, mdstat->devnm,
GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
if (!info)
goto out2;
newd = xmalloc(sizeof(*newd));
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*2) {
+ if (sysfs_get_ll(info, NULL, "array_size", &array_size) == 0 &&
+ a->info.custom_array_size > array_size*2) {
sysfs_set_num(info, NULL, "array_size",
a->info.custom_array_size/2);
}
strcmp(mdstat->level, "linear") == 0)
return;
- mdi = sysfs_read(-1, mdstat->devnum,
+ mdi = sysfs_read(-1, mdstat->devnm,
GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
- GET_DEGRADED|GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
-
+ GET_SAFEMODE|GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE|
+ GET_LAYOUT);
if (!mdi)
return;
new = xcalloc(1, sizeof(*new));
- new->devnum = mdstat->devnum;
- strcpy(new->info.sys_name, devnum2devname(new->devnum));
+ strcpy(new->info.sys_name, mdstat->devnm);
new->prev_state = new->curr_state = new->next_state = inactive;
new->prev_action= new->curr_action= new->next_action= idle;
new->container = container;
- inst = to_subarray(mdstat, container->devname);
+ inst = to_subarray(mdstat, container->devnm);
new->info.array = mdi->array;
new->info.component_size = mdi->component_size;
}
}
- new->action_fd = sysfs_open(new->devnum, NULL, "sync_action");
- new->info.state_fd = sysfs_open(new->devnum, NULL, "array_state");
- new->resync_start_fd = sysfs_open(new->devnum, NULL, "resync_start");
- new->metadata_fd = sysfs_open(new->devnum, NULL, "metadata_version");
- new->sync_completed_fd = sysfs_open(new->devnum, NULL, "sync_completed");
- dprintf("%s: inst: %d action: %d state: %d\n", __func__, atoi(inst),
+ new->action_fd = sysfs_open2(new->info.sys_name, NULL, "sync_action");
+ new->info.state_fd = sysfs_open2(new->info.sys_name, NULL, "array_state");
+ new->resync_start_fd = sysfs_open2(new->info.sys_name, NULL, "resync_start");
+ new->metadata_fd = sysfs_open2(new->info.sys_name, NULL, "metadata_version");
+ new->sync_completed_fd = sysfs_open2(new->info.sys_name, NULL, "sync_completed");
+ new->safe_mode_delay_fd = sysfs_open2(new->info.sys_name, NULL,
+ "safe_mode_delay");
+
+ dprintf("inst: %s action: %d state: %d\n", inst,
new->action_fd, new->info.state_fd);
+ if (sigterm)
+ new->info.safe_mode_delay = 1;
+ else if (mdi->safe_mode_delay >= 50)
+ /* Normal start, mdadm set this. */
+ new->info.safe_mode_delay = mdi->safe_mode_delay;
+ else
+ /* Restart, just pick a number */
+ new->info.safe_mode_delay = 5000;
+ sysfs_set_safemode(&new->info, new->info.safe_mode_delay);
+
/* reshape_position is set by mdadm in sysfs
* read this information for new arrays only (empty victim)
*/
* manage this instance
*/
if (!aa_ready(new) || container->ss->open_new(container, new, inst) < 0) {
- fprintf(stderr, "mdmon: failed to monitor %s\n",
+ pr_err("failed to monitor %s\n",
mdstat->metadata_version);
new->container = NULL;
free_aa(new);
for ( ; mdstat ; mdstat = mdstat->next) {
struct active_array *a;
- if (mdstat->devnum == container->devnum) {
+ if (strcmp(mdstat->devnm, container->devnm) == 0) {
manage_container(mdstat, container);
continue;
}
- if (!is_container_member(mdstat, container->devname))
+ if (!is_container_member(mdstat, container->devnm))
/* Not for this array */
continue;
/* Looks like a member of this container */
for (a = container->arrays; a; a = a->next) {
- if (mdstat->devnum == a->devnum) {
+ if (strcmp(mdstat->devnm, a->info.sys_name) == 0) {
if (a->container && a->to_remove == 0)
manage_member(mdstat, a);
break;
if (msg->len == 0) { /* ping_monitor */
int cnt;
-
+
cnt = monitor_loop_cnt;
if (cnt & 1)
cnt += 2; /* wait until next pselect */
mu->space_list = NULL;
mu->next = NULL;
if (container->ss->prepare_update)
- container->ss->prepare_update(container, mu);
+ if (!container->ss->prepare_update(container, mu))
+ free_updates(&mu);
queue_metadata_update(mu);
}
}