]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Grow: Fix linear-growth when devices are not all the same size.
[thirdparty/mdadm.git] / Manage.c
index f17105a85202ff14092494d646246c9229f2c31c..7b3fabe1d016e8f7813a9afa9a446fd2d5c01bf2 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -112,9 +112,14 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
                struct map_ent *map = NULL;
                struct stat stb;
                if (ioctl(fd, STOP_ARRAY, NULL)) {
-                       if (quiet==0)
+                       if (quiet==0) {
                                fprintf(stderr, Name ": fail to stop array %s: %s\n",
                                        devname, strerror(errno));
+                               if (errno == EBUSY)
+                                       fprintf(stderr, "Perhaps a running "
+                                               "process, mounted filesystem "
+                                               "or active volume group?\n");
+                       }
                        return 1;
                }
                if (quiet <= 0)
@@ -188,6 +193,7 @@ int Manage_subdevs(char *devname, int fd,
         */
        mdu_array_info_t array;
        mdu_disk_info_t disc;
+       unsigned long long array_size;
        mddev_dev_t dv, next = NULL;
        struct stat stb;
        int j, jnext = 0;
@@ -202,6 +208,14 @@ int Manage_subdevs(char *devname, int fd,
                return 1;
        }
 
+       /* array.size is only 32 bit and may be truncated.
+        * So read from sysfs if possible, and record number of sectors
+        */
+
+       array_size = get_component_size(fd);
+       if (array_size <= 0)
+               array_size = array.size * 2;
+
        tst = super_by_fd(fd);
        if (!tst) {
                fprintf(stderr, Name ": unsupport array - version %d.%d\n",
@@ -335,14 +349,6 @@ int Manage_subdevs(char *devname, int fd,
 
                        if (array.not_persistent == 0) {
 
-                               /* Make sure device is large enough */
-                               if (tst->ss->avail_size(tst, ldsize/512) <
-                                   array.size) {
-                                       fprintf(stderr, Name ": %s not large enough to join array\n",
-                                               dv->devname);
-                                       return 1;
-                               }
-
                                /* need to find a sample superblock to copy, and
                                 * a spare slot to use
                                 */
@@ -372,6 +378,15 @@ int Manage_subdevs(char *devname, int fd,
                                        fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
                                        return 1;
                                }
+
+                               /* Make sure device is large enough */
+                               if (tst->ss->avail_size(tst, ldsize/512) <
+                                   array_size) {
+                                       fprintf(stderr, Name ": %s not large enough to join array\n",
+                                               dv->devname);
+                                       return 1;
+                               }
+
                                /* Possibly this device was recently part of the array
                                 * and was temporarily removed, and is now being re-added.
                                 * If so, we can simply re-add it.
@@ -412,7 +427,7 @@ int Manage_subdevs(char *devname, int fd,
                                /* non-persistent. Must ensure that new drive
                                 * is at least array.size big.
                                 */
-                               if (ldsize/512 < array.size) {
+                               if (ldsize/512 < array_size) {
                                        fprintf(stderr, Name ": %s not large enough to join array\n",
                                                dv->devname);
                                        return 1;