summaryrefslogtreecommitdiff
path: root/Grow.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-05-14 16:34:06 +1000
committerNeilBrown <neilb@suse.de>2014-05-15 14:23:21 +1000
commit5e76dce1acd906e8fc8af04973c3a129cdc77fd6 (patch)
tree44074f57538de42d0e81fa2c63b99e0d044195cb /Grow.c
parent54ded86fbd7a6a14896cd4a26b909759a1153366 (diff)
Grow: try to let "--grow --continue" from systemd complete a reshape.
If "--assemble" or "--incremental" is started by udev, then monitoring the reshape in the background won't work. So try asking systemd to start a grow-continue. If that fails, just do it the old way. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Grow.c')
-rw-r--r--Grow.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/Grow.c b/Grow.c
index 710c4c11..f6a989da 100644
--- a/Grow.c
+++ b/Grow.c
@@ -26,6 +26,7 @@
#include <sys/mman.h>
#include <stdint.h>
#include <signal.h>
+#include <sys/wait.h>
#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
#error no endian defined
@@ -3231,6 +3232,55 @@ started:
return 1;
}
+ if (!forked && !check_env("MDADM_NO_SYSTEMCTL")) {
+ int skipped, i, pid, status;
+ char pathbuf[1024];
+ char *devnm;
+ /* In a systemd/udev world, it is best to get systemd to
+ * run "mdadm --grow --continue" rather than running in the
+ * background.
+ */
+ if (container)
+ devnm = container;
+ else
+ devnm = sra->sys_name;
+ 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",
+ "start",
+ pathbuf, NULL);
+ status = execl("/bin/systemctl", "systemctl", "start",
+ pathbuf, NULL);
+ exit(1);
+ case -1: /* Just do it ourselves. */
+ break;
+ default: /* parent - good */
+ pid = wait(&status);
+ if (pid >= 0 && status == 0) {
+ free(fdlist);
+ free(offsets);
+ sysfs_free(sra);
+ return 0;
+ }
+ }
+ }
+
/* Now we just need to kick off the reshape and watch, while
* handling backups of the data...
* This is all done by a forked background process.
@@ -3312,12 +3362,18 @@ started:
if (backup_file && done) {
char *bul;
- unlink(backup_file);
bul = make_backup(sra->sys_name);
if (bul) {
+ char buf[1024];
+ int l = readlink(bul, buf, sizeof(buf));
+ if (l > 0) {
+ buf[l]=0;
+ unlink(buf);
+ }
unlink(bul);
free(bul);
}
+ unlink(backup_file);
}
if (!done) {
abort_reshape(sra);
@@ -4898,7 +4954,7 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
} else
ret_val = reshape_array(NULL, mdfd, "array", st, info, 1,
NULL, INVALID_SECTORS,
- backup_file, 0, 0,
+ backup_file, 0, 1,
1 | info->reshape_active,
freeze_reshape);