int disks, int chunk, int level, int layout, int data,
int dests, int *destfd, unsigned long long *destoffsets);
-static int freeze_array(struct mdinfo *sra)
+static int freeze_container(struct supertype *st)
{
- /* Try to freeze resync on this array.
+ int container_dev = (st->container_dev != NoMdDev
+ ? st->container_dev : st->devnum);
+ char *container = devnum2devname(container_dev);
+
+ if (!container) {
+ fprintf(stderr, Name
+ ": could not determine container name, freeze aborted\n");
+ return -2;
+ }
+
+ if (block_monitor(container, 1)) {
+ fprintf(stderr, Name ": failed to freeze container\n");
+ return -2;
+ }
+
+ return 1;
+}
+
+static void unfreeze_container(struct supertype *st)
+{
+ int container_dev = (st->container_dev != NoMdDev
+ ? st->container_dev : st->devnum);
+ char *container = devnum2devname(container_dev);
+
+ if (!container) {
+ fprintf(stderr, Name
+ ": could not determine container name, unfreeze aborted\n");
+ return;
+ }
+
+ unblock_monitor(container, 1);
+}
+
+static int freeze(struct supertype *st)
+{
+ /* Try to freeze resync/rebuild on this array/container.
* Return -1 if the array is busy,
+ * return -2 container cannot be frozen,
* return 0 if this kernel doesn't support 'frozen'
* return 1 if it worked.
*/
- char buf[20];
- if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0)
- return 0;
- if (strcmp(buf, "idle\n") != 0 &&
- strcmp(buf, "frozen\n") != 0)
- return -1;
- if (sysfs_set_str(sra, NULL, "sync_action", "frozen") < 0)
- return 0;
- return 1;
+ if (st->ss->external)
+ return freeze_container(st);
+ else {
+ struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+ int err;
+
+ if (!sra)
+ return -1;
+ err = sysfs_freeze_array(sra);
+ sysfs_free(sra);
+ return err;
+ }
}
-static void unfreeze_array(struct mdinfo *sra, int frozen)
+static void unfreeze(struct supertype *st, int frozen)
{
/* If 'frozen' is 1, unfreeze the array */
- if (frozen > 0)
- sysfs_set_str(sra, NULL, "sync_action", "idle");
+ if (frozen <= 0)
+ return;
+
+ if (st->ss->external)
+ return unfreeze_container(st);
+ else {
+ struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+
+ if (sra)
+ sysfs_set_str(sra, NULL, "sync_action", "idle");
+ else
+ fprintf(stderr, Name ": failed to unfreeze array\n");
+ sysfs_free(sra);
+ }
}
static void wait_reshape(struct mdinfo *sra)
return;
}
+ if (st->ss->load_container(st, fd, NULL)) {
+ fprintf(stderr, Name
+ ": failed read metadata while aborting reshape\n");
+ return ;
+ }
+
+
for (e = ent; e; e = e->next) {
int level_fixed = 0, disks_fixed = 0;
- struct mdinfo *sub, prev;
+ struct mdinfo *sub, *prev;
+ char *subarray;
if (!is_container_member(e, container))
continue;
- st->ss->free_super(st);
- sprintf(st->subarray, "%s", to_subarray(e, container));
- if (st->ss->load_super(st, fd, NULL)) {
- fprintf(stderr, Name
- ": failed read metadata while aborting reshape\n");
- continue;
- }
- st->ss->getinfo_super(st, &prev);
+ subarray = to_subarray(e, container);
+ prev = st->ss->container_content(st, subarray);
/* changing level might change raid_disks so we do it
* first and then check if raid_disks still needs fixing
*/
- if (map_name(pers, e->level) != prev.array.level) {
+ if (map_name(pers, e->level) != prev->array.level) {
sub = sysfs_read(-1, e->devnum, GET_VERSION);
if (sub &&
- !sysfs_set_num(sub, NULL, "level", prev.array.level))
+ !sysfs_set_num(sub, NULL, "level", prev->array.level))
level_fixed = 1;
sysfs_free(sub);
} else
level_fixed = 1;
sub = sysfs_read(-1, e->devnum, GET_DISKS);
- if (sub && sub->array.raid_disks != prev.array.raid_disks) {
+ if (sub && sub->array.raid_disks != prev->array.raid_disks) {
if (!subarray_set_num(container, sub, "raid_disks",
- prev.array.raid_disks))
+ prev->array.raid_disks))
disks_fixed = 1;
} else if (sub)
disks_fixed = 1;
if (!disks_fixed || !level_fixed)
fprintf(stderr, Name
": failed to restore %s to a %d-disk %s array\n",
- e->dev, prev.array.raid_disks,
- map_num(pers, prev.array.level));
+ e->dev, prev->array.raid_disks,
+ map_num(pers, prev->array.level));
+ free(prev);
}
+ st->ss->free_super(st);
free_mdstat(ent);
}
*/
if (st->ss->external) {
int container_dev;
+ int rv;
if (subarray) {
container_dev = st->container_dev;
if (cfd < 0) {
fprintf(stderr, Name ": Unable to open container for %s\n",
devname);
+ free(subarray);
return 1;
}
container = devnum2devname(st->devnum);
if (!container) {
fprintf(stderr, Name ": Could not determine container name\n");
+ free(subarray);
return 1;
}
- if (st->ss->load_super(st, cfd, NULL)) {
+ if (subarray)
+ rv = st->ss->load_container(st, cfd, NULL);
+ else
+ rv = st->ss->load_super(st, cfd, NULL);
+ if (rv) {
fprintf(stderr, Name ": Cannot read superblock for %s\n",
devname);
+ free(subarray);
return 1;
}
sra = sysfs_read(fd, 0, GET_LEVEL);
if (sra) {
- if (st->ss->external && st->subarray[0] == 0) {
+ if (st->ss->external && subarray == NULL) {
array.level = LEVEL_CONTAINER;
sra->array.level = LEVEL_CONTAINER;
}
- frozen = freeze_array(sra);
} else {
fprintf(stderr, Name ": failed to read sysfs parameters for %s\n",
devname);
return 1;
}
- if (frozen < 0) {
+ frozen = freeze(st);
+ if (frozen < -1) {
+ /* freeze() already spewed the reason */
+ return 1;
+ } else if (frozen < 0) {
fprintf(stderr, Name ": %s is performing resync/recovery and cannot"
" be reshaped\n", devname);
return 1;
}
-
/* ========= set size =============== */
if (size >= 0 && (size == 0 || size != array.size)) {
long long orig_size = array.size;
if (c && sysfs_set_str(sra, NULL, "level", c) == 0)
fprintf(stderr, Name ": aborting level change\n");
}
- if (sra)
- unfreeze_array(sra, frozen);
+ unfreeze(st, frozen);
return rv;
}