#include <sys/mman.h>
#include <stddef.h>
#include <stdint.h>
-#include <signal.h>
#include <sys/wait.h>
#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
info.disk.minor = minor(rdev);
info.disk.raid_disk = d;
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
- st->ss->update_super(st, &info, "linear-grow-new", newdev, 0, 0, NULL);
+ if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_NEW, newdev,
+ 0, 0, NULL) != 0) {
+ pr_err("Preparing new metadata failed on %s\n", newdev);
+ close(nfd);
+ return 1;
+ }
if (st->ss->store_super(st, nfd)) {
pr_err("Cannot store new superblock on %s\n", newdev);
if (st->ss->load_super(st, fd2, NULL)) {
pr_err("cannot find super block on %s\n", dv);
close(fd);
+ close(fd2);
return 1;
}
info.array.raid_disks = nd+1;
info.array.active_disks = nd+1;
info.array.working_disks = nd+1;
- st->ss->update_super(st, &info, "linear-grow-update", dv,
- 0, 0, NULL);
+ if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_UPDATE, dv,
+ 0, 0, NULL) != 0) {
+ pr_err("Updating metadata failed on %s\n", dv);
+ close(fd2);
+ return 1;
+ }
if (st->ss->store_super(st, fd2)) {
pr_err("Cannot store new superblock on %s\n", dv);
return 1;
}
if (bmf.pathname[0]) {
- if (strcmp(s->bitmap_file,"none") == 0) {
+ if (str_is_none(s->bitmap_file) == true) {
if (ioctl(fd, SET_BITMAP_FILE, -1) != 0) {
pr_err("failed to remove bitmap %s\n",
bmf.pathname);
return 1;
}
if (array.state & (1 << MD_SB_BITMAP_PRESENT)) {
- if (strcmp(s->bitmap_file, "none")==0) {
+ if (str_is_none(s->bitmap_file) == true) {
array.state &= ~(1 << MD_SB_BITMAP_PRESENT);
if (md_set_array_info(fd, &array) != 0) {
if (array.state & (1 << MD_SB_CLUSTERED))
return 1;
}
- if (strcmp(s->bitmap_file, "none") == 0) {
+ if (str_is_none(s->bitmap_file) == true) {
pr_err("no bitmap found on %s\n", devname);
return 1;
}
dv = map_dev(disk.major, disk.minor, 1);
if (!dv)
continue;
+ if ((disk.state & (1 << MD_DISK_WRITEMOSTLY)) &&
+ (strcmp(s->bitmap_file, "clustered") == 0)) {
+ pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname);
+ free(mdi);
+ return 1;
+ }
fd2 = dev_open(dv, O_RDWR);
if (fd2 < 0)
continue;
pr_err("failed to load super-block.\n");
}
close(fd2);
- if (rv)
+ if (rv) {
+ free(mdi);
return 1;
+ }
}
if (offset_setable) {
st->ss->getinfo_super(st, mdi, NULL);
if (sysfs_init(mdi, fd, NULL)) {
- pr_err("failed to intialize sysfs.\n");
+ pr_err("failed to initialize sysfs.\n");
free(mdi);
}
rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
char *subarray = NULL;
int ret = 0;
char container_dev[PATH_MAX];
- char buf[20];
+ char buf[SYSFS_MAX_BUF_SIZE];
if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
s->consistency_policy != CONSISTENCY_POLICY_PPL) {
pr_err("Operation not supported for consistency policy %s\n",
- map_num(consistency_policies, s->consistency_policy));
+ map_num_s(consistency_policies, s->consistency_policy));
return 1;
}
if (sra->consistency_policy == (unsigned)s->consistency_policy) {
pr_err("Consistency policy is already %s\n",
- map_num(consistency_policies, s->consistency_policy));
+ map_num_s(consistency_policies, s->consistency_policy));
ret = 1;
goto free_info;
} else if (sra->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
sra->consistency_policy != CONSISTENCY_POLICY_PPL) {
pr_err("Current consistency policy is %s, cannot change to %s\n",
- map_num(consistency_policies, sra->consistency_policy),
- map_num(consistency_policies, s->consistency_policy));
+ map_num_s(consistency_policies, sra->consistency_policy),
+ map_num_s(consistency_policies, s->consistency_policy));
ret = 1;
goto free_info;
}
if (s->consistency_policy == CONSISTENCY_POLICY_PPL) {
- if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0) {
+ if (sysfs_get_str(sra, NULL, "sync_action", buf, sizeof(buf)) <= 0) {
ret = 1;
goto free_info;
} else if (strcmp(buf, "reshape\n") == 0) {
}
if (subarray) {
- char *update;
+ enum update_opt update;
if (s->consistency_policy == CONSISTENCY_POLICY_PPL)
- update = "ppl";
+ update = UOPT_PPL;
else
- update = "no-ppl";
+ update = UOPT_NO_PPL;
sprintf(container_dev, "/dev/%s", st->container_devnm);
goto free_info;
}
- ret = st->ss->update_super(st, sra, "ppl",
+ ret = st->ss->update_super(st, sra, UOPT_PPL,
devname,
c->verbose, 0, NULL);
if (ret) {
}
ret = sysfs_set_str(sra, NULL, "consistency_policy",
- map_num(consistency_policies,
- s->consistency_policy));
+ map_num_s(consistency_policies,
+ s->consistency_policy));
if (ret)
pr_err("Failed to change array consistency policy\n");
for (e = ent ; e; e = e->next) {
if (!is_container_member(e, container))
continue;
- if (e->percent >= 0) {
+ /* frozen array is not idle*/
+ if (e->percent >= 0 || e->metadata_version[9] == '-') {
is_idle = 0;
break;
}
else {
struct mdinfo *sra = sysfs_read(-1, st->devnm, GET_VERSION);
int err;
- char buf[20];
+ char buf[SYSFS_MAX_BUF_SIZE];
if (!sra)
return -1;
/* Need to clear any 'read-auto' status */
- if (sysfs_get_str(sra, NULL, "array_state", buf, 20) > 0 &&
+ if (sysfs_get_str(sra, NULL, "array_state", buf, sizeof(buf)) > 0 &&
strncmp(buf, "read-auto", 9) == 0)
sysfs_set_str(sra, NULL, "array_state", "clean");
return unfreeze_container(st);
else {
struct mdinfo *sra = sysfs_read(-1, st->devnm, GET_VERSION);
- char buf[20];
+ char buf[SYSFS_MAX_BUF_SIZE];
if (sra &&
- sysfs_get_str(sra, NULL, "sync_action", buf, 20) > 0 &&
+ sysfs_get_str(sra, NULL, "sync_action", buf, sizeof(buf)) > 0 &&
strcmp(buf, "frozen\n") == 0)
sysfs_set_str(sra, NULL, "sync_action", "idle");
sysfs_free(sra);
static void wait_reshape(struct mdinfo *sra)
{
int fd = sysfs_get_fd(sra, NULL, "sync_action");
- char action[20];
+ char action[SYSFS_MAX_BUF_SIZE];
if (fd < 0)
return;
- while (sysfs_fd_get_str(fd, action, 20) > 0 &&
+ while (sysfs_fd_get_str(fd, action, sizeof(action)) > 0 &&
strncmp(action, "reshape", 7) == 0)
sysfs_wait(fd, NULL);
close(fd);
* to close a race with the array_state going clean before the
* next write to raid_disks / stripe_cache_size
*/
- char safe[50];
+ char safe[SYSFS_MAX_BUF_SIZE];
int rc;
/* only 'raid_disks' and 'stripe_cache_size' trigger md_allow_write */
}
int start_reshape(struct mdinfo *sra, int already_running,
- int before_data_disks, int data_disks)
+ int before_data_disks, int data_disks, struct supertype *st)
{
int err;
unsigned long long sync_max_to_set;
else
sync_max_to_set = (sra->component_size * data_disks
- sra->reshape_progress) / data_disks;
+
if (!already_running)
sysfs_set_num(sra, NULL, "sync_min", sync_max_to_set);
- err = err ?: sysfs_set_num(sra, NULL, "sync_max", sync_max_to_set);
+
+ if (st->ss->external)
+ err = err ?: sysfs_set_num(sra, NULL, "sync_max", sync_max_to_set);
+ else
+ err = err ?: sysfs_set_str(sra, NULL, "sync_max", "max");
+
if (!already_running && err == 0) {
int cnt = 5;
do {
err = sysfs_set_str(sra, NULL, "sync_action",
"reshape");
if (err)
- sleep(1);
+ sleep_for(1, 0, true);
} while (err && errno == EBUSY && cnt-- > 0);
}
return err;
rv = 1;
sysfs_free(arrays);
if (rv) {
- pr_err("Error. Cannot perform operation on /dev/%s\n", st->devnm);
- pr_err("For this operation it MUST be single array in container\n");
+ pr_err("Error. Cannot perform operation on %s- for this operation "
+ "it MUST be single array in container\n", st->devnm);
return rv;
}
}
remaining = sd->next;
sysfs_set_str(sra, sd, "state", "faulty");
- sysfs_set_str(sra, sd, "slot", "none");
+ sysfs_set_str(sra, sd, "slot", STR_COMMON_NONE);
/* for external metadata disks should be removed in mdmon */
if (!st->ss->external)
sysfs_set_str(sra, sd, "state", "remove");
/* Find GCD */
a = GCD(a, b);
/* LCM == product / GCD */
- blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a;
+ blocks = (unsigned long)(ochunk/512) * (unsigned long)(nchunk/512) *
+ odata * ndata / a;
return blocks;
}
return NULL;
}
- if (re->after.data_disks == re->before.data_disks &&
- get_linux_version() < 2006032)
- return "in-place reshape is not safe before 2.6.32 - sorry.";
-
- if (re->after.data_disks < re->before.data_disks &&
- get_linux_version() < 2006030)
- return "reshape to fewer devices is not supported before 2.6.30 - sorry.";
-
re->backup_blocks = compute_backup_blocks(
info->new_chunk, info->array.chunk_size,
re->after.data_disks, re->before.data_disks);
char *backup_file, int verbose,
int forked, int restart, int freeze_reshape);
+/**
+ * prepare_external_reshape() - prepares update on external metadata if supported.
+ * @devname: Device name.
+ * @subarray: Subarray.
+ * @st: Supertype.
+ * @container: Container.
+ * @cfd: Container file descriptor.
+ *
+ * Function checks that the requested reshape is supported on external metadata,
+ * and performs an initial check that the container holds the pre-requisite
+ * spare devices (mdmon owns final validation).
+ *
+ * Return: 0 on success, else 1
+ */
+static int prepare_external_reshape(char *devname, char *subarray,
+ struct supertype *st, char *container,
+ const int cfd)
+{
+ struct mdinfo *cc = NULL;
+ struct mdinfo *content = NULL;
+
+ if (st->ss->load_container(st, cfd, NULL)) {
+ pr_err("Cannot read superblock for %s\n", devname);
+ return 1;
+ }
+
+ if (!st->ss->container_content)
+ return 1;
+
+ cc = st->ss->container_content(st, subarray);
+ for (content = cc; content ; content = content->next) {
+ /*
+ * check if reshape is allowed based on metadata
+ * indications stored in content.array.status
+ */
+ if (is_bit_set(&content->array.state, MD_SB_BLOCK_VOLUME) ||
+ is_bit_set(&content->array.state, MD_SB_BLOCK_CONTAINER_RESHAPE)) {
+ pr_err("Cannot reshape arrays in container with unsupported metadata: %s(%s)\n",
+ devname, container);
+ goto error;
+ }
+ if (content->consistency_policy == CONSISTENCY_POLICY_PPL) {
+ pr_err("Operation not supported when ppl consistency policy is enabled\n");
+ goto error;
+ }
+ if (content->consistency_policy == CONSISTENCY_POLICY_BITMAP) {
+ pr_err("Operation not supported when write-intent bitmap consistency policy is enabled\n");
+ goto error;
+ }
+ }
+ sysfs_free(cc);
+ if (mdmon_running(container))
+ st->update_tail = &st->updates;
+ return 0;
+error:
+ sysfs_free(cc);
+ return 1;
+}
+
int Grow_reshape(char *devname, int fd,
struct mddev_dev *devlist,
- unsigned long long data_offset,
struct context *c, struct shape *s)
{
/* Make some changes in the shape of an array.
struct supertype *st;
char *subarray = NULL;
- int frozen;
+ int frozen = 0;
int changed = 0;
char *container = NULL;
int cfd = -1;
int added_disks;
struct mdinfo info;
- struct mdinfo *sra;
+ struct mdinfo *sra = NULL;
if (md_get_array_info(fd, &array) < 0) {
pr_err("%s is not an active md array - aborting\n",
devname);
return 1;
}
- if (data_offset != INVALID_SECTORS && array.level != 10 &&
+ if (s->level != UnSet && s->chunk) {
+ pr_err("Cannot change array level in the same operation as changing chunk size.\n");
+ return 1;
+ }
+
+ if (s->data_offset != INVALID_SECTORS && array.level != 10 &&
(array.level < 4 || array.level > 6)) {
pr_err("--grow --data-offset not yet supported\n");
return 1;
return 1;
}
- if (s->raiddisks && s->raiddisks < array.raid_disks &&
- array.level > 1 && get_linux_version() < 2006032 &&
- !check_env("MDADM_FORCE_FEWER")) {
- pr_err("reducing the number of devices is not safe before Linux 2.6.32\n"
- " Please use a newer kernel\n");
- return 1;
- }
-
if (array.level > 1 && s->size > 1 &&
- (array.chunk_size / 1024) > (int)s->size) {
+ (unsigned long long) (array.chunk_size / 1024) > s->size) {
pr_err("component size must be larger than chunk size.\n");
return 1;
}
pr_err("Cannot increase raid-disks on this array beyond %d\n", st->max_devs);
return 1;
}
- if (s->level == 0 &&
- (array.state & (1<<MD_SB_BITMAP_PRESENT)) &&
- !(array.state & (1<<MD_SB_CLUSTERED))) {
- array.state &= ~(1<<MD_SB_BITMAP_PRESENT);
- if (md_set_array_info(fd, &array)!= 0) {
- pr_err("failed to remove internal bitmap.\n");
- return 1;
- }
- }
-
- /* in the external case we need to check that the requested reshape is
- * supported, and perform an initial check that the container holds the
- * pre-requisite spare devices (mdmon owns final validation)
- */
- if (st->ss->external) {
- int retval;
+ if (s->level == 0 && (array.state & (1 << MD_SB_BITMAP_PRESENT)) &&
+ !(array.state & (1 << MD_SB_CLUSTERED)) && !st->ss->external) {
+ array.state &= ~(1 << MD_SB_BITMAP_PRESENT);
+ if (md_set_array_info(fd, &array) != 0) {
+ pr_err("failed to remove internal bitmap.\n");
+ return 1;
+ }
+ }
+ if (st->ss->external) {
if (subarray) {
container = st->container_devnm;
cfd = open_dev_excl(st->container_devnm);
return 1;
}
- retval = st->ss->load_container(st, cfd, NULL);
-
- if (retval) {
- pr_err("Cannot read superblock for %s\n", devname);
+ rv = prepare_external_reshape(devname, subarray, st,
+ container, cfd);
+ if (rv > 0) {
free(subarray);
- return 1;
+ close(cfd);
+ goto release;
}
- /* check if operation is supported for metadata handler */
- if (st->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 = 1;
-
- /* check if reshape is allowed based on metadata
- * indications stored in content.array.status
- */
- if (content->array.state &
- (1 << MD_SB_BLOCK_VOLUME))
- allow_reshape = 0;
- if (content->array.state &
- (1 << MD_SB_BLOCK_CONTAINER_RESHAPE))
- allow_reshape = 0;
- if (!allow_reshape) {
- pr_err("cannot reshape arrays in container with unsupported metadata: %s(%s)\n",
- devname, container);
- sysfs_free(cc);
- free(subarray);
- return 1;
- }
- if (content->consistency_policy ==
- CONSISTENCY_POLICY_PPL) {
- pr_err("Operation not supported when ppl consistency policy is enabled\n");
- sysfs_free(cc);
- free(subarray);
- return 1;
- }
- }
- sysfs_free(cc);
+ if (s->raiddisks && subarray) {
+ pr_err("--raid-devices operation can be performed on a container only\n");
+ close(cfd);
+ free(subarray);
+ return 1;
}
- if (mdmon_running(container))
- st->update_tail = &st->updates;
}
added_disks = 0;
goto release;
}
+ if (array.level == 0) {
+ pr_err("Component size change is not supported for RAID0\n");
+ rv = 1;
+ goto release;
+ }
+
if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
devname, APPLY_METADATA_CHANGES,
c->verbose > 0)) {
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(container);
- if (mdmon_running(st->container_devnm) &&
- st->update_tail == NULL)
- st->update_tail = &st->updates;
+ if (mdmon_running(st->container_devnm) == false) {
+ pr_err("No mdmon found. Grow cannot continue.\n");
+ goto release;
+ }
}
if (s->size == MAX_SIZE)
/* got truncated to 32bit, write to
* component_size instead
*/
- if (sra)
- rv = sysfs_set_num(sra, NULL,
- "component_size", s->size);
- else
- rv = -1;
+ rv = sysfs_set_num(sra, NULL, "component_size", s->size);
} else {
rv = md_set_array_info(fd, &array);
* a backport has been arranged.
*/
if (sra == NULL ||
- sysfs_set_str(sra, NULL, "resync_start",
- "none") < 0)
+ sysfs_set_str(sra, NULL, "resync_start", STR_COMMON_NONE) < 0)
pr_err("--assume-clean not supported with --grow on this kernel\n");
}
md_get_array_info(fd, &array);
devname, s->size);
}
changed = 1;
- } else if (array.level != LEVEL_CONTAINER) {
+ } else if (!is_container(array.level)) {
s->size = get_component_size(fd)/2;
if (s->size == 0)
s->size = array.size;
if ((s->level == UnSet || s->level == array.level) &&
(s->layout_str == NULL) &&
(s->chunk == 0 || s->chunk == array.chunk_size) &&
- data_offset == INVALID_SECTORS &&
+ s->data_offset == INVALID_SECTORS &&
(s->raiddisks == 0 || s->raiddisks == array.raid_disks)) {
/* Nothing more to do */
if (!changed && c->verbose >= 0)
memset(&info, 0, sizeof(info));
info.array = array;
if (sysfs_init(&info, fd, NULL)) {
- pr_err("failed to intialize sysfs.\n");
+ pr_err("failed to initialize sysfs.\n");
rv = 1;
goto release;
}
info.component_size = s->size*2;
info.new_level = s->level;
info.new_chunk = s->chunk * 1024;
- if (info.array.level == LEVEL_CONTAINER) {
+ if (is_container(info.array.level)) {
info.delta_disks = UnSet;
info.array.raid_disks = s->raiddisks;
} else if (s->raiddisks)
info.new_layout = UnSet;
if (info.array.level == 6 && info.new_level == UnSet) {
char l[40], *h;
- strcpy(l, map_num(r6layout, info.array.layout));
+ strcpy(l, map_num_s(r6layout, info.array.layout));
h = strrchr(l, '-');
if (h && strcmp(h, "-6") == 0) {
*h = 0;
info.new_layout = info.array.layout;
else if (info.array.level == 5 && info.new_level == 6) {
char l[40];
- strcpy(l, map_num(r5layout, info.array.layout));
+ strcpy(l, map_num_s(r5layout, info.array.layout));
strcat(l, "-6");
info.new_layout = map_name(r6layout, l);
} else {
printf("layout for %s set to %d\n",
devname, array.layout);
}
- } else if (array.level == LEVEL_CONTAINER) {
+ } else if (is_container(array.level)) {
/* This change is to be applied to every array in the
* container. This is only needed when the metadata imposes
* restraints of the various arrays in the container.
* number of devices (On-Line Capacity Expansion) must be
* performed at the level of the container
*/
- if (fd > 0) {
- close(fd);
- fd = -1;
- }
+ close_fd(&fd);
rv = reshape_container(container, devname, -1, st, &info,
c->force, c->backup_file, c->verbose,
0, 0, 0);
}
sync_metadata(st);
rv = reshape_array(container, fd, devname, st, &info, c->force,
- devlist, data_offset, c->backup_file,
+ devlist, s->data_offset, c->backup_file,
c->verbose, 0, 0, 0);
frozen = 0;
}
static int verify_reshape_position(struct mdinfo *info, int level)
{
int ret_val = 0;
- char buf[40];
+ char buf[SYSFS_MAX_BUF_SIZE];
int rv;
/* read sync_max, failure can mean raid0 array */
- rv = sysfs_get_str(info, NULL, "sync_max", buf, 40);
+ rv = sysfs_get_str(info, NULL, "sync_max", buf, sizeof(buf));
if (rv > 0) {
char *ep;
goto release;
}
if (data_offset != INVALID_SECTORS &&
- data_offset < sd->data_offset - min) {
- pr_err("--data-offset too small on %s\n",
+ data_offset > sd->data_offset - min) {
+ pr_err("--data-offset too large on %s\n",
dn);
goto release;
}
struct mdinfo info;
if (sysfs_init(&info, fd, NULL)) {
- pr_err("failed to intialize sysfs.\n");
+ pr_err("failed to initialize sysfs.\n");
return 1;
}
md_get_array_info(fd, &array);
- if (level == 0 && (array.level >= 4 && array.level <= 6)) {
+ if (level == 0 && is_level456(array.level)) {
/* To convert to RAID0 we need to fail and
* remove any non-data devices. */
int found = 0;
sigterm = 1;
}
-static int continue_via_systemd(char *devnm)
-{
- int skipped, i, pid, status;
- char pathbuf[1024];
- /* In a systemd/udev world, it is best to get systemd to
- * run "mdadm --grow --continue" rather than running in the
- * background.
- */
- switch(fork()) {
- case 0:
- /* FIXME yuk. CLOSE_EXEC?? */
- skipped = 0;
- for (i = 3; skipped < 20; i++)
- if (close(i) < 0)
- skipped++;
- else
- skipped = 0;
-
- /* Don't want to see error messages from
- * systemctl. If the service doesn't exist,
- * we fork ourselves.
- */
- close(2);
- open("/dev/null", O_WRONLY);
- snprintf(pathbuf, sizeof(pathbuf),
- "mdadm-grow-continue@%s.service", devnm);
- status = execl("/usr/bin/systemctl", "systemctl", "restart",
- pathbuf, NULL);
- status = execl("/bin/systemctl", "systemctl", "restart",
- pathbuf, NULL);
- exit(1);
- case -1: /* Just do it ourselves. */
- break;
- default: /* parent - good */
- pid = wait(&status);
- if (pid >= 0 && status == 0)
- return 1;
- }
- return 0;
-}
-
static int reshape_array(char *container, int fd, char *devname,
struct supertype *st, struct mdinfo *info,
int force, struct mddev_dev *devlist,
unsigned long long array_size;
int done;
struct mdinfo *sra = NULL;
- char buf[20];
+ char buf[SYSFS_MAX_BUF_SIZE];
/* when reshaping a RAID0, the component_size might be zero.
* So try to fix that up.
dprintf("Cannot get array information.\n");
goto release;
}
+ if (st->update_tail == NULL)
+ st->update_tail = &st->updates;
if (array.level == 0 && info->component_size == 0) {
get_dev_size(fd, NULL, &array_size);
info->component_size = array_size / array.raid_disks;
* level and frozen, we can safely add them.
*/
if (devlist) {
- if (Manage_subdevs(devname, fd, devlist, verbose, 0, NULL, 0))
+ if (Manage_subdevs(devname, fd, devlist, verbose, 0, UOPT_UNDEFINED, 0))
goto release;
}
goto release;
} else if (verbose >= 0)
printf("chunk size for %s set to %d\n",
- devname, array.chunk_size);
+ devname, info->new_chunk);
}
unfreeze(st);
return 0;
default: /* parent */
return 0;
case 0:
+ manage_fork_fds(0);
map_fork();
break;
}
goto release;
err = start_reshape(sra, restart, reshape.before.data_disks,
- reshape.after.data_disks);
+ reshape.after.data_disks, st);
if (err) {
pr_err("Cannot %s reshape for %s\n",
restart ? "continue" : "start", devname);
return 1;
}
- if (!forked && !check_env("MDADM_NO_SYSTEMCTL"))
- if (continue_via_systemd(container ?: sra->sys_name)) {
+ if (!forked)
+ if (continue_via_systemd(container ?: sra->sys_name,
+ GROW_SERVICE, NULL)) {
free(fdlist);
free(offsets);
sysfs_free(sra);
break;
}
+ /* Close unused file descriptor in the forked process */
+ close_fd(&fd);
+
/* If another array on the same devices is busy, the
* reshape will wait for them. This would mean that
* the first section that we suspend will stay suspended
mdstat_wait(30 - (delayed-1) * 25);
} while (delayed);
mdstat_close();
- close(fd);
if (check_env("MDADM_GROW_VERIFY"))
fd = open(devname, O_RDONLY | O_DIRECT);
else
fd = -1;
mlockall(MCL_FUTURE);
- signal(SIGTERM, catch_term);
+ if (signal_s(SIGTERM, catch_term) == SIG_ERR)
+ goto release;
if (st->ss->external) {
/* metadata handler takes it from here */
*/
ping_monitor(container);
- if (!forked && !freeze_reshape && !check_env("MDADM_NO_SYSTEMCTL"))
- if (continue_via_systemd(container))
+ if (!forked && !freeze_reshape)
+ if (continue_via_systemd(container, GROW_SERVICE, NULL))
return 0;
switch (forked ? 0 : fork()) {
printf("%s: multi-array reshape continues in background\n", Name);
return 0;
case 0: /* child */
+ manage_fork_fds(0);
map_fork();
break;
}
unsigned long long array_size = (info->component_size
* reshape->before.data_disks);
int fd;
- char buf[20];
+ char buf[SYSFS_MAX_BUF_SIZE];
/* First, we unsuspend any region that is now known to be safe.
* If suspend_point is on the 'wrong' side of reshape_progress, then
/* Check that sync_action is still 'reshape' to avoid
* waiting forever on a dead array
*/
- char action[20];
- if (sysfs_get_str(info, NULL, "sync_action", action, 20) <= 0 ||
+ char action[SYSFS_MAX_BUF_SIZE];
+ if (sysfs_get_str(info, NULL, "sync_action", action, sizeof(action)) <= 0 ||
strncmp(action, "reshape", 7) != 0)
break;
/* Some kernels reset 'sync_completed' to zero
*/
if (completed == 0) {
unsigned long long reshapep;
- char action[20];
- if (sysfs_get_str(info, NULL, "sync_action", action, 20) > 0 &&
+ char action[SYSFS_MAX_BUF_SIZE];
+ if (sysfs_get_str(info, NULL, "sync_action", action, sizeof(action)) > 0 &&
strncmp(action, "idle", 4) == 0 &&
sysfs_get_ll(info, NULL,
"reshape_position", &reshapep) == 0)
* it was just a device failure that leaves us degraded but
* functioning.
*/
- if (sysfs_get_str(info, NULL, "reshape_position", buf,
- sizeof(buf)) < 0 || strncmp(buf, "none", 4) != 0) {
+ if (sysfs_get_str(info, NULL, "reshape_position", buf, sizeof(buf)) < 0 ||
+ str_is_none(buf) == false) {
/* The abort might only be temporary. Wait up to 10
* seconds for fd to contain a valid number again.
*/
if (sd->disk.state & (1<<MD_DISK_FAULTY))
continue;
if (sd->disk.state & (1<<MD_DISK_SYNC)) {
- char sbuf[100];
+ char sbuf[SYSFS_MAX_BUF_SIZE];
if (sysfs_get_str(sra, sd, "state",
sbuf, sizeof(sbuf)) < 0 ||
lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0);
if ((unsigned long long)read(afd, abuf, len) != len)
fail("read first from array failed");
- if (memcmp(bbuf, abuf, len) != 0) {
-#if 0
- int i;
- printf("offset=%llu len=%llu\n",
- (unsigned long long)__le64_to_cpu(bsb2.arraystart)*512, len);
- for (i=0; i<len; i++)
- if (bbuf[i] != abuf[i]) {
- printf("first diff byte %d\n", i);
- break;
- }
-#endif
+ if (memcmp(bbuf, abuf, len) != 0)
fail("data1 compare failed");
- }
}
if (bsb2.length2) {
unsigned long long len = __le64_to_cpu(bsb2.length2)*512;
continue;
st->ss->getinfo_super(st, &dinfo, NULL);
dinfo.reshape_progress = info->reshape_progress;
- st->ss->update_super(st, &dinfo, "_reshape_progress",
+ st->ss->update_super(st, &dinfo,
+ UOPT_SPEC__RESHAPE_PROGRESS,
NULL,0, 0, NULL);
st->ss->store_super(st, fdlist[j]);
st->ss->free_super(st);
}
st->ss->getinfo_super(st, content, NULL);
if (!content->reshape_active)
- sleep(3);
+ sleep_for(3, 0, true);
else
break;
} while (cnt-- > 0);
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container))
- st->update_tail = &st->updates;
- else {
+ if (mdmon_running(container) == false) {
pr_err("No mdmon found. Grow cannot continue.\n");
ret_val = 1;
goto Grow_continue_command_exit;