diff --git a/Assemble.c b/Assemble.c index 2000dd0..ac1115d 100644 --- a/Assemble.c +++ b/Assemble.c @@ -439,13 +439,6 @@ int Assemble(struct supertype *st, char *mddev, content; content = content->next) { - /* do not assemble arrays that might have bad blocks */ - if (content->array.state & (1<used = 2; - goto loop; - } if (!ident_matches(ident, content, tst, homehost, update, report_missmatch ? devname : NULL)) @@ -455,6 +448,11 @@ int Assemble(struct supertype *st, char *mddev, fprintf(stderr, Name ": member %s in %s is already assembled\n", content->text_version, devname); + } else if (content->array.state & (1<text_version, + devname); } else break; } @@ -1557,8 +1555,15 @@ int assemble_container_content(struct supertype *st, int mdfd, (working + preexist + expansion) >= content->array.working_disks) { int err; + int start_reshape; - if (content->reshape_active) { + /* There are two types of reshape: container wide or sub-array specific + * Check if metadata requests blocking container wide reshapes + */ + start_reshape = (content->reshape_active && + !((content->reshape_active == CONTAINER_RESHAPE) && + (content->array.state & (1<array.raid_disks + expansion; if (restore_backup(st, content, working, diff --git a/Grow.c b/Grow.c index 93a69fd..13825a2 100644 --- a/Grow.c +++ b/Grow.c @@ -1357,6 +1357,36 @@ static int reshape_container(char *container, char *devname, char *backup_file, int quiet, int restart, int freeze_reshape); +/* + * helper routine to check metadata reshape avalability + * 1. Do not "grow" arrays with volume activation blocked + * 2. do not reshape containers with container reshape blocked + * + * IN: + * subarray - array name or NULL for container wide reshape + * content - md device info from container_content + * OUT: + * 0 - block reshape + */ +static int check_reshape(char *subarray, struct mdinfo *content) +{ + char *ep; + unsigned int idx; + + if (!subarray) { + if (content->array.state & (1<container_member == (int) idx + && (content->array.state & (1<ss->container_content) { + struct mdinfo *cc = NULL; + struct mdinfo *content = NULL; + + cc = st->ss->container_content(st, subarray); + for (content = cc; content ; content = content->next) { + int allow_reshape; + + /* check if reshape is allowed based on metadata + * indications stored in content.array.status + */ + allow_reshape = check_reshape(subarray, content); + if (!allow_reshape) { + fprintf(stderr, Name + " cannot reshape arrays in" + " container with unsupported" + " metadata: %s(%s)\n", + devname, container_buf); + sysfs_free(cc); + free(subarray); + return 1; + } + } + sysfs_free(cc); + } if (mdmon_running(container_dev)) st->update_tail = &st->updates; } @@ -3723,9 +3779,28 @@ int Grow_continue_command(char *devname, int fd, cc = st->ss->container_content(st, NULL); for (content = cc; content ; content = content->next) { char *array; + int allow_reshape; if (content->reshape_active == 0) continue; + /* The decision about array or container wide + * reshape is taken in Grow_continue based + * content->reshape_active state, therefore we + * need to check_reshape based on + * reshape_active and subarray name + */ + allow_reshape = + check_reshape((content->reshape_active == CONTAINER_RESHAPE)? NULL : subarray, + content); + if (!allow_reshape) { + fprintf(stderr, Name + ": cannot continue reshape of an array" + " in container with unsupported" + " metadata: %s(%s)\n", + devname, buf); + ret_val = 1; + goto Grow_continue_command_exit; + } array = strchr(content->text_version+1, '/')+1; mdstat = mdstat_by_subdev(array, container_dev); diff --git a/Incremental.c b/Incremental.c index c21c971..98a3a74 100644 --- a/Incremental.c +++ b/Incremental.c @@ -1446,6 +1446,8 @@ static int Incremental_container(struct supertype *st, char *devname, struct map_ent *smp; int suuid[4]; int sfd; + int ra_blocked = 0; + int ra_all = 0; st->ss->getinfo_super(st, &info, NULL); @@ -1473,21 +1475,26 @@ static int Incremental_container(struct supertype *st, char *devname, trustworthy = FOREIGN; list = st->ss->container_content(st, NULL); - /* do not assemble arrays that might have bad blocks */ - if (list && list->array.state & (1<next) { int mdfd; char chosen_name[1024]; struct map_ent *mp; struct mddev_ident *match = NULL; + ra_all++; + /* do not activate arrays blocked by metadata handler */ + if (ra->array.state & (1 << MD_SB_BLOCK_VOLUME)) { + fprintf(stderr, Name ": Cannot activate array %s in %s.\n", + ra->text_version, devname); + ra_blocked++; + continue; + } mp = map_by_uuid(&map, ra->uuid); if (mp) { @@ -1566,6 +1573,13 @@ static int Incremental_container(struct supertype *st, char *devname, close(mdfd); } + /* don't move spares to container with volume being activated + when all volumes are blocked */ + if (ra_all == ra_blocked) { + map_unlock(&map); + return 0; + } + /* Now move all suitable spares from spare container */ domains = domain_from_array(list, st->ss->name); memcpy(suuid, uuid_zero, sizeof(int[4])); diff --git a/md_p.h b/md_p.h index 6c79a3d..517b204 100644 --- a/md_p.h +++ b/md_p.h @@ -101,7 +101,9 @@ typedef struct mdp_device_descriptor_s { #define MD_SB_CLEAN 0 #define MD_SB_ERRORS 1 #define MD_SB_BBM_ERRORS 2 - +#define MD_SB_BLOCK_CONTAINER_RESHAPE 3 /* block container wide reshapes */ +#define MD_SB_BLOCK_VOLUME 4 /* block activation of array, other arrays + * in container can be activated */ #define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ typedef struct mdp_superblock_s { diff --git a/mdadm.h b/mdadm.h index c397045..6dbc5ea 100644 --- a/mdadm.h +++ b/mdadm.h @@ -194,6 +194,9 @@ struct mdinfo { unsigned long long custom_array_size; /* size for non-default sized * arrays (in sectors) */ +#define NO_RESHAPE 0 +#define VOLUME_RESHAPE 1 +#define CONTAINER_RESHAPE 2 int reshape_active; unsigned long long reshape_progress; int recovery_blocked; /* for external metadata it diff --git a/super-intel.c b/super-intel.c index d491318..3525dae 100644 --- a/super-intel.c +++ b/super-intel.c @@ -2304,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. @@ -5684,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 */ @@ -5736,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", @@ -5758,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; @@ -5846,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<