"with %s metadata\n", st->ss->name);
return 1;
}
- mdi = sysfs_read(fd, -1, GET_BITMAP_LOCATION);
+ mdi = sysfs_read(fd, NULL, GET_BITMAP_LOCATION);
if (mdi)
offset_setable = 1;
for (d=0; d< st->max_devs; d++) {
}
if (offset_setable) {
st->ss->getinfo_super(st, mdi, NULL);
- sysfs_init(mdi, fd, -1);
+ sysfs_init(mdi, fd, NULL);
rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
mdi->bitmap_offset);
} else {
/* Check that all member arrays for this container, or the
* container of this array, are idle
*/
- int container_dev = (st->container_dev != NoMdDev
- ? st->container_dev : st->devnum);
- char container[40];
+ char *container = (st->container_devnm[0]
+ ? st->container_devnm : st->devnm);
struct mdstat_ent *ent, *e;
int is_idle = 1;
- fmt_devname(container, container_dev);
ent = mdstat_read(0, 0);
for (e = ent ; e; e = e->next) {
if (!is_container_member(e, container))
static int freeze_container(struct supertype *st)
{
- int container_dev = (st->container_dev != NoMdDev
- ? st->container_dev : st->devnum);
- char container[40];
+ char *container = (st->container_devnm[0]
+ ? st->container_devnm : st->devnm);
if (!check_idle(st))
return -1;
- fmt_devname(container, container_dev);
-
if (block_monitor(container, 1)) {
pr_err("failed to freeze container\n");
return -2;
static void unfreeze_container(struct supertype *st)
{
- int container_dev = (st->container_dev != NoMdDev
- ? st->container_dev : st->devnum);
- char container[40];
-
- fmt_devname(container, container_dev);
+ char *container = (st->container_devnm[0]
+ ? st->container_devnm : st->devnm);
unblock_monitor(container, 1);
}
if (st->ss->external)
return freeze_container(st);
else {
- struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+ struct mdinfo *sra = sysfs_read(-1, st->devnm, GET_VERSION);
int err;
char buf[20];
if (st->ss->external)
return unfreeze_container(st);
else {
- struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+ struct mdinfo *sra = sysfs_read(-1, st->devnm, GET_VERSION);
if (sra)
sysfs_set_str(sra, NULL, "sync_action", "idle");
switch (re->level) {
case 4:
+ re->before.layout = 0;
re->after.layout = 0;
break;
case 5:
switch (re->level) {
case 4:
+ re->before.layout = 0;
re->after.layout = 0;
break;
case 5:
if (re->after.data_disks == re->before.data_disks &&
re->after.layout == re->before.layout &&
info->new_chunk == info->array.chunk_size) {
- /* Nothing to change */
+ /* Nothing to change, can change level immediately. */
+ re->level = info->new_level;
re->backup_blocks = 0;
return NULL;
}
if (re->after.data_disks == 1 && re->before.data_disks == 1) {
/* chunk and layout changes make no difference */
+ re->level = info->new_level;
re->backup_blocks = 0;
return NULL;
}
int frozen;
int changed = 0;
char *container = NULL;
- char container_buf[20];
int cfd = -1;
struct mddev_dev *dv;
* pre-requisite spare devices (mdmon owns final validation)
*/
if (st->ss->external) {
- int container_dev;
int rv;
if (subarray) {
- container_dev = st->container_dev;
- cfd = open_dev_excl(st->container_dev);
+ container = st->container_devnm;
+ cfd = open_dev_excl(st->container_devnm);
} else {
- container_dev = st->devnum;
+ container = st->devnm;
close(fd);
- cfd = open_dev_excl(st->devnum);
+ cfd = open_dev_excl(st->devnm);
fd = cfd;
}
if (cfd < 0) {
return 1;
}
- fmt_devname(container_buf, container_dev);
- container = container_buf;
-
rv = st->ss->load_container(st, cfd, NULL);
if (rv) {
pr_err("cannot reshape arrays in"
" container with unsupported"
" metadata: %s(%s)\n",
- devname, container_buf);
+ devname, container);
sysfs_free(cc);
free(subarray);
return 1;
}
sysfs_free(cc);
}
- if (mdmon_running(container_dev))
+ if (mdmon_running(container))
st->update_tail = &st->updates;
}
return 1;
}
- sra = sysfs_read(fd, 0, GET_LEVEL | GET_DISKS | GET_DEVS
+ sra = sysfs_read(fd, NULL, GET_LEVEL | GET_DISKS | GET_DEVS
| GET_STATE | GET_VERSION);
if (sra) {
if (st->ss->external && subarray == NULL) {
}
/* make sure mdmon is
* aware of the new level */
- if (!mdmon_running(st->container_dev))
- start_mdmon(st->container_dev);
+ if (!mdmon_running(st->container_devnm))
+ start_mdmon(st->container_devnm);
ping_monitor(container);
- if (mdmon_running(st->container_dev) &&
+ if (mdmon_running(st->container_devnm) &&
st->update_tail == NULL)
st->update_tail = &st->updates;
}
memset(&info, 0, sizeof(info));
info.array = array;
- sysfs_init(&info, fd, NoMdDev);
+ sysfs_init(&info, fd, NULL);
strcpy(info.text_version, sra->text_version);
info.component_size = s->size*2;
info.new_level = s->level;
return ret_val;
}
-static int raid10_reshape(char *container, int fd, char *devname,
- struct supertype *st, struct mdinfo *info,
- struct reshape *reshape,
- unsigned long long data_offset,
- int force, int verbose)
+static int set_new_data_offset(struct mdinfo *sra, struct supertype *st,
+ char *devname, int delta_disks,
+ unsigned long long data_offset,
+ unsigned long long min)
{
- /* Changing raid_disks, layout, chunksize or possibly
- * just data_offset for a RAID10.
- * We must always change data_offset. We change by at least
- * ->backup_blocks which is the largest of the old and new
- * chunk sizes.
- * If raid_disks is increasing, then data_offset must decrease
- * by at least this copy size.
- * If raid_disks is unchanged, data_offset must increase or
- * decrease by at least backup_blocks but preferably by much more.
- * We choose half of the available space.
- * If raid_disks is decreasing, data_offset must increase by
- * at least backup_blocks. To allow of this, component_size
- * must be decreased by the same amount.
- *
- * So we calculate the required minimum and direction, possibly
- * reduce the component_size, then iterate through the devices
- * and set the new_data_offset.
- * If that all works, we set chunk_size, layout, raid_disks, and start
- * 'reshape'
- */
- struct mdinfo *sra, *sd;
- unsigned long long min;
+ struct mdinfo *sd;
int dir = 0;
int err = 0;
- sra = sysfs_read(fd, 0,
- GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|GET_CHUNK
- );
- if (!sra) {
- fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n",
- devname);
- goto release;
- }
- min = reshape->backup_blocks;
-
- if (info->delta_disks)
- sysfs_set_str(sra, NULL, "reshape_direction",
- info->delta_disks < 0 ? "backwards" : "forwards");
- if (info->delta_disks < 0 &&
- info->space_after < reshape->backup_blocks) {
- int rv = sysfs_set_num(sra, NULL, "component_size",
- (sra->component_size -
- reshape->backup_blocks)/2);
- if (rv) {
- fprintf(stderr, Name ": cannot reduce component size\n");
- goto release;
- }
- }
for (sd = sra->devs; sd; sd = sd->next) {
char *dn;
int dfd;
st2->ss->getinfo_super(st2, &info2, NULL);
st2->ss->free_super(st2);
free(st2);
- if (info->delta_disks < 0) {
+ if (delta_disks < 0) {
/* Don't need any space as array is shrinking
* just move data_offset up by min
*/
- if (data_offset == 1)
+ if (data_offset == INVALID_SECTORS)
info2.new_data_offset = info2.data_offset + min;
else {
if ((unsigned long long)data_offset
}
info2.new_data_offset = data_offset;
}
- } else if (info->delta_disks > 0) {
+ } else if (delta_disks > 0) {
/* need space before */
if (info2.space_before < min) {
fprintf(stderr, Name ": Insufficient head-space for reshape on %s\n",
dn);
goto release;
}
- if (data_offset == 1)
+ if (data_offset == INVALID_SECTORS)
info2.new_data_offset = info2.data_offset - min;
else {
if ((unsigned long long)data_offset
* might guide us, otherwise choose
* direction with most space
*/
- if (data_offset == 1) {
+ if (data_offset == INVALID_SECTORS) {
if (info2.space_before > info2.space_after)
dir = -1;
else
dn);
goto release;
}
- if (data_offset != 1 &&
+ if (data_offset != INVALID_SECTORS &&
data_offset < info2.data_offset + min) {
fprintf(stderr, Name ": --data-offset too small on %s\n",
dn);
goto release;
}
- if (data_offset != 1)
+ if (data_offset != INVALID_SECTORS)
info2.new_data_offset = data_offset;
else {
unsigned long long off =
dn);
goto release;
}
- if (data_offset != 1 &&
+ if (data_offset != INVALID_SECTORS &&
data_offset < info2.data_offset - min) {
fprintf(stderr, Name ": --data-offset too small on %s\n",
dn);
goto release;
}
- if (data_offset != 1)
+ if (data_offset != INVALID_SECTORS)
info2.new_data_offset = data_offset;
else {
unsigned long long off =
break;
}
}
+ return err;
+release:
+ return -1;
+}
+
+static int raid10_reshape(char *container, int fd, char *devname,
+ struct supertype *st, struct mdinfo *info,
+ struct reshape *reshape,
+ unsigned long long data_offset,
+ int force, int verbose)
+{
+ /* Changing raid_disks, layout, chunksize or possibly
+ * just data_offset for a RAID10.
+ * We must always change data_offset. We change by at least
+ * ->backup_blocks which is the largest of the old and new
+ * chunk sizes.
+ * If raid_disks is increasing, then data_offset must decrease
+ * by at least this copy size.
+ * If raid_disks is unchanged, data_offset must increase or
+ * decrease by at least backup_blocks but preferably by much more.
+ * We choose half of the available space.
+ * If raid_disks is decreasing, data_offset must increase by
+ * at least backup_blocks. To allow of this, component_size
+ * must be decreased by the same amount.
+ *
+ * So we calculate the required minimum and direction, possibly
+ * reduce the component_size, then iterate through the devices
+ * and set the new_data_offset.
+ * If that all works, we set chunk_size, layout, raid_disks, and start
+ * 'reshape'
+ */
+ struct mdinfo *sra;
+ unsigned long long min;
+ int err = 0;
+
+ sra = sysfs_read(fd, NULL,
+ GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|GET_CHUNK
+ );
+ if (!sra) {
+ fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n",
+ devname);
+ goto release;
+ }
+ min = reshape->backup_blocks;
+
+ if (info->delta_disks)
+ sysfs_set_str(sra, NULL, "reshape_direction",
+ info->delta_disks < 0 ? "backwards" : "forwards");
+ if (info->delta_disks < 0 &&
+ info->space_after < reshape->backup_blocks) {
+ int rv = sysfs_set_num(sra, NULL, "component_size",
+ (sra->component_size -
+ reshape->backup_blocks)/2);
+ if (rv) {
+ fprintf(stderr, Name ": cannot reduce component size\n");
+ goto release;
+ }
+ }
+ err = set_new_data_offset(sra, st, devname, info->delta_disks, data_offset,
+ min);
+ if (err < 0)
+ goto release;
+
if (!err && sysfs_set_num(sra, NULL, "chunk_size", info->new_chunk) < 0)
err = errno;
if (!err && sysfs_set_num(sra, NULL, "layout", reshape->after.layout) < 0)
unsigned long long min_space_before = 0, min_space_after = 0;
int first = 1;
- sra = sysfs_read(fd, 0, GET_DEVS);
+ sra = sysfs_read(fd, NULL, GET_DEVS);
if (!sra)
return;
for (sd = sra->devs; sd; sd = sd->next) {
if (reshape.level > 0 && st->ss->external) {
/* make sure mdmon is aware of the new level */
- if (mdmon_running(st->container_dev))
+ if (mdmon_running(container))
flush_mdmon(container);
- if (!mdmon_running(st->container_dev))
- start_mdmon(st->container_dev);
+ if (!mdmon_running(container))
+ start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(st->container_dev) &&
+ if (mdmon_running(container) &&
st->update_tail == NULL)
st->update_tail = &st->updates;
}
struct mdinfo *d;
if (info2) {
- sysfs_init(info2, fd, st->devnum);
+ sysfs_init(info2, fd, st->devnm);
/* When increasing number of devices, we need to set
* new raid_disks before adding these, or they might
* be rejected.
&reshape, data_offset,
force, verbose);
}
- sra = sysfs_read(fd, 0,
+ sra = sysfs_read(fd, NULL,
GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|GET_CHUNK|
GET_CACHE);
if (!sra) {
delayed = 0;
mds = mdstat_read(0, 0);
for (m = mds; m; m = m->next)
- if (m->devnum == devname2devnum(sra->sys_name)) {
+ if (strcmp(m->devnm, sra->sys_name) == 0) {
if (m->resync &&
m->percent == RESYNC_DELAYED)
delayed = 1;
if (st->ss->external) {
/* Re-load the metadata as much could have changed */
- int cfd = open_dev(st->container_dev);
+ int cfd = open_dev(st->container_devnm);
if (cfd >= 0) {
flush_mdmon(container);
st->ss->free_super(st);
{
struct mdinfo *cc = NULL;
int rv = restart;
- int last_devnum = -1;
+ char last_devnm[32] = "";
/* component_size is not meaningful for a container,
* so pass '0' meaning 'no change'
int fd;
struct mdstat_ent *mdstat;
char *adev;
+ int devid;
sysfs_free(cc);
continue;
subarray = strchr(content->text_version+1, '/')+1;
- mdstat = mdstat_by_subdev(subarray,
- devname2devnum(container));
+ mdstat = mdstat_by_subdev(subarray, container);
if (!mdstat)
continue;
if (mdstat->active == 0) {
- pr_err("Skipping inactive "
- "array md%i.\n", mdstat->devnum);
+ pr_err("Skipping inactive array %s.\n",
+ mdstat->devnm);
free_mdstat(mdstat);
mdstat = NULL;
continue;
if (!content)
break;
- adev = map_dev(dev2major(mdstat->devnum),
- dev2minor(mdstat->devnum),
- 0);
+ devid = devnm2devid(mdstat->devnm);
+ adev = map_dev(major(devid), minor(devid), 0);
if (!adev)
adev = content->text_version;
- fd = open_dev(mdstat->devnum);
+ fd = open_dev(mdstat->devnm);
if (fd < 0) {
printf(Name ": Device %s cannot be opened for reshape.",
adev);
break;
}
- if (last_devnum == mdstat->devnum) {
+ if (strcmp(last_devnm, mdstat->devnm) == 0) {
/* Do not allow for multiple reshape_array() calls for
* the same array.
* It can happen when reshape_array() returns without
close(fd);
break;
}
- last_devnum = mdstat->devnum;
+ strcpy(last_devnm, mdstat->devnm);
- sysfs_init(content, fd, mdstat->devnum);
+ sysfs_init(content, fd, mdstat->devnm);
- if (mdmon_running(devname2devnum(container)))
+ if (mdmon_running(container))
flush_mdmon(container);
rv = reshape_array(container, fd, adev, st,
if (rv)
break;
- if (mdmon_running(devname2devnum(container)))
+ if (mdmon_running(container))
flush_mdmon(container);
}
if (!rv)
char *subarray = NULL;
struct mdinfo *cc = NULL;
struct mdstat_ent *mdstat = NULL;
- char buf[40];
int cfd = -1;
int fd2 = -1;
}
st->ss->getinfo_super(st, content, NULL);
} else {
- int container_dev;
+ char *container;
if (subarray) {
dprintf("subarray (%s)\n", subarray);
- container_dev = st->container_dev;
- cfd = open_dev_excl(st->container_dev);
+ container = st->container_devnm;
+ cfd = open_dev_excl(st->container_devnm);
} else {
- container_dev = st->devnum;
+ container = st->devnm;
close(fd);
- cfd = open_dev_excl(st->devnum);
- dprintf("container (%i)\n", container_dev);
+ cfd = open_dev_excl(st->devnm);
+ dprintf("container (%s)\n", container);
fd = cfd;
}
if (cfd < 0) {
ret_val = 1;
goto Grow_continue_command_exit;
}
- fmt_devname(buf, container_dev);
/* find in container array under reshape
*/
pr_err("cannot continue reshape of an array"
" in container with unsupported"
" metadata: %s(%s)\n",
- devname, buf);
+ devname, container);
ret_val = 1;
goto Grow_continue_command_exit;
}
array = strchr(content->text_version+1, '/')+1;
- mdstat = mdstat_by_subdev(array, container_dev);
+ mdstat = mdstat_by_subdev(array, container);
if (!mdstat)
continue;
if (mdstat->active == 0) {
- pr_err("Skipping inactive "
- "array md%i.\n", mdstat->devnum);
+ pr_err("Skipping inactive array %s.\n",
+ mdstat->devnm);
free_mdstat(mdstat);
mdstat = NULL;
continue;
ret_val = 1;
goto Grow_continue_command_exit;
}
- fd2 = open_dev(mdstat->devnum);
+ fd2 = open_dev(mdstat->devnm);
if (fd2 < 0) {
- pr_err("cannot open (md%i)\n",
- mdstat->devnum);
+ pr_err("cannot open (%s)\n", mdstat->devnm);
ret_val = 1;
goto Grow_continue_command_exit;
}
- sysfs_init(content, fd2, mdstat->devnum);
+ sysfs_init(content, fd2, mdstat->devnm);
/* start mdmon in case it is not running
*/
- if (!mdmon_running(container_dev))
- start_mdmon(container_dev);
- ping_monitor(buf);
+ if (!mdmon_running(container))
+ start_mdmon(container);
+ ping_monitor(container);
- if (mdmon_running(container_dev))
+ if (mdmon_running(container))
st->update_tail = &st->updates;
else {
pr_err("No mdmon found. "
return ret_val;
if (st->ss->external) {
- char container[40];
- int cfd = open_dev(st->container_dev);
+ int cfd = open_dev(st->container_devnm);
if (cfd < 0)
return 1;
- fmt_devname(container, st->container_dev);
- st->ss->load_container(st, cfd, container);
+ st->ss->load_container(st, cfd, st->container_devnm);
close(cfd);
- ret_val = reshape_container(container, NULL, mdfd,
+ ret_val = reshape_container(st->container_devnm, NULL, mdfd,
st, info, 0, backup_file,
0, 1, freeze_reshape);
} else