summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-12-14 17:32:49 +1100
committerNeil Brown <neilb@suse.de>2006-12-14 17:32:49 +1100
commit4a39c6f236fba4065c7b74f03791eb50759289ad (patch)
tree30448db7fa9bb6e9293c29b073c6958d4dcdb5ac
parentc5a6f9a61d166512f237fa88bd5867dfa4e81a70 (diff)
downloadmdadm-4a39c6f236fba4065c7b74f03791eb50759289ad.tar.gz
mdadm-4a39c6f236fba4065c7b74f03791eb50759289ad.tar.xz
mdadm-4a39c6f236fba4065c7b74f03791eb50759289ad.zip
Check device is large enough before hot-add.
This improves quality of error message.
-rw-r--r--ChangeLog2
-rw-r--r--Manage.c36
2 files changed, 37 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 45efef2..94a39e8 100644
--- 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
diff --git a/Manage.c b/Manage.c
index 0378b6e..144fb4f 100644
--- 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.