st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
+ if (tst)
+ tst->ss->free_super(tst);
return -1;
}
struct supertype *tst;
int i;
int dfd;
+ int disk_state;
if (tmpdev->used != 1)
continue;
if (strcmp(c->update, "ppl") == 0 &&
ident->bitmap_fd >= 0) {
pr_err("PPL is not compatible with bitmap\n");
+ close(mdfd);
+ free(devices);
+ free(devmap);
return -1;
}
devices[devcnt].i.disk.major = major(stb.st_rdev);
devices[devcnt].i.disk.minor = minor(stb.st_rdev);
- if (devices[devcnt].i.disk.state == 6) {
+ disk_state = devices[devcnt].i.disk.state & ~((1<<MD_DISK_FAILFAST) |
+ (1<<MD_DISK_WRITEMOSTLY));
+ if (disk_state == ((1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC))) {
if (most_recent < 0 ||
devices[devcnt].i.events
> devices[most_recent].i.events) {
if (best[i] == -1 || (devices[best[i]].i.events
< devices[devcnt].i.events))
best[i] = devcnt;
+ else if (st->ss == &super_imsm)
+ best[i+1] = devcnt;
}
devcnt++;
}
current_events = devices[chosen_drive].i.events;
add_another:
if (c->verbose >= 0)
- pr_err("forcing event count in %s(%d) from %d upto %d\n",
+ pr_err("forcing event count in %s(%d) from %d up to %d\n",
devices[chosen_drive].devname,
devices[chosen_drive].i.disk.raid_disk,
(int)(devices[chosen_drive].i.events),
* START_ARRAY
*
*/
- int rv;
- int mdfd;
+ int rv = -1;
+ int mdfd = -1;
int clean;
int auto_assem = (mddev == NULL && !ident->uuid_set &&
ident->super_minor == UnSet && ident->name[0] == 0 &&
(ident->container == NULL || ident->member == NULL));
- struct devs *devices;
+ struct devs *devices = NULL;
char *devmap;
int *best = NULL; /* indexed by raid_disk */
int bestcnt = 0;
char chosen_name[1024];
struct map_ent *map = NULL;
struct map_ent *mp;
- int locked = 0;
- struct mdp_superblock_1 *sb;
- bitmap_super_t *bms;
/*
* If any subdevs are listed, then any that don't
* set of devices failed. Those are now marked as ->used==2 and
* we ignore them and try again
*/
- if (locked)
- /*
- * if come back try_again is called, then need to unlock first,
- * and lock again since the metadate is re-read.
- */
- cluster_release_dlmlock();
if (!st && ident->st)
st = ident->st;
if (c->verbose>0)
if (!st || !st->sb || !content)
return 2;
- sb = st->sb;
- bms = (bitmap_super_t*)(((char*)sb) + 4096);
- if (sb && bms->version == BITMAP_MAJOR_CLUSTERED) {
- locked = cluster_get_dlmlock();
- if (locked != 1)
- return 1;
- }
-
/* We have a full set of devices - we now need to find the
* array device.
* However there is a risk that we are racing with "mdadm -I"
pr_err("Found some drive for an array that is already active: %s\n",
mp->path);
pr_err("giving up.\n");
- if (locked == 1)
- cluster_release_dlmlock();
- return 1;
+ goto out;
}
for (dv = pre_exist->devs; dv; dv = dv->next) {
/* We want to add this device to our list,
st->ss->free_super(st);
if (auto_assem)
goto try_again;
- if (locked == 1)
- cluster_release_dlmlock();
- return 1;
+ goto out;
}
mddev = chosen_name;
if (pre_exist == NULL) {
st->ss->free_super(st);
if (auto_assem)
goto try_again;
- if (locked == 1)
- cluster_release_dlmlock();
- return 1;
+ goto out;
}
/* just incase it was started but has no content */
ioctl(mdfd, STOP_ARRAY, NULL);
err = assemble_container_content(st, mdfd, content, c,
chosen_name, NULL);
close(mdfd);
- if (locked == 1)
- cluster_release_dlmlock();
return err;
}
c, content, mdfd, mddev,
&most_recent, &bestcnt, &best, inargv);
if (devcnt < 0) {
- if (locked == 1)
- cluster_release_dlmlock();
- return 1;
+ mdfd = -3;
+ /*
+ * devices is already freed in load_devices, so set devices
+ * to NULL to avoid double free devices.
+ */
+ devices = NULL;
+ goto out;
}
if (devcnt == 0) {
mddev);
if (st)
st->ss->free_super(st);
- close(mdfd);
- free(devices);
free(devmap);
- return 1;
+ goto out;
}
if (c->update && strcmp(c->update, "byteorder")==0)
: (O_RDONLY|O_EXCL)))< 0) {
pr_err("Cannot open %s: %s\n",
devices[j].devname, strerror(errno));
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
if (st->ss->load_super(st,fd, NULL)) {
close(fd);
pr_err("RAID superblock has disappeared from %s\n",
devices[j].devname);
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
close(fd);
}
if (st->sb == NULL) {
pr_err("No suitable drives found for %s\n", mddev);
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
st->ss->getinfo_super(st, content, NULL);
if (sysfs_init(content, mdfd, NULL)) {
pr_err("Unable to initialize sysfs\n");
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
/* after reload context, store journal_clean in context */
else
desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
+ desired_state |= devices[j].i.disk.state & ((1<<MD_DISK_FAILFAST) |
+ (1<<MD_DISK_WRITEMOSTLY));
+
if (!devices[j].uptodate)
continue;
if (fd < 0) {
pr_err("Could not open %s for write - cannot Assemble array.\n",
devices[chosen_drive].devname);
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
if (st->ss->store_super(st, fd)) {
close(fd);
pr_err("Could not re-write superblock on %s\n",
devices[chosen_drive].devname);
- close(mdfd);
- free(devices);
- return 1;
+ goto out;
}
if (c->verbose >= 0)
pr_err("Marking array %s as 'clean'\n",
pr_err("Failed to restore critical section for reshape, sorry.\n");
if (c->backup_file == NULL)
cont_err("Possibly you needed to specify the --backup-file\n");
- close(mdfd);
- free(devices);
- return err;
+ goto out;
}
}
if (rv == 1 && !pre_exist)
ioctl(mdfd, STOP_ARRAY, NULL);
free(devices);
+out:
map_unlock(&map);
if (rv == 0) {
wait_for(chosen_name, mdfd);
usecs <<= 1;
}
}
- } else
+ } else if (mdfd >= 0)
close(mdfd);
/* '2' means 'OK, but not started yet' */
- if (locked == 1)
- cluster_release_dlmlock();
+ if (rv == -1) {
+ free(devices);
+ return 1;
+ }
return rv == 2 ? 0 : rv;
}
spare, &c->backup_file, c->verbose) == 1)
return 1;
- err = sysfs_set_str(content, NULL,
- "array_state", "readonly");
+ if (content->reshape_progress == 0) {
+ /* If reshape progress is 0 - we are assembling the
+ * array that was stopped, before reshape has started.
+ * Array needs to be started as active, Grow_continue()
+ * will start the reshape.
+ */
+ sysfs_set_num(content, NULL, "reshape_position",
+ MaxSector);
+ err = sysfs_set_str(content, NULL,
+ "array_state", "active");
+ sysfs_set_num(content, NULL, "reshape_position", 0);
+ } else {
+ err = sysfs_set_str(content, NULL,
+ "array_state", "readonly");
+ }
+
if (err)
return 1;