summaryrefslogtreecommitdiffstats
path: root/super-intel.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-12-01 16:04:06 -0700
committerDan Williams <dan.j.williams@intel.com>2009-12-01 16:04:06 -0700
commita7dd165b4ea5c3db8dd05f4594e8dea783296ae3 (patch)
tree3ecb283a693f9c8505241664e971dfa909363fb7 /super-intel.c
parent2ed4f75388f99968be58097941a9704f6e42d701 (diff)
downloadmdadm-a7dd165b4ea5c3db8dd05f4594e8dea783296ae3.tar.gz
mdadm-a7dd165b4ea5c3db8dd05f4594e8dea783296ae3.tar.xz
mdadm-a7dd165b4ea5c3db8dd05f4594e8dea783296ae3.zip
imsm: catch attempt to auto-layout zero-length arrays
When -z is omitted reserve_space() looks to satisfy a zero length allocation which lo and behold is equal to the amount of free space on a full disk. So, catch maxsize == 0 and simplify the return value from merge_extents() to always equal amount of free space (no benefit to having a special case ~0ULL == error). Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/super-intel.c b/super-intel.c
index 2e119f8..6fe5e0d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -3333,7 +3333,7 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
unsigned long reserve;
if (!e)
- return ~0ULL; /* error */
+ return 0;
/* coalesce and sort all extents. also, check to see if we need to
* reserve space between member arrays
@@ -3376,17 +3376,23 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
} while (e[i-1].size);
free(e);
+ if (maxsize == 0)
+ return 0;
+
+ /* FIXME assumes volume at offset 0 is the first volume in a
+ * container
+ */
if (start_extent > 0)
reserve = IMSM_RESERVED_SECTORS; /* gap between raid regions */
else
reserve = 0;
if (maxsize < reserve)
- return ~0ULL;
+ return 0;
super->create_offset = ~((__u32) 0);
if (start + reserve > super->create_offset)
- return ~0ULL; /* start overflows create_offset */
+ return 0; /* start overflows create_offset */
super->create_offset = start + reserve;
return maxsize - reserve;
@@ -3569,15 +3575,11 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
i += dl->extent_cnt;
maxsize = merge_extents(super, i);
- if (maxsize < size) {
+ if (maxsize < size || maxsize == 0) {
if (verbose)
fprintf(stderr, Name ": not enough space after merge (%llu < %llu)\n",
maxsize, size);
return 0;
- } else if (maxsize == ~0ULL) {
- if (verbose)
- fprintf(stderr, Name ": failed to merge %d extents\n", i);
- return 0;
}
*freesize = maxsize;
@@ -3634,7 +3636,8 @@ static int reserve_space(struct supertype *st, int raiddisks,
if (cnt < raiddisks ||
(super->orom && used && used != raiddisks) ||
- maxsize < minsize) {
+ maxsize < minsize ||
+ maxsize == 0) {
fprintf(stderr, Name ": not enough devices with space to create array.\n");
return 0; /* No enough free spaces large enough */
}