DDF: ddf_open_new: check device status for new subarray
It is possible that mdadm creates a new subarray containing failed devices. This may happen if a device has failed, but the meta data containing that information hasn't been written out yet. This code tests for this situation, and handles it in the monitor. Signed-off-by: Martin Wilck <mwilck@arcor.de> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
82c8e664cc
commit
5daa35ac1a
29
super-ddf.c
29
super-ddf.c
|
@ -3985,11 +3985,38 @@ static int ddf_open_new(struct supertype *c, struct active_array *a, char *inst)
|
|||
{
|
||||
struct ddf_super *ddf = c->sb;
|
||||
int n = atoi(inst);
|
||||
struct mdinfo *dev;
|
||||
struct dl *dl;
|
||||
static const char faulty[] = "faulty";
|
||||
|
||||
if (all_ff(ddf->virt->entries[n].guid)) {
|
||||
pr_err("%s: subarray %d doesn't exist\n", __func__, n);
|
||||
return -ENODEV;
|
||||
}
|
||||
dprintf("ddf: open_new %d\n", n);
|
||||
dprintf("%s: new subarray %d, GUID: %s\n", __func__, n,
|
||||
guid_str(ddf->virt->entries[n].guid));
|
||||
for (dev = a->info.devs; dev; dev = dev->next) {
|
||||
for (dl = ddf->dlist; dl; dl = dl->next)
|
||||
if (dl->major == dev->disk.major &&
|
||||
dl->minor == dev->disk.minor)
|
||||
break;
|
||||
if (!dl) {
|
||||
pr_err("%s: device %d/%d of subarray %d not found in meta data\n",
|
||||
__func__, dev->disk.major, dev->disk.minor, n);
|
||||
return -1;
|
||||
}
|
||||
if ((be16_to_cpu(ddf->phys->entries[dl->pdnum].state) &
|
||||
(DDF_Online|DDF_Missing|DDF_Failed)) != DDF_Online) {
|
||||
pr_err("%s: new subarray %d contains broken device %d/%d (%02x)\n",
|
||||
__func__, n, dl->major, dl->minor,
|
||||
be16_to_cpu(
|
||||
ddf->phys->entries[dl->pdnum].state));
|
||||
if (write(dev->state_fd, faulty, sizeof(faulty)-1) !=
|
||||
sizeof(faulty) - 1)
|
||||
pr_err("Write to state_fd failed\n");
|
||||
dev->curr_state = DS_FAULTY;
|
||||
}
|
||||
}
|
||||
a->info.container_member = n;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue