]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
Increment version for clustered bitmaps
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index a8bbf2bf19a5c58610145bff0e0e5e2aafcc6fa3..80d7b223e8ac0700ce9d43c7abc070ec5d36561c 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -297,6 +297,9 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                        "  between different architectures.  Consider upgrading the Linux kernel.\n");
        }
 
+       if (s->bitmap_file && strcmp(s->bitmap_file, "clustered") == 0)
+               major = BITMAP_MAJOR_CLUSTERED;
+
        if (ioctl(fd, GET_BITMAP_FILE, &bmf) != 0) {
                if (errno == ENOMEM)
                        pr_err("Memory allocation failure.\n");
@@ -330,8 +333,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                        }
                        return 0;
                }
-               pr_err("Internal bitmap already present on %s\n",
-                       devname);
+               pr_err("%s bitmap already present on %s\n", s->bitmap_file, devname);
                return 1;
        }
 
@@ -375,7 +377,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                free(st);
                return 1;
        }
-       if (strcmp(s->bitmap_file, "internal") == 0) {
+       if (strcmp(s->bitmap_file, "internal") == 0 ||
+           strcmp(s->bitmap_file, "clustered") == 0) {
                int rv;
                int d;
                int offset_setable = 0;
@@ -384,6 +387,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                        pr_err("Internal bitmaps not supported with %s metadata\n", st->ss->name);
                        return 1;
                }
+               st->nodes = c->nodes;
+               st->cluster_name = c->homecluster;
                mdi = sysfs_read(fd, NULL, GET_BITMAP_LOCATION);
                if (mdi)
                        offset_setable = 1;
@@ -410,7 +415,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                                                    bitmapsize, offset_setable,
                                                    major)
                                                )
-                                               st->ss->write_bitmap(st, fd2);
+                                               st->ss->write_bitmap(st, fd2, NoUpdate);
                                        else {
                                                pr_err("failed to create internal bitmap - chunksize problem.\n");
                                                close(fd2);
@@ -426,6 +431,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
                        rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
                                                  mdi->bitmap_offset);
                } else {
+                       if (strcmp(s->bitmap_file, "clustered") == 0)
+                               array.state |= (1<<MD_SB_CLUSTERED);
                        array.state |= (1<<MD_SB_BITMAP_PRESENT);
                        rv = ioctl(fd, SET_ARRAY_INFO, &array);
                }
@@ -612,10 +619,8 @@ static void unfreeze(struct supertype *st)
 
                if (sra &&
                    sysfs_get_str(sra, NULL, "sync_action", buf, 20) > 0
-                   && strcmp(buf, "frozen\n") == 0) {
-                       printf("unfreeze\n");
+                   && strcmp(buf, "frozen\n") == 0)
                        sysfs_set_str(sra, NULL, "sync_action", "idle");
-               }
                sysfs_free(sra);
        }
 }
@@ -718,9 +723,14 @@ int start_reshape(struct mdinfo *sra, int already_running,
        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 (!already_running)
-               err = err ?: sysfs_set_str(sra, NULL, "sync_action", "reshape");
-
+       if (!already_running && err == 0) {
+               int cnt = 5;
+               do {
+                       err = sysfs_set_str(sra, NULL, "sync_action", "reshape");
+                       if (err)
+                               sleep(1);
+               } while (err && errno == EBUSY && cnt-- > 0);
+       }
        return err;
 }
 
