From 4a39c6f236fba4065c7b74f03791eb50759289ad Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 14 Dec 2006 17:32:49 +1100 Subject: [PATCH] Check device is large enough before hot-add. This improves quality of error message. --- ChangeLog | 2 ++ Manage.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 45efef2a..94a39e8b 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 0378b6ee..144fb4fb 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. -- 2.39.2