]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
mdmon: remove switch-root functionality.
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index 7764bdb6275d728ea5826593b3f8158aabb74f19..efa8c47271439743ab53521ec1bb1994f78bb990 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -563,16 +563,27 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                } else
                        rv = ioctl(fd, SET_ARRAY_INFO, &array);
                if (rv != 0) {
+                       int err = errno;
                        fprintf(stderr, Name ": Cannot set device size for %s: %s\n",
-                               devname, strerror(errno));
+                               devname, strerror(err));
+                       if (err == EBUSY && 
+                           (array.state & (1<<MD_SB_BITMAP_PRESENT)))
+                               fprintf(stderr, "       Bitmap must be removed before size can be changed\n");
                        rv = 1;
                        goto release;
                }
                ioctl(fd, GET_ARRAY_INFO, &array);
+               size = get_component_size(fd);
+               if (size == 0)
+                       size = array.size;
                if (!quiet)
-                       fprintf(stderr, Name ": component size of %s has been set to %dK\n",
-                               devname, array.size);
+                       fprintf(stderr, Name ": component size of %s has been set to %lluK\n",
+                               devname, size);
                changed = 1;
+       } else {
+               size = get_component_size(fd);
+               if (size == 0)
+                       size = array.size;
        }
 
        /* ======= set level =========== */
@@ -659,8 +670,12 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        }
                        err = sysfs_set_str(sra, NULL, "level", c);
                        if (err) {
+                               err = errno;
                                fprintf(stderr, Name ": %s: could not set level to %s\n",
                                        devname, c);
+                               if (err == EBUSY && 
+                                   (array.state & (1<<MD_SB_BITMAP_PRESENT)))
+                                       fprintf(stderr, "       Bitmap must be removed before level can be changed\n");
                                rv = 1;
                                goto release;
                        }
@@ -726,9 +741,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        c = map_num(pers, level);
                        if (c) {
                                rv = sysfs_set_str(sra, NULL, "level", c);
-                               if (rv)
+                               if (rv) {
+                                       int err = errno;
                                        fprintf(stderr, Name ": %s: could not set level to %s\n",
                                                devname, c);
+                                       if (err == EBUSY && 
+                                           (array.state & (1<<MD_SB_BITMAP_PRESENT)))
+                                               fprintf(stderr, "       Bitmap must be removed before level can be changed\n");
+                               }
                        }
                } else if (!changed && !quiet)
                        fprintf(stderr, Name ": %s: no change requested\n",
@@ -844,10 +864,10 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 
                if (chunksize) {
                        nchunk = chunksize * 1024;
-                       if (array.size % chunksize) {
-                               fprintf(stderr, Name ": component size %dK is not"
+                       if (size % chunksize) {
+                               fprintf(stderr, Name ": component size %lluK is not"
                                        " a multiple of chunksize %dK\n",
-                                       array.size, chunksize);
+                                       size, chunksize);
                                break;
                        }
                }
@@ -891,13 +911,12 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                }
 
                /* Check that we can hold all the data */
-               size = ndata * array.size;
                get_dev_size(fd, NULL, &array_size);
-               if (size < (array_size/1024)) {
+               if (ndata * size < (array_size/1024)) {
                        fprintf(stderr, Name ": this change will reduce the size of the array.\n"
                                "       use --grow --array-size first to truncate array.\n"
                                "       e.g. mdadm --grow %s --array-size %llu\n",
-                               devname, size);
+                               devname, ndata * size);
                        rv = 1;
                        break;
                }
@@ -1060,12 +1079,16 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                if (ochunk == nchunk && olayout == nlayout) {
                        array.raid_disks = ndisks;
                        if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
+                               int err = errno;
                                rv = 1;
                                fprintf(stderr, Name ": Cannot set device shape for %s: %s\n",
                                        devname, strerror(errno));
                                if (ndisks < odisks &&
                                    get_linux_version() < 2006030)
                                        fprintf(stderr, Name ": linux 2.6.30 or later required\n");
+                               if (err == EBUSY && 
+                                   (array.state & (1<<MD_SB_BITMAP_PRESENT)))
+                                       fprintf(stderr, "       Bitmap must be removed before shape can be changed\n");
 
                                break;
                        }
@@ -1073,17 +1096,21 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        /* set them all just in case some old 'new_*' value
                         * persists from some earlier problem
                         */
+                       int err;
                        if (sysfs_set_num(sra, NULL, "chunk_size", nchunk) < 0)
-                               rv = 1;
-                       if (sysfs_set_num(sra, NULL, "layout", nlayout) < 0)
-                               rv = 1;
-                       if (sysfs_set_num(sra, NULL, "raid_disks", ndisks) < 0)
-                               rv = 1;
+                               rv = 1, err = errno;
+                       if (!rv && sysfs_set_num(sra, NULL, "layout", nlayout) < 0)
+                               rv = 1, err = errno;
+                       if (!rv && sysfs_set_num(sra, NULL, "raid_disks", ndisks) < 0)
+                               rv = 1, err = errno;
                        if (rv) {
                                fprintf(stderr, Name ": Cannot set device shape for %s\n",
                                        devname);
                                if (get_linux_version() < 2006030)
                                        fprintf(stderr, Name ": linux 2.6.30 or later required\n");
+                               if (err == EBUSY && 
+                                   (array.state & (1<<MD_SB_BITMAP_PRESENT)))
+                                       fprintf(stderr, "       Bitmap must be removed before shape can be changed\n");
                                break;
                        }
                }
@@ -1431,21 +1458,23 @@ static void validate(int afd, int bfd, unsigned long long offset)
 
                lseek64(bfd, offset, 0);
                if (read(bfd, bbuf, len) != len) {
-                       printf("len %llu\n", len);
+                       //printf("len %llu\n", len);
                        fail("read first backup failed");
                }
                lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0);
                if (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",
-                              __le64_to_cpu(bsb2.arraystart)*512, len);
+                              (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
                        fail("data1 compare failed");
                }
        }