Check device is large enough before hot-add.

This improves quality of error message.
This commit is contained in:
Neil Brown 2006-12-14 17:32:49 +11:00
parent c5a6f9a61d
commit 4a39c6f236
2 changed files with 37 additions and 1 deletions

View File

@ -23,6 +23,8 @@ Changes Prior to this release
- If two drives in a raid5 disappear at the same time, then "-Af" - 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 will add them both in rather than just one and forcing the array
to 'clean'. This is slightly safer in some cases. 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 Changes Prior to 2.5.6 release
- Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled - Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled

View File

@ -186,6 +186,9 @@ int Manage_subdevs(char *devname, int fd,
return 1; return 1;
} }
for (dv = devlist ; dv; dv=dv->next) { for (dv = devlist ; dv; dv=dv->next) {
unsigned long long ldsize;
unsigned long dsize;
if (stat(dv->devname, &stb)) { if (stat(dv->devname, &stb)) {
fprintf(stderr, Name ": cannot find %s: %s\n", fprintf(stderr, Name ": cannot find %s: %s\n",
dv->devname, strerror(errno)); dv->devname, strerror(errno));
@ -202,7 +205,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, dv->disposition); dv->devname, dv->disposition);
return 1; return 1;
case 'a': case 'a':
/* add the device - hot or cold */ /* add the device */
st = super_by_version(array.major_version, st = super_by_version(array.major_version,
array.minor_version); array.minor_version);
if (!st) { if (!st) {
@ -221,6 +224,20 @@ int Manage_subdevs(char *devname, int fd,
if (array.not_persistent==0) if (array.not_persistent==0)
st->ss->load_super(st, tfd, &osuper, NULL); st->ss->load_super(st, tfd, &osuper, NULL);
/* will use osuper later */ /* 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); close(tfd);
if (array.major_version == 0 && if (array.major_version == 0 &&
@ -240,6 +257,14 @@ int Manage_subdevs(char *devname, int fd,
if (array.not_persistent == 0) { 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 /* need to find a sample superblock to copy, and
* a spare slot to use * a spare slot to use
*/ */
@ -303,6 +328,15 @@ int Manage_subdevs(char *devname, int fd,
/* fall back on normal-add */ /* 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 /* in 2.6.17 and earlier, version-1 superblocks won't
* use the number we write, but will choose a free number. * use the number we write, but will choose a free number.