diff options
author | Neil Brown <neilb@suse.de> | 2008-04-28 16:29:37 +1000 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2008-04-28 16:29:37 +1000 |
commit | 7a3be72fc621b4a7589e923cf0652c51493f831a (patch) | |
tree | c2e88676f5be4205eab54fe9b71c43ec442b0ffd /Manage.c | |
parent | 2cdb64897d4fe33a11af13c6356dcd338c561e77 (diff) | |
download | mdadm-7a3be72fc621b4a7589e923cf0652c51493f831a.tar.gz mdadm-7a3be72fc621b4a7589e923cf0652c51493f831a.tar.xz mdadm-7a3be72fc621b4a7589e923cf0652c51493f831a.zip |
Fix problems with array.size overflowing on large arrays.
array.size is 32bits and counts K. So for arrays with
more than 4Terrabytes, it can overflow.
The correct number can be read from sysfs, but there are still
a few places that use array.size and risk truncation. What is worse.
they compare a number of kilobytes with a number of sectors !!
So use get_component_size() to read the sysfs information, and be
more consistent about units.
Diffstat (limited to 'Manage.c')
-rw-r--r-- | Manage.c | 13 |
1 files changed, 11 insertions, 2 deletions
@@ -188,6 +188,7 @@ int Manage_subdevs(char *devname, int fd, */ mdu_array_info_t array; mdu_disk_info_t disc; + unsigned long long array_size; mddev_dev_t dv, next = NULL; struct stat stb; int j, jnext = 0; @@ -202,6 +203,14 @@ int Manage_subdevs(char *devname, int fd, return 1; } + /* array.size is only 32 bit and may be truncated. + * So read from sysfs if possible, and record number of sectors + */ + + array_size = get_component_size(fd); + if (array_size <= 0) + array_size = array.size * 2; + tst = super_by_fd(fd); if (!tst) { fprintf(stderr, Name ": unsupport array - version %d.%d\n", @@ -337,7 +346,7 @@ int Manage_subdevs(char *devname, int fd, /* Make sure device is large enough */ if (tst->ss->avail_size(tst, ldsize/512) < - array.size) { + array_size) { fprintf(stderr, Name ": %s not large enough to join array\n", dv->devname); return 1; @@ -412,7 +421,7 @@ int Manage_subdevs(char *devname, int fd, /* non-persistent. Must ensure that new drive * is at least array.size big. */ - if (ldsize/512 < array.size) { + if (ldsize/512 < array_size) { fprintf(stderr, Name ": %s not large enough to join array\n", dv->devname); return 1; |