From: NeilBrown Date: Thu, 8 Sep 2011 03:08:51 +0000 (+1000) Subject: Grow: refuse to grow a 0.90 array beyond 2TB X-Git-Tag: mdadm-3.2.3~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20a4675688e0384a1b4eac61b05f60fbf7747df9;p=thirdparty%2Fmdadm.git Grow: refuse to grow a 0.90 array beyond 2TB A kernel bug makes handling for arrays using more than 2TB per device incorrect, and the kernel doesn't stop an array from growing beyond any limit. This is fixed in 3.1 So prior to 3.1, make sure not to ask for an array to grow bigger than 2TB per device. Signed-off-by: NeilBrown --- diff --git a/Grow.c b/Grow.c index 048351d7..17d14b67 100644 --- a/Grow.c +++ b/Grow.c @@ -1446,6 +1446,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, /* ========= set size =============== */ if (size >= 0 && (size == 0 || size != array.size)) { long long orig_size = get_component_size(fd)/2; + long long min_csize; struct mdinfo *mdi; if (orig_size == 0) @@ -1461,10 +1462,40 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, /* Update the size of each member device in case * they have been resized. This will never reduce * below the current used-size. The "size" attribute - * understand '0' to mean 'max'. + * understands '0' to mean 'max'. */ - for (mdi = sra->devs; mdi; mdi = mdi->next) - sysfs_set_num(sra, mdi, "size", size); + min_csize = 0; + for (mdi = sra->devs; mdi; mdi = mdi->next) { + if (sysfs_set_num(sra, mdi, "size", size) < 0) + break; + if (array.not_persistent == 0 && + array.major_version == 0 && + get_linux_version() < 3001000) { + /* Dangerous to allow size to exceed 2TB */ + unsigned long long csize; + if (sysfs_get_ll(sra, mdi, "size", &csize) == 0) { + if (csize >= 2ULL*1024*1024*1024) + csize = 2ULL*1024*1024*1024; + if ((min_csize == 0 || (min_csize + > (long long)csize))) + min_csize = csize; + } + } + } + if (min_csize && size > min_csize) { + fprintf(stderr, Name ": Cannot safely make this array " + "use more than 2TB per device on this kernel.\n"); + rv = 1; + goto release; + } + if (min_csize && size == 0) { + /* Don't let the kernel choose a size - it will get + * it wrong + */ + fprintf(stderr, Name ": Limited v0.90 array to " + "2TB per device\n"); + size = min_csize; + } array.size = size; if (array.size != size) {