X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=super-intel.c;h=3525dae6681dff82483ca5e2d9fb679f2cf93413;hb=c9aaf5effb5e4afe5dd1e4d08188140bc596808e;hp=587da383d1832eae08f7501e9c3bf029e8ad0db1;hpb=ea672ee1190e3ce4e4f0a0e612f9dd1808b31c41;p=thirdparty%2Fmdadm.git diff --git a/super-intel.c b/super-intel.c index 587da383..3525dae6 100644 --- a/super-intel.c +++ b/super-intel.c @@ -989,7 +989,6 @@ static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st) struct extent *e; int i; unsigned long long rv = 0; - __u32 reservation; if (!super) return rv; @@ -1007,7 +1006,6 @@ static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st) continue; if (i > 0) rv = e[i-1].start + e[i-1].size; - reservation = __le32_to_cpu(dl->disk.total_blocks) - e[i].start; free(e); /* add the amount of space needed for metadata */ @@ -2295,7 +2293,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, info->custom_array_size |= __le32_to_cpu(dev->size_low); info->recovery_blocked = imsm_reshape_blocks_arrays_changes(st->sb); - if (prev_map && map->map_state == prev_map->map_state) { + if (prev_map && map->map_state == prev_map->map_state && + (migr_type(dev) == MIGR_GEN_MIGR)) { info->reshape_active = 1; info->new_level = get_imsm_raid_level(map); info->new_layout = imsm_level_to_layout(info->new_level); @@ -2305,7 +2304,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, /* this needs to be applied to every array * in the container. */ - info->reshape_active = 2; + info->reshape_active = CONTAINER_RESHAPE; } /* We shape information that we give to md might have to be * modify to cope with md's requirement for reshaping arrays. @@ -2863,7 +2862,7 @@ static void fd2devname(int fd, char *name) sprintf(path, "/sys/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)); - rv = readlink(path, dname, sizeof(dname)); + rv = readlink(path, dname, sizeof(dname)-1); if (rv <= 0) return; @@ -5685,20 +5684,24 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra struct imsm_super *mpb = super->anchor; struct mdinfo *rest = NULL; unsigned int i; - int bbm_errors = 0; + int sb_errors = 0; struct dl *d; int spare_disks = 0; /* do not assemble arrays when not all attributes are supported */ if (imsm_check_attributes(mpb->attributes) == 0) { - fprintf(stderr, Name ": IMSM metadata loading not allowed " - "due to attributes incompatibility.\n"); - return NULL; + sb_errors = 1; + fprintf(stderr, Name ": Unsupported attributes in IMSM metadata." + "Arrays activation is blocked.\n"); } /* check for bad blocks */ - if (imsm_bbm_log_size(super->anchor)) - bbm_errors = 1; + if (imsm_bbm_log_size(super->anchor)) { + fprintf(stderr, Name ": BBM log found in IMSM metadata." + "Arrays activation is blocked.\n"); + sb_errors = 1; + } + /* count spare devices, not used in maps */ @@ -5737,18 +5740,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra */ chunk = __le16_to_cpu(map->blocks_per_strip) >> 1; -#ifndef MDASSEMBLE - if (!validate_geometry_imsm_orom(super, - get_imsm_raid_level(map), /* RAID level */ - imsm_level_to_layout(get_imsm_raid_level(map)), - map->num_members, /* raid disks */ - &chunk, - 1 /* verbose */)) { - fprintf(stderr, Name ": RAID gemetry validation failed. " - "Cannot proceed with the action(s).\n"); - continue; - } -#endif /* MDASSEMBLE */ this = malloc(sizeof(*this)); if (!this) { fprintf(stderr, Name ": failed to allocate %zu bytes\n", @@ -5759,6 +5750,29 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra super->current_vol = i; getinfo_super_imsm_volume(st, this, NULL); this->next = rest; +#ifndef MDASSEMBLE + /* mdadm does not support all metadata features- set the bit in all arrays state */ + if (!validate_geometry_imsm_orom(super, + get_imsm_raid_level(map), /* RAID level */ + imsm_level_to_layout(get_imsm_raid_level(map)), + map->num_members, /* raid disks */ + &chunk, + 1 /* verbose */)) { + fprintf(stderr, Name ": IMSM RAID gemetry validation failed. " + "Array %s activation is blocked.\n", + dev->volume); + this->array.state |= + (1<array.state |= + (1<num_members; slot++) { unsigned long long recovery_start; struct mdinfo *info_d; @@ -5847,10 +5861,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra rest = this; } - /* if array has bad blocks, set suitable bit in array status */ - if (bbm_errors) - rest->array.state |= (1<serial); + memcpy(buf, disk->serial, MAX_RAID_SERIAL_LEN); + buf[MAX_RAID_SERIAL_LEN] = '\000'; + strcat(buf, ":0"); if ((len = strlen(buf)) >= MAX_RAID_SERIAL_LEN) shift = len - MAX_RAID_SERIAL_LEN + 1; strncpy((char *)disk->serial, &buf[shift], MAX_RAID_SERIAL_LEN); @@ -6639,9 +6651,9 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, * are removed from container. */ if (failed) { - dprintf("found failed disks in %s, check if there another" + dprintf("found failed disks in %.*s, check if there another" "failed sub-array.\n", - dev->volume); + MAX_RAID_SERIAL_LEN, dev->volume); /* check if states of the other volumes allow for rebuild */ for (i = 0; i < super->anchor->num_raid_devs; i++) { if (i != inst) { @@ -6979,6 +6991,120 @@ error_disk_add: return ret_val; } +static int apply_update_activate_spare(struct imsm_update_activate_spare *u, + struct intel_super *super, + struct active_array *active_array) +{ + struct imsm_super *mpb = super->anchor; + struct imsm_dev *dev = get_imsm_dev(super, u->array); + struct imsm_map *map = get_imsm_map(dev, 0); + struct imsm_map *migr_map; + struct active_array *a; + struct imsm_disk *disk; + __u8 to_state; + struct dl *dl; + unsigned int found; + int failed; + int victim; + int i; + int second_map_created = 0; + + for (; u; u = u->next) { + victim = get_imsm_disk_idx(dev, u->slot, -1); + + if (victim < 0) + return 0; + + for (dl = super->disks; dl; dl = dl->next) + if (dl == u->dl) + break; + + if (!dl) { + fprintf(stderr, "error: imsm_activate_spare passed " + "an unknown disk (index: %d)\n", + u->dl->index); + return 0; + } + + /* count failures (excluding rebuilds and the victim) + * to determine map[0] state + */ + failed = 0; + for (i = 0; i < map->num_members; i++) { + if (i == u->slot) + continue; + disk = get_imsm_disk(super, + get_imsm_disk_idx(dev, i, -1)); + if (!disk || is_failed(disk)) + failed++; + } + + /* adding a pristine spare, assign a new index */ + if (dl->index < 0) { + dl->index = super->anchor->num_disks; + super->anchor->num_disks++; + } + disk = &dl->disk; + disk->status |= CONFIGURED_DISK; + disk->status &= ~SPARE_DISK; + + /* mark rebuild */ + to_state = imsm_check_degraded(super, dev, failed); + if (!second_map_created) { + second_map_created = 1; + map->map_state = IMSM_T_STATE_DEGRADED; + migrate(dev, super, to_state, MIGR_REBUILD); + } else + map->map_state = to_state; + migr_map = get_imsm_map(dev, 1); + set_imsm_ord_tbl_ent(map, u->slot, dl->index); + set_imsm_ord_tbl_ent(migr_map, u->slot, + dl->index | IMSM_ORD_REBUILD); + + /* update the family_num to mark a new container + * generation, being careful to record the existing + * family_num in orig_family_num to clean up after + * earlier mdadm versions that neglected to set it. + */ + if (mpb->orig_family_num == 0) + mpb->orig_family_num = mpb->family_num; + mpb->family_num += super->random; + + /* count arrays using the victim in the metadata */ + found = 0; + for (a = active_array; a ; a = a->next) { + dev = get_imsm_dev(super, a->info.container_member); + map = get_imsm_map(dev, 0); + + if (get_imsm_disk_slot(map, victim) >= 0) + found++; + } + + /* delete the victim if it is no longer being + * utilized anywhere + */ + if (!found) { + struct dl **dlp; + + /* We know that 'manager' isn't touching anything, + * so it is safe to delete + */ + for (dlp = &super->disks; *dlp; dlp = &(*dlp)->next) + if ((*dlp)->index == victim) + break; + + /* victim may be on the missing list */ + if (!*dlp) + for (dlp = &super->missing; *dlp; + dlp = &(*dlp)->next) + if ((*dlp)->index == victim) + break; + imsm_delete(super, dlp, victim); + } + } + + return 1; +} static int apply_reshape_container_disks_update(struct imsm_update_reshape *u, struct intel_super *super, @@ -7273,99 +7399,8 @@ static void imsm_process_update(struct supertype *st, } case update_activate_spare: { struct imsm_update_activate_spare *u = (void *) update->buf; - struct imsm_dev *dev = get_imsm_dev(super, u->array); - struct imsm_map *map = get_imsm_map(dev, 0); - struct imsm_map *migr_map; - struct active_array *a; - struct imsm_disk *disk; - __u8 to_state; - struct dl *dl; - unsigned int found; - int failed; - int victim = get_imsm_disk_idx(dev, u->slot, -1); - int i; - - for (dl = super->disks; dl; dl = dl->next) - if (dl == u->dl) - break; - - if (!dl) { - fprintf(stderr, "error: imsm_activate_spare passed " - "an unknown disk (index: %d)\n", - u->dl->index); - return; - } - - super->updates_pending++; - /* count failures (excluding rebuilds and the victim) - * to determine map[0] state - */ - failed = 0; - for (i = 0; i < map->num_members; i++) { - if (i == u->slot) - continue; - disk = get_imsm_disk(super, - get_imsm_disk_idx(dev, i, -1)); - if (!disk || is_failed(disk)) - failed++; - } - - /* adding a pristine spare, assign a new index */ - if (dl->index < 0) { - dl->index = super->anchor->num_disks; - super->anchor->num_disks++; - } - disk = &dl->disk; - disk->status |= CONFIGURED_DISK; - disk->status &= ~SPARE_DISK; - - /* mark rebuild */ - to_state = imsm_check_degraded(super, dev, failed); - map->map_state = IMSM_T_STATE_DEGRADED; - migrate(dev, super, to_state, MIGR_REBUILD); - migr_map = get_imsm_map(dev, 1); - set_imsm_ord_tbl_ent(map, u->slot, dl->index); - set_imsm_ord_tbl_ent(migr_map, u->slot, dl->index | IMSM_ORD_REBUILD); - - /* update the family_num to mark a new container - * generation, being careful to record the existing - * family_num in orig_family_num to clean up after - * earlier mdadm versions that neglected to set it. - */ - if (mpb->orig_family_num == 0) - mpb->orig_family_num = mpb->family_num; - mpb->family_num += super->random; - - /* count arrays using the victim in the metadata */ - found = 0; - for (a = st->arrays; a ; a = a->next) { - dev = get_imsm_dev(super, a->info.container_member); - map = get_imsm_map(dev, 0); - - if (get_imsm_disk_slot(map, victim) >= 0) - found++; - } - - /* delete the victim if it is no longer being - * utilized anywhere - */ - if (!found) { - struct dl **dlp; - - /* We know that 'manager' isn't touching anything, - * so it is safe to delete - */ - for (dlp = &super->disks; *dlp; dlp = &(*dlp)->next) - if ((*dlp)->index == victim) - break; - - /* victim may be on the missing list */ - if (!*dlp) - for (dlp = &super->missing; *dlp; dlp = &(*dlp)->next) - if ((*dlp)->index == victim) - break; - imsm_delete(super, dlp, victim); - } + if (apply_update_activate_spare(u, super, st->arrays)) + super->updates_pending++; break; } case update_create_array: {