]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Check device is large enough before hot-add.
authorNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:32:49 +0000 (17:32 +1100)
committerNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:32:49 +0000 (17:32 +1100)
This improves quality of error message.

ChangeLog
Manage.c

index 45efef2ae0e84f094798d6dc3306b67ffdde678a..94a39e8b92dc63d6c130654e15c988251fd8f910 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,8 @@ Changes Prior to this release
     -   If two drives in a raid5 disappear at the same time, then "-Af"
         will add them both in rather than just one and forcing the array
        to 'clean'.  This is slightly safer in some cases.
+    -   Check device is large enough before hot-add: this improves quality
+       of error message.
 
 Changes Prior to 2.5.6 release
     -   Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled
index 0378b6ee1f68f2446214782911c1a71af0029c6b..144fb4fb88bf9683a602b6dfcfa9e30f8f836cca 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -186,6 +186,9 @@ int Manage_subdevs(char *devname, int fd,
                return 1;
        }
        for (dv = devlist ; dv; dv=dv->next) {
+               unsigned long long ldsize;
+               unsigned long dsize;
+
                if (stat(dv->devname, &stb)) {
                        fprintf(stderr, Name ": cannot find %s: %s\n",
                                dv->devname, strerror(errno));
@@ -202,7 +205,7 @@ int Manage_subdevs(char *devname, int fd,
                                dv->devname, dv->disposition);
                        return 1;
                case 'a':
-                       /* add the device - hot or cold */
+                       /* add the device */
                        st = super_by_version(array.major_version,
                                              array.minor_version);
                        if (!st) {
@@ -221,6 +224,20 @@ int Manage_subdevs(char *devname, int fd,
                        if (array.not_persistent==0)
                                st->ss->load_super(st, tfd, &osuper, NULL);
                        /* will use osuper later */
+#ifdef BLKGETSIZE64
+                       if (ioctl(tfd, BLKGETSIZE64, &ldsize)==0)
+                               ;
+                       else
+#endif
+                       if (ioctl(tfd, BLKGETSIZE, &dsize)) {
+                               fprintf(stderr, Name ": Cannot get size of %s: %s\n",
+                                       dv->devname, strerror(errno));
+                               close(tfd);
+                               return 1;
+                       } else {
+                               ldsize = dsize;
+                               ldsize <<= 9;
+                       }
                        close(tfd);
 
                        if (array.major_version == 0 &&
@@ -240,6 +257,14 @@ int Manage_subdevs(char *devname, int fd,
 
                        if (array.not_persistent == 0) {
 
+                               /* Make sure device is large enough */
+                               if (st->ss->avail_size(st, 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 
                                 */
@@ -303,6 +328,15 @@ int Manage_subdevs(char *devname, int fd,
                                                /* fall back on normal-add */
                                        }
                                }
+                       } else {
+                               /* non-persistent. Must ensure that new drive
+                                * is at least array.size big.
+                                */
+                               if (ldsize/512 < array.size) {
+                                       fprintf(stderr, Name ": %s not large enough to join array\n",
+                                               dv->devname);
+                                       return 1;
+                               }
                        }
                        /* in 2.6.17 and earlier, version-1 superblocks won't
                         * use the number we write, but will choose a free number.