From ae6aad82398085e07c922fbfa667a5f6ec5dd7e6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 19 Aug 2008 14:55:10 +1000 Subject: [PATCH] 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 Signed-off-by: NeilBrown --- super-intel.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/super-intel.c b/super-intel.c index 0b902edf..c96793f5 100644 --- a/super-intel.c +++ b/super-intel.c @@ -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, -- 2.39.2