]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
mdadm: fix reshape from RAID5 to RAID6 with backup file
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index 4436a4d6bd4cdff4fe3ebe03c2a1f3eebdf33196..5c2512f6318026bcfae2975fd07758f889172f29 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -446,7 +446,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                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",
@@ -931,12 +931,15 @@ int start_reshape(struct mdinfo *sra, int already_running,
        err = err ?: sysfs_set_num(sra, NULL, "sync_max", sync_max_to_set);
        if (!already_running && err == 0) {
                int cnt = 5;
+               int err2;
                do {
                        err = sysfs_set_str(sra, NULL, "sync_action",
                                            "reshape");
-                       if (err)
+                       err2 = sysfs_set_str(sra, NULL, "sync_max",
+                                           "max");
+                       if (err || err2)
                                sleep(1);
-               } while (err && errno == EBUSY && cnt-- > 0);
+               } while (err && err2 && errno == EBUSY && cnt-- > 0);
        }
        return err;
 }
@@ -1196,7 +1199,8 @@ unsigned long compute_backup_blocks(int nchunk, int ochunk,
        /* 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;
 }
@@ -2177,7 +2181,7 @@ size_change_error:
        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;
        }
@@ -2612,8 +2616,8 @@ static int set_new_data_offset(struct mdinfo *sra, struct supertype *st,
                                        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;
                                }
@@ -2902,7 +2906,7 @@ static int impose_level(int fd, int level, char *devname, int verbose)
        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;
        }
 
@@ -2981,47 +2985,6 @@ static void catch_term(int sig)
        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,
@@ -3285,7 +3248,7 @@ static int reshape_array(char *container, int fd, char *devname,
                                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;
@@ -3400,6 +3363,7 @@ static int reshape_array(char *container, int fd, char *devname,
                default: /* parent */
                        return 0;
                case 0:
+                       manage_fork_fds(0);
                        map_fork();
                        break;
                }
@@ -3508,14 +3472,16 @@ started:
                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)) {
                        free(fdlist);
                        free(offsets);
                        sysfs_free(sra);
                        return 0;
                }
 
+       close(fd);
        /* 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.
@@ -3568,7 +3534,6 @@ started:
                        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
@@ -3703,8 +3668,8 @@ int reshape_container(char *container, char *devname,
         */
        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))
                        return 0;
 
        switch (forked ? 0 : fork()) {
@@ -3717,6 +3682,7 @@ int reshape_container(char *container, char *devname,
                        printf("%s: multi-array reshape continues in background\n", Name);
                return 0;
        case 0: /* child */
+               manage_fork_fds(0);
                map_fork();
                break;
        }