]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
Monitor: fix inconsistencies in values for ->percent
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index 389992e24a3e84cee1997776d91f96dc6d85da6c..8e3b5c0f80bf8f5e9790ae522258950e13bd204d 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -424,8 +424,8 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
                if (offset_setable) {
                        st->ss->getinfo_super(st, mdi, NULL);
                        sysfs_init(mdi, fd, -1);
-                       rv = sysfs_set_num(mdi, NULL, "bitmap/location",
-                                          mdi->bitmap_offset);
+                       rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
+                                                 mdi->bitmap_offset);
                } else {
                        array.state |= (1<<MD_SB_BITMAP_PRESENT);
                        rv = ioctl(fd, SET_ARRAY_INFO, &array);
@@ -623,8 +623,6 @@ static void unfreeze(struct supertype *st)
 
                if (sra)
                        sysfs_set_str(sra, NULL, "sync_action", "idle");
-               else
-                       fprintf(stderr, Name ": failed to unfreeze array\n");
                sysfs_free(sra);
        }
 }
@@ -1668,7 +1666,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                rv = 0;
                for (mdi = sra->devs; mdi; mdi = mdi->next) {
                        if (sysfs_set_num(sra, mdi, "size", size) < 0) {
-                               rv = 1;
+                               /* Probably kernel refusing to let us
+                                * reduce the size - not an error.
+                                */
                                break;
                        }
                        if (array.not_persistent == 0 &&
@@ -1749,7 +1749,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        /* do not recync non-existing parity,
                         * we will drop it anyway
                         */
-                       sysfs_set_str(sra, NULL, "sync_action", "idle");
+                       sysfs_set_str(sra, NULL, "sync_action", "frozen");
                        /* go back to raid0, drop parity disk
                         */
                        sysfs_set_str(sra, NULL, "level", "raid0");
@@ -1883,9 +1883,37 @@ size_change_error:
                                *h = 0;
                                info.new_layout = map_name(r6layout, l);
                        }
+               } else {
+                       fprintf(stderr, Name
+                               ": %s is only meaningful when reshaping"
+                               " a RAID6 array.\n", layout_str);
+                       rv = 1;
+                       goto release;
                }
        } else if (strcmp(layout_str, "preserve") == 0) {
-               info.new_layout = UnSet;
+               /* This means that a non-standard RAID6 layout
+                * is OK.
+                * In particular:
+                * - When reshape a RAID6 (e.g. adding a device)
+                *   which is in a non-standard layout, it is OK
+                *   to preserve that layout.
+                * - When converting a RAID5 to RAID6, leave it in
+                *   the XXX-6 layout, don't re-layout.
+                */
+               if (info.array.level == 6 && info.new_level == UnSet)
+                       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));
+                       strcat(l, "-6");
+                       info.new_layout = map_name(r6layout, l);
+               } else {
+                       fprintf(stderr, Name
+                               ": %s in only meaningful when reshaping"
+                               " to RAID6\n", layout_str);
+                       rv = 1;
+                       goto release;
+               }
        } else {
                int l = info.new_level;
                if (l == UnSet)