static int Incremental_container(struct supertype *st, char *devname,
char *homehost,
- int verbose, int runstop, int autof);
+ int verbose, int runstop, int autof,
+ int freeze_reshape);
static struct mddev_ident *search_mdstat(struct supertype *st,
struct mdinfo *info,
int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
- int autof)
+ int autof, int freeze_reshape)
{
/* Add this device to an array, creating the array if necessary
* and starting the array if sensible or - if runstop>0 - if possible.
close(dfd);
if (!rv && st->ss->container_content)
return Incremental_container(st, devname, homehost,
- verbose, runstop, autof);
+ verbose, runstop, autof,
+ freeze_reshape);
fprintf(stderr, Name ": %s is not part of an md array.\n",
devname);
}
close (dfd); dfd = -1;
- memset(&info, 0, sizeof(info));
st->ss->getinfo_super(st, &info, NULL);
/* 3/ Check if there is a match in mdadm.conf */
* array was possibly started early and our best bet is
* to add this anyway.
* Also if action policy is re-add or better we allow
- * re-add
+ * re-add.
+ * This doesn't apply to containers as the 'non-spare'
+ * flag has a different meaning. The test has to happen
+ * at the device level there
*/
- if ((info.disk.state & (1<<MD_DISK_SYNC)) != 0
+ if (!st->ss->external
+ && (info.disk.state & (1<<MD_DISK_SYNC)) != 0
&& ! policy_action_allows(policy, st->ss->name,
act_re_add)
&& runstop < 1) {
- int active = 0;
-
- if (st->ss->external) {
- char *devname = devnum2devname(fd2devnum(mdfd));
-
- active = devname && is_container_active(devname);
- free(devname);
- } else if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0)
- active = 1;
- if (active) {
+ if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) {
fprintf(stderr, Name
": not adding %s to active array (without --run) %s\n",
devname, chosen_name);
goto out;
}
close(dfd2);
- memset(&info2, 0, sizeof(info2));
st2->ss->getinfo_super(st2, &info2, NULL);
st2->ss->free_super(st2);
if (info.array.level != info2.array.level ||
/* 7/ Is there enough devices to possibly start the array? */
/* 7a/ if not, finish with success. */
if (info.array.level == LEVEL_CONTAINER) {
- char *devname = NULL;
+ int devnum = devnum; /* defined and used iff ->external */
/* Try to assemble within the container */
map_unlock(&map);
sysfs_uevent(&info, "change");
chosen_name, info.array.working_disks);
wait_for(chosen_name, mdfd);
if (st->ss->external)
- devname = devnum2devname(fd2devnum(mdfd));
+ devnum = fd2devnum(mdfd);
close(mdfd);
sysfs_free(sra);
rv = Incremental(chosen_name, verbose, runstop,
- NULL, homehost, require_homehost, autof);
+ NULL, homehost, require_homehost, autof,
+ freeze_reshape);
if (rv == 1)
/* Don't fail the whole -I if a subarray didn't
* have enough devices to start yet
rv = 0;
/* after spare is added, ping monitor for external metadata
* so that it can eg. try to rebuild degraded array */
- if (st->ss->external) {
- ping_monitor(devname);
- free(devname);
- }
+ if (st->ss->external)
+ ping_monitor_by_id(devnum);
return rv;
}
int cnt = 0;
__u64 max_events = 0;
char *avail = NULL;
- int *best;
+ int *best = NULL;
char *devmap = NULL;
int numdevs = 0;
int devnum;
best[info.disk.raid_disk] = devnum;
st->ss->getinfo_super(st, bestinfo, NULL);
} else { /* info.events much bigger */
- memset(avail, 0, info.disk.raid_disk);
+ memset(avail, 0, raid_disks);
max_events = info.events;
avail[info.disk.raid_disk] = 2;
+ best[info.disk.raid_disk] = devnum;
st->ss->getinfo_super(st, bestinfo, NULL);
}
}
struct domainlist *dl = NULL;
struct mdinfo *sra;
unsigned long long devsize;
- unsigned long long component_size;
+ unsigned long long component_size = 0;
if (is_subarray(mp->metadata))
continue;
}
dl = domain_from_array(sra, st2->ss->name);
- if (!domain_test(dl, pol, st2->ss->name)) {
+ if (domain_test(dl, pol, st2->ss->name) != 1) {
/* domain test fails */
if (verbose > 1)
fprintf(stderr, Name ": not adding %s to %s as"
close(dfd);
*dfdp = -1;
rv = Manage_subdevs(chosen->sys_name, mdfd, &devlist,
- -1, 0, NULL);
+ -1, 0, NULL, 0);
close(mdfd);
}
if (verbose > 0) {
DIR *dir;
struct dirent *de;
char *chosen = NULL;
- unsigned long long chosen_size;
+ unsigned long long chosen_size = 0;
struct supertype *chosen_st = NULL;
int fd;
pol2 = path_policy(de->d_name, type_disk);
domain_merge(&domlist, pol2, st ? st->ss->name : NULL);
- if (domain_test(domlist, pol, st ? st->ss->name : NULL) == 0)
+ if (domain_test(domlist, pol, st ? st->ss->name : NULL) != 1)
/* new device is incompatible with this device. */
goto next;
domain_free(domlist);
domlist = NULL;
- asprintf(&devname, "/dev/disk/by-path/%s", de->d_name);
+ if (asprintf(&devname, "/dev/disk/by-path/%s", de->d_name) != 1) {
+ devname = NULL;
+ goto next;
+ }
fd = open(devname, O_RDONLY);
if (fd < 0)
goto next;
if (!st) {
/* Check domain policy again, this time referring to metadata */
domain_merge(&domlist, pol2, st2->ss->name);
- if (domain_test(domlist, pol, st2->ss->name) == 0)
+ if (domain_test(domlist, pol, st2->ss->name) != 1)
/* Incompatible devices for this metadata type */
goto next;
if (!policy_action_allows(pol, st2->ss->name, act_spare))
static int Incremental_container(struct supertype *st, char *devname,
char *homehost, int verbose,
- int runstop, int autof)
+ int runstop, int autof, int freeze_reshape)
{
/* Collect the contents of this container and for each
* array, choose a device name and assemble the array.
int trustworthy;
struct mddev_ident *match;
int rv = 0;
+ struct domainlist *domains;
+ struct map_ent *smp;
+ int suuid[4];
+ int sfd;
- memset(&info, 0, sizeof(info));
st->ss->getinfo_super(st, &info, NULL);
if ((runstop > 0 && info.container_enough >= 0) ||
fprintf(stderr, Name ": failed to get exclusive lock on "
"mapfile\n");
/* do not assemble arrays that might have bad blocks */
- if (list->array.state & (1<<MD_SB_BBM_ERRORS)) {
+ if (list && list->array.state & (1<<MD_SB_BBM_ERRORS)) {
fprintf(stderr, Name ": BBM log found in metadata. "
"Cannot activate array(s).\n");
- list = NULL;
+ /* free container data and exit */
+ sysfs_free(list);
+ map_unlock(&map);
+ return 2;
}
for (ra = list ; ra ; ra = ra->next) {
fprintf(stderr, Name ": array %s/%s is "
"explicitly ignored by mdadm.conf\n",
match->container, match->member);
+ map_unlock(&map);
return 2;
}
if (match)
if (mdfd < 0) {
fprintf(stderr, Name ": failed to open %s: %s.\n",
chosen_name, strerror(errno));
+ map_unlock(&map);
return 2;
}
assemble_container_content(st, mdfd, ra, runstop,
- chosen_name, verbose);
+ chosen_name, verbose, NULL,
+ freeze_reshape);
+ close(mdfd);
+ }
+
+ /* Now move all suitable spares from spare container */
+ domains = domain_from_array(list, st->ss->name);
+ memcpy(suuid, uuid_zero, sizeof(int[4]));
+ if (domains &&
+ (smp = map_by_uuid(&map, suuid)) != NULL &&
+ (sfd = open(smp->path, O_RDONLY)) >= 0) {
+ /* spare container found */
+ struct supertype *sst =
+ super_imsm.match_metadata_desc("imsm");
+ struct mdinfo *sinfo;
+ unsigned long long min_size = 0;
+ if (st->ss->min_acceptable_spare_size)
+ min_size = st->ss->min_acceptable_spare_size(st);
+ if (!sst->ss->load_container(sst, sfd, NULL)) {
+ close(sfd);
+ sinfo = container_choose_spares(sst, min_size,
+ domains, NULL,
+ st->ss->name, 0);
+ sst->ss->free_super(sst);
+ if (sinfo){
+ int count = 0;
+ struct mdinfo *disks = sinfo->devs;
+ while (disks) {
+ /* move spare from spare
+ * container to currently
+ * assembled one
+ */
+ if (move_spare(
+ smp->path,
+ devname,
+ makedev(disks->disk.major,
+ disks->disk.minor)))
+ count++;
+ disks = disks->next;
+ }
+ if (count)
+ fprintf(stderr, Name
+ ": Added %d spare%s to %s\n",
+ count, count>1?"s":"", devname);
+ }
+ sysfs_free(sinfo);
+ } else
+ close(sfd);
}
+ domain_free(domains);
map_unlock(&map);
return 0;
}
if (subfd >= 0) {
Manage_subdevs(memb->dev, subfd,
&devlist, verbose, 0,
- NULL);
+ NULL, 0);
close(subfd);
}
}
free_mdstat(mdstat);
} else
- Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL);
+ Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
devlist.disposition = 'r';
- rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL);
+ rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
close(mdfd);
free_mdstat(ent);
return rv;