imsm: delete kicked disks

When we have determined that a disk is no longer of any value, remove
it from the data structure.   This is now safe because the manager
will back off while any metadata update is pending in the monitor.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Dan Williams 2008-08-19 14:55:10 +10:00 committed by NeilBrown
parent 0b5ec75e01
commit ae6aad8239
1 changed files with 57 additions and 11 deletions

View File

@ -1104,17 +1104,22 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
return rc;
}
static void __free_imsm_disk(struct dl *d)
{
if (d->fd >= 0)
close(d->fd);
if (d->devname)
free(d->devname);
free(d);
}
static void free_imsm_disks(struct intel_super *super)
{
while (super->disks) {
struct dl *d = super->disks;
super->disks = d->next;
if (d->fd >= 0)
close(d->fd);
if (d->devname)
free(d->devname);
free(d);
__free_imsm_disk(d);
}
}
@ -2601,6 +2606,8 @@ static int disks_overlap(struct imsm_map *m1, struct imsm_map *m2)
return 0;
}
static void imsm_delete(struct intel_super *super, struct dl **dlp);
static void imsm_process_update(struct supertype *st,
struct metadata_update *update)
{
@ -2669,15 +2676,18 @@ static void imsm_process_update(struct supertype *st,
* utilized anywhere
*/
if (!found) {
disk = get_imsm_disk(super, victim);
struct dl **dlp;
for (dlp = &super->disks; *dlp; )
if ((*dlp)->index == victim)
break;
disk = &(*dlp)->disk;
status = __le32_to_cpu(disk->status);
status &= ~(CONFIGURED_DISK | USABLE_DISK);
disk->status = __cpu_to_le32(status);
/* at this point the disk can be removed from the
* metadata, however we need to guarantee that we do
* not race with any manager thread routine that relies
* on dl->index or map->disk_ord_tbl
*/
/* We know that 'manager' isn't touching anything,
* so it is safe to:
*/
imsm_delete(super, dlp);
}
break;
}
@ -2805,6 +2815,42 @@ static void imsm_prepare_update(struct supertype *st,
return;
}
/* must be called while manager is quiesced */
static void imsm_delete(struct intel_super *super, struct dl **dlp)
{
struct imsm_super *mpb = super->anchor;
struct dl *dl = *dlp;
struct dl *iter;
struct imsm_dev *dev;
struct imsm_map *map;
int i, j;
dprintf("%s: deleting device %x:%x from imsm_super\n",
__func__, dl->major, dl->minor);
/* shift all indexes down one */
for (iter = super->disks; iter; iter = iter->next)
if (iter->index > dl->index)
iter->index--;
for (i = 0; i < mpb->num_raid_devs; i++) {
dev = get_imsm_dev(super, i);
map = get_imsm_map(dev, 0);
for (j = 0; j < map->num_members; j++) {
int idx = get_imsm_disk_idx(map, j);
if (idx > dl->index)
map->disk_ord_tbl[j] = __cpu_to_le32(idx - 1);
}
}
mpb->num_disks--;
super->updates_pending++;
*dlp = (*dlp)->next;
__free_imsm_disk(dl);
}
struct superswitch super_imsm = {
#ifndef MDASSEMBLE
.examine_super = examine_super_imsm,