@@ -845,7 +855,8 @@ int reshape_prepare_fdlist(char *devname,
        for (sd = sra->devs; sd; sd = sd->next) {
                if (sd->disk.state & (1<<MD_DISK_FAULTY))
                        continue;
-               if (sd->disk.state & (1<<MD_DISK_SYNC)) {
+               if (sd->disk.state & (1<<MD_DISK_SYNC) &&
+                   sd->disk.raid_disk < raid_disks) {
                        char *dn = map_dev(sd->disk.major,
                                           sd->disk.minor, 1);
                        fdlist[sd->disk.raid_disk]
@@ -931,7 +942,7 @@ int reshape_open_backup_file(char *backup_file,
        if (!restart && strncmp(backup_file, MAP_DIR, strlen(MAP_DIR)) != 0) {
                char *bu = make_backup(sys_name);
                if (symlink(backup_file, bu))
-                       pr_err("Recording backup file in " MAP_DIR "failed: %s\n",
+                       pr_err("Recording backup file in " MAP_DIR " failed: %s\n",
                               strerror(errno));
                free(bu);
        }
@@ -1771,8 +1782,8 @@ int Grow_reshape(char *devname, int fd,
                                                   "raid5");
                                if (!rv) {
                                        raid0_takeover = 1;
-                                       /* get array parametes after takeover
-                                        * to chane one parameter at time only
+                                       /* get array parameters after takeover
+                                        * to change one parameter at time only
                                         */
                                        rv = ioctl(fd, GET_ARRAY_INFO, &array);
                                }
@@ -2213,7 +2224,9 @@ static int set_new_data_offset(struct mdinfo *sra, struct supertype *st,
                if (info2.space_before == 0 &&
                    info2.space_after == 0) {
                        /* Metadata doesn't support data_offset changes */
-                       pr_err("%s: Metadata version doesn't support data_offset changes\n", devname);
+                       if (!can_fallback)
+                               pr_err("%s: Metadata version doesn't support data_offset changes\n",
+                                      devname);
                        goto fallback;
                }
                if (before > info2.space_before)
@@ -2532,7 +2545,7 @@ static void update_cache_size(char *container, struct mdinfo *sra,
        /* make sure there is room for 'blocks' with a bit to spare */
        if (cache < 16 + blocks / disks)
                cache = 16 + blocks / disks;
-       cache /= (4096/512); /* Covert from sectors to pages */
+       cache /= (4096/512); /* Convert from sectors to pages */
 
        if (sra->cache_size < cache)
                subarray_set_num(container, sra, "stripe_cache_size",
@@ -3102,8 +3115,19 @@ static int reshape_array(char *container, int fd, char *devname,
                                   devname, container, &reshape) < 0)
                        goto release;
                if (sysfs_set_str(sra, NULL, "sync_action", "reshape") < 0) {
-                       pr_err("Failed to initiate reshape!\n");
-                       goto release;
+                       struct mdinfo *sd;
+                       if (errno != EINVAL) {
+                               pr_err("Failed to initiate reshape!\n");
+                               goto release;
+                       }
+                       /* revert data_offset and try the old way */
+                       for (sd = sra->devs; sd; sd = sd->next) {
+                               sysfs_set_num(sra, sd, "new_offset",
+                                             sd->data_offset);
+                               sysfs_set_str(sra, NULL, "reshape_direction",
+                                             "forwards");
+                       }
+                       break;
                }
                if (info->new_level == reshape.level)
                        return 0;
@@ -3166,7 +3190,7 @@ started:
        d = reshape_prepare_fdlist(devname, sra, odisks,
                                   nrdisks, blocks, backup_file,
                                   fdlist, offsets);
-       if (d < 0) {
+       if (d < odisks) {
                goto release;
        }
        if ((st->ss->manage_reshape == NULL) ||
@@ -3178,7 +3202,7 @@ started:
                                       devname);
                                pr_err(" Please provide one with \"--backup=...\"\n");
                                goto release;
-                       } else if (sra->array.spare_disks == 0) {
+                       } else if (d == odisks) {
                                pr_err("%s: Cannot grow - need a spare or backup-file to backup critical section\n", devname);
                                goto release;
                        }
@@ -3826,9 +3850,11 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape,
                 * So we need these extra tests.
                 */
                if (completed == 0 && advancing
+                   && strncmp(action, "idle", 4) == 0
                    && info->reshape_progress > 0)
                        break;
                if (completed == 0 && !advancing
+                   && strncmp(action, "idle", 4) == 0
                    && info->reshape_progress < (info->component_size
                                                 * reshape->after.data_disks))
                        break;
@@ -3837,21 +3863,31 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape,
                        goto check_progress;
        }
        /* Some kernels reset 'sync_completed' to zero,
-        * we need to have real point we are in md
+        * we need to have real point we are in md.
+        * So in that case, read 'reshape_position' from sysfs.
         */
-       if (completed == 0)
-               completed = max_progress;
-
-       /* some kernels can give an incorrectly high 'completed' number */
-       completed /= (info->new_chunk/512);
-       completed *= (info->new_chunk/512);
-       /* Convert 'completed' back in to a 'progress' number */
-       completed *= reshape->after.data_disks;
-       if (!advancing) {
-               completed = info->component_size * reshape->after.data_disks
-                       - completed;
+       if (completed == 0) {
+               unsigned long long reshapep;
+               char action[20];
+               if (sysfs_get_str(info, NULL, "sync_action",
+                                 action, 20) > 0 &&
+                   strncmp(action, "idle", 4) == 0 &&
+                   sysfs_get_ll(info, NULL,
+                                "reshape_position", &reshapep) == 0)
+                       *reshape_completed = reshapep;
+       } else {
+               /* some kernels can give an incorrectly high
+                * 'completed' number, so round down */
+               completed /= (info->new_chunk/512);
+               completed *= (info->new_chunk/512);
+               /* Convert 'completed' back in to a 'progress' number */
+               completed *= reshape->after.data_disks;
+               if (!advancing)
+                       completed = (info->component_size
+                                    * reshape->after.data_disks
+                                    - completed);
+               *reshape_completed = completed;
        }
-       *reshape_completed = completed;
 
        close(fd);
 
@@ -3871,7 +3907,6 @@ check_progress:
         * it was just a device failure that leaves us degraded but
         * functioning.
         */
-       strcpy(buf, "hi");
        if (sysfs_get_str(info, NULL, "reshape_position", buf, sizeof(buf)) < 0
            || strncmp(buf, "none", 4) != 0) {
                /* The abort might only be temporary.  Wait up to 10