77 lines
2.3 KiB
Diff
77 lines
2.3 KiB
Diff
Based on
|
|
commit 7a3be72fc621b4a7589e923cf0652c51493f831a
|
|
Author: Neil Brown <neilb@suse.de>
|
|
Date: Mon Apr 28 16:29:37 2008 +1000
|
|
|
|
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.
|
|
|
|
---
|
|
Detail.c | 2 +-
|
|
Manage.c | 14 ++++++++++++--
|
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
|
|
|
--- Detail.c.orig
|
|
+++ Detail.c
|
|
@@ -174,7 +174,7 @@ int Detail(char *dev, int brief, int exp
|
|
if (dsize > 0)
|
|
printf(" Used Dev Size : %llu%s\n",
|
|
dsize,
|
|
- human_size((long long)array.size<<10));
|
|
+ human_size((long long)dsize<<10));
|
|
else
|
|
printf(" Used Dev Size : unknown\n");
|
|
} else
|
|
--- Manage.c.orig
|
|
+++ Manage.c
|
|
@@ -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;
|
|
@@ -203,6 +204,15 @@ int Manage_subdevs(char *devname, int fd
|
|
devname);
|
|
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;
|
|
+
|
|
for (dv = devlist, j=0 ; dv; dv = next, j = jnext) {
|
|
unsigned long long ldsize;
|
|
char dvname[20];
|
|
@@ -335,7 +345,7 @@ int Manage_subdevs(char *devname, int fd
|
|
|
|
/* Make sure device is large enough */
|
|
if (st->ss->avail_size(st, ldsize/512) <
|
|
- array.size) {
|
|
+ array_size) {
|
|
fprintf(stderr, Name ": %s not large enough to join array\n",
|
|
dv->devname);
|
|
return 1;
|
|
@@ -409,7 +419,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;
|