summaryrefslogtreecommitdiffstats
path: root/super-intel.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-11-01 04:09:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-11-01 04:09:40 +0000
commit256f011d2f256c8c2c05c37a518401199fa423bf (patch)
tree8dc9f04b281a2a8d080f0f327d11f33846be8e33 /super-intel.c
parentReleasing debian version 4.2+20230508-7. (diff)
downloadmdadm-256f011d2f256c8c2c05c37a518401199fa423bf.tar.xz
mdadm-256f011d2f256c8c2c05c37a518401199fa423bf.zip
Merging upstream version 4.2+20231026.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c464
1 files changed, 242 insertions, 222 deletions
diff --git a/super-intel.c b/super-intel.c
index ae0f4a8..6bdd5c4 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -499,8 +499,15 @@ struct intel_disk {
struct intel_disk *next;
};
+/**
+ * struct extent - reserved space details.
+ * @start: start offset.
+ * @size: size of reservation, set to 0 for metadata reservation.
+ * @vol: index of the volume, meaningful if &size is set.
+ */
struct extent {
unsigned long long start, size;
+ int vol;
};
/* definitions of reshape process types */
@@ -650,6 +657,11 @@ static int check_no_platform(void)
char *l = conf_line(fp);
char *w = l;
+ if (l == NULL) {
+ fclose(fp);
+ return 0;
+ }
+
do {
if (strcmp(w, search) == 0)
no_platform = 1;
@@ -1534,9 +1546,10 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
int get_minimal_reservation)
{
/* find a list of used extents on the given physical device */
- struct extent *rv, *e;
- int i;
int memberships = count_memberships(dl, super);
+ struct extent *rv = xcalloc(memberships + 1, sizeof(struct extent));
+ struct extent *e = rv;
+ int i;
__u32 reservation;
/* trim the reserved area for spares, so they can join any array
@@ -1548,9 +1561,6 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
else
reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
- rv = xcalloc(sizeof(struct extent), (memberships + 1));
- e = rv;
-
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_map *map = get_imsm_map(dev, MAP_0);
@@ -1558,6 +1568,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
if (get_imsm_disk_slot(map, dl->index) >= 0) {
e->start = pba_of_lba0(map);
e->size = per_dev_array_size(map);
+ e->vol = i;
e++;
}
}
@@ -1639,17 +1650,29 @@ static int is_journal(struct imsm_disk *disk)
return (disk->status & JOURNAL_DISK) == JOURNAL_DISK;
}
-/* round array size down to closest MB and ensure it splits evenly
- * between members
+/**
+ * round_member_size_to_mb()- Round given size to closest MiB.
+ * @size: size to round in sectors.
*/
-static unsigned long long round_size_to_mb(unsigned long long size, unsigned int
- disk_count)
+static inline unsigned long long round_member_size_to_mb(unsigned long long size)
{
- size /= disk_count;
- size = (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
- size *= disk_count;
+ return (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
+}
- return size;
+/**
+ * round_size_to_mb()- Round given size.
+ * @array_size: size to round in sectors.
+ * @disk_count: count of data members.
+ *
+ * Get size per each data member and round it to closest MiB to ensure that data
+ * splits evenly between members.
+ *
+ * Return: Array size, rounded down.
+ */
+static inline unsigned long long round_size_to_mb(unsigned long long array_size,
+ unsigned int disk_count)
+{
+ return round_member_size_to_mb(array_size / disk_count) * disk_count;
}
static int able_to_resync(int raid_level, int missing_disks)
@@ -2649,9 +2672,14 @@ static void print_imsm_capability(const struct imsm_orom *orom)
else
printf("Rapid Storage Technology%s\n",
imsm_orom_is_enterprise(orom) ? " enterprise" : "");
- if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
- printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
- orom->minor_ver, orom->hotfix_ver, orom->build);
+ if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) {
+ if (imsm_orom_is_vmd_without_efi(orom))
+ printf(" Version : %d.%d\n", orom->major_ver,
+ orom->minor_ver);
+ else
+ printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
+ orom->minor_ver, orom->hotfix_ver, orom->build);
+ }
printf(" RAID Levels :%s%s%s%s%s\n",
imsm_orom_has_raid0(orom) ? " raid0" : "",
imsm_orom_has_raid1(orom) ? " raid1" : "",
@@ -3778,7 +3806,6 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
struct intel_super *super = st->sb;
struct imsm_disk *disk;
int map_disks = info->array.raid_disks;
- int max_enough = -1;
int i;
struct imsm_super *mpb;
@@ -3820,12 +3847,9 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
- int failed, enough, j, missing = 0;
+ int j = 0;
struct imsm_map *map;
- __u8 state;
- failed = imsm_count_failed(super, dev, MAP_0);
- state = imsm_check_degraded(super, dev, failed, MAP_0);
map = get_imsm_map(dev, MAP_0);
/* any newly missing disks?
@@ -3840,36 +3864,10 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
if (!(ord & IMSM_ORD_REBUILD) &&
get_imsm_missing(super, idx)) {
- missing = 1;
break;
}
}
-
- if (state == IMSM_T_STATE_FAILED)
- enough = -1;
- else if (state == IMSM_T_STATE_DEGRADED &&
- (state != map->map_state || missing))
- enough = 0;
- else /* we're normal, or already degraded */
- enough = 1;
- if (is_gen_migration(dev) && missing) {
- /* during general migration we need all disks
- * that process is running on.
- * No new missing disk is allowed.
- */
- max_enough = -1;
- enough = -1;
- /* no more checks necessary
- */
- break;
- }
- /* in the missing/failed disk case check to see
- * if at least one array is runnable
- */
- max_enough = max(max_enough, enough);
}
- dprintf("enough: %d\n", max_enough);
- info->container_enough = max_enough;
if (super->disks) {
__u32 reserved = imsm_reserved_sectors(super, super->disks);
@@ -5533,40 +5531,37 @@ static void imsm_update_version_info(struct intel_super *super)
}
}
-static int check_name(struct intel_super *super, char *name, int quiet)
+/**
+ * imsm_check_name() - check imsm naming criteria.
+ * @super: &intel_super pointer, not NULL.
+ * @name: name to check.
+ * @verbose: verbose level.
+ *
+ * Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes.
+ *
+ * Returns: &true if @name matches, &false otherwise.
+ */
+static bool imsm_is_name_allowed(struct intel_super *super, const char * const name,
+ const int verbose)
{
struct imsm_super *mpb = super->anchor;
- char *reason = NULL;
- char *start = name;
- size_t len = strlen(name);
int i;
- if (len > 0) {
- while (isspace(start[len - 1]))
- start[--len] = 0;
- while (*start && isspace(*start))
- ++start, --len;
- memmove(name, start, len + 1);
+ if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) {
+ pr_vrb("imsm: Name \"%s\" is too long\n", name);
+ return false;
}
- if (len > MAX_RAID_SERIAL_LEN)
- reason = "must be 16 characters or less";
- else if (len == 0)
- reason = "must be a non-empty string";
-
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) {
- reason = "already exists";
- break;
+ pr_vrb("imsm: Name \"%s\" already exists\n", name);
+ return false;
}
}
- if (reason && !quiet)
- pr_err("imsm volume name %s\n", reason);
-
- return !reason;
+ return true;
}
static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
@@ -5661,8 +5656,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
}
}
- if (!check_name(super, name, 0))
+ if (imsm_is_name_allowed(super, name, 1) == false)
return 0;
+
dv = xmalloc(sizeof(*dv));
dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
/*
@@ -6877,20 +6873,35 @@ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
return end - base_start;
}
-static unsigned long long merge_extents(struct intel_super *super, int sum_extents)
+/** merge_extents() - analyze extents and get free size.
+ * @super: Intel metadata, not NULL.
+ * @expanding: if set, we are expanding &super->current_vol.
+ *
+ * Build a composite disk with all known extents and generate a size given the
+ * "all disks in an array must share a common start offset" constraint.
+ * If a volume is expanded, then return free space after the volume.
+ *
+ * Return: Free space or 0 on failure.
+ */
+static unsigned long long merge_extents(struct intel_super *super, const bool expanding)
{
- /* build a composite disk with all known extents and generate a new
- * 'maxsize' given the "all disks in an array must share a common start
- * offset" constraint
- */
- struct extent *e = xcalloc(sum_extents, sizeof(*e));
+ struct extent *e;
struct dl *dl;
- int i, j;
- int start_extent;
- unsigned long long pos;
+ int i, j, pos_vol_idx = -1;
+ int extent_idx = 0;
+ int sum_extents = 0;
+ unsigned long long pos = 0;
unsigned long long start = 0;
- unsigned long long maxsize;
- unsigned long reserve;
+ unsigned long long free_size = 0;
+
+ unsigned long pre_reservation = 0;
+ unsigned long post_reservation = IMSM_RESERVED_SECTORS;
+ unsigned long reservation_size;
+
+ for (dl = super->disks; dl; dl = dl->next)
+ if (dl->e)
+ sum_extents += dl->extent_cnt;
+ e = xcalloc(sum_extents, sizeof(struct extent));
/* coalesce and sort all extents. also, check to see if we need to
* reserve space between member arrays
@@ -6909,50 +6920,57 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
j = 0;
while (i < sum_extents) {
e[j].start = e[i].start;
+ e[j].vol = e[i].vol;
e[j].size = find_size(e, &i, sum_extents);
j++;
if (e[j-1].size == 0)
break;
}
- pos = 0;
- maxsize = 0;
- start_extent = 0;
i = 0;
do {
- unsigned long long esize;
+ unsigned long long esize = e[i].start - pos;
- esize = e[i].start - pos;
- if (esize >= maxsize) {
- maxsize = esize;
+ if (expanding ? pos_vol_idx == super->current_vol : esize >= free_size) {
+ free_size = esize;
start = pos;
- start_extent = i;
+ extent_idx = i;
}
+
pos = e[i].start + e[i].size;
+ pos_vol_idx = e[i].vol;
+
i++;
} while (e[i-1].size);
- free(e);
- if (maxsize == 0)
+ if (free_size == 0) {
+ dprintf("imsm: Cannot find free size.\n");
+ free(e);
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 (!expanding && extent_idx != 0)
+ /*
+ * Not a real first volume in a container is created, pre_reservation is needed.
+ */
+ pre_reservation = IMSM_RESERVED_SECTORS;
- if (maxsize < reserve)
- return 0;
+ if (e[extent_idx].size == 0)
+ /*
+ * extent_idx points to the metadata, post_reservation is allready done.
+ */
+ post_reservation = 0;
+ free(e);
- super->create_offset = ~((unsigned long long) 0);
- if (start + reserve > super->create_offset)
- return 0; /* start overflows create_offset */
- super->create_offset = start + reserve;
+ reservation_size = pre_reservation + post_reservation;
+
+ if (free_size < reservation_size) {
+ dprintf("imsm: Reservation size is greater than free space.\n");
+ return 0;
+ }
- return maxsize - reserve;
+ super->create_offset = start + pre_reservation;
+ return free_size - reservation_size;
}
static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
@@ -6998,7 +7016,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
int fd = -1;
while (dev && !is_fd_valid(fd)) {
char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1);
- num = sprintf(path, "%s%s", "/dev/", dev->name);
+ num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name);
if (num > 0)
fd = open(path, O_RDONLY, 0);
if (num <= 0 || !is_fd_valid(fd)) {
@@ -7550,13 +7568,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
return 0;
}
- /* count total number of extents for merge */
- i = 0;
- for (dl = super->disks; dl; dl = dl->next)
- if (dl->e)
- i += dl->extent_cnt;
-
- maxsize = merge_extents(super, i);
+ maxsize = merge_extents(super, false);
if (mpb->num_raid_devs > 0 && size && size != maxsize)
pr_err("attempting to create a second volume with size less then remaining space.\n");
@@ -7591,7 +7603,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
* @super: &intel_super pointer, not NULL.
* @raiddisks: number of raid disks.
* @size: requested size, could be 0 (means max size).
- * @chunk: requested chunk.
+ * @chunk: requested chunk size in KiB.
* @freesize: pointer for returned size value.
*
* Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR.
@@ -7605,22 +7617,22 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
const int raiddisks,
unsigned long long size,
const int chunk,
- unsigned long long *freesize)
+ unsigned long long *freesize,
+ bool expanding)
{
struct imsm_super *mpb = super->anchor;
struct dl *dl;
int i;
- int extent_cnt;
struct extent *e;
+ int cnt = 0;
+ int used = 0;
unsigned long long maxsize;
- unsigned long long minsize;
- int cnt;
- int used;
+ unsigned long long minsize = size;
+
+ if (minsize == 0)
+ minsize = chunk * 2;
/* find the largest common start free region of the possible disks */
- used = 0;
- extent_cnt = 0;
- cnt = 0;
for (dl = super->disks; dl; dl = dl->next) {
dl->raiddisk = -1;
@@ -7640,19 +7652,18 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
;
dl->e = e;
dl->extent_cnt = i;
- extent_cnt += i;
cnt++;
}
- maxsize = merge_extents(super, extent_cnt);
- minsize = size;
- if (size == 0)
- /* chunk is in K */
- minsize = chunk * 2;
+ maxsize = merge_extents(super, expanding);
+ if (maxsize < minsize) {
+ pr_err("imsm: Free space is %llu but must be equal or larger than %llu.\n",
+ maxsize, minsize);
+ return IMSM_STATUS_ERROR;
+ }
- if (cnt < raiddisks || (super->orom && used && used != raiddisks) ||
- maxsize < minsize || maxsize == 0) {
- pr_err("not enough devices with space to create array.\n");
+ if (cnt < raiddisks || (super->orom && used && used != raiddisks)) {
+ pr_err("imsm: Not enough devices with space to create array.\n");
return IMSM_STATUS_ERROR;
}
@@ -7702,7 +7713,7 @@ static imsm_status_t autolayout_imsm(struct intel_super *super,
int vol_cnt = super->anchor->num_raid_devs;
imsm_status_t rv;
- rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize);
+ rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize, false);
if (rv != IMSM_STATUS_OK)
return IMSM_STATUS_ERROR;
@@ -7897,7 +7908,7 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
if (i < current_vol)
continue;
- sprintf(subarray, "%u", i);
+ snprintf(subarray, sizeof(subarray), "%u", i);
if (is_subarray_active(subarray, st->devnm)) {
pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
current_vol, i);
@@ -7975,7 +7986,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
char *ep;
int vol;
- if (!check_name(super, name, 0))
+ if (imsm_is_name_allowed(super, name, 1) == false)
return 2;
vol = strtoul(subarray, &ep, 10);
@@ -10302,7 +10313,8 @@ static void imsm_process_update(struct supertype *st,
if (a->info.container_member == target)
break;
dev = get_imsm_dev(super, u->dev_idx);
- if (a || !check_name(super, name, 1)) {
+
+ if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) {
dprintf("failed to rename subarray-%d\n", target);
break;
}
@@ -11270,7 +11282,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
char *drv=NULL;
struct stat st;
- strcpy(disk_path, disk_by_path);
+ strncpy(disk_path, disk_by_path, PATH_MAX);
strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
if (stat(disk_path, &st) == 0) {
struct sys_dev* hba;
@@ -11624,6 +11636,96 @@ static void imsm_update_metadata_locally(struct supertype *st,
}
}
+/**
+ * imsm_analyze_expand() - check expand properties and calculate new size.
+ * @st: imsm supertype.
+ * @geo: new geometry params.
+ * @array: array info.
+ * @direction: reshape direction.
+ *
+ * Obtain free space after the &array and verify if expand to requested size is
+ * possible. If geo->size is set to %MAX_SIZE, assume that max free size is
+ * requested.
+ *
+ * Return:
+ * On success %IMSM_STATUS_OK is returned, geo->size and geo->raid_disks are
+ * updated.
+ * On error, %IMSM_STATUS_ERROR is returned.
+ */
+static imsm_status_t imsm_analyze_expand(struct supertype *st,
+ struct geo_params *geo,
+ struct mdinfo *array,
+ int direction)
+{
+ struct intel_super *super = st->sb;
+ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
+ int data_disks = imsm_num_data_members(map);
+
+ unsigned long long current_size;
+ unsigned long long free_size;
+ unsigned long long new_size;
+ unsigned long long max_size;
+
+ const int chunk_kib = geo->chunksize / 1024;
+ imsm_status_t rv;
+
+ if (direction == ROLLBACK_METADATA_CHANGES) {
+ /**
+ * Accept size for rollback only.
+ */
+ new_size = geo->size * 2;
+ goto success;
+ }
+
+ if (data_disks == 0) {
+ pr_err("imsm: Cannot retrieve data disks.\n");
+ return IMSM_STATUS_ERROR;
+ }
+ current_size = array->custom_array_size / data_disks;
+
+ rv = imsm_get_free_size(super, dev->vol.map->num_members, 0, chunk_kib, &free_size, true);
+ if (rv != IMSM_STATUS_OK) {
+ pr_err("imsm: Cannot find free space for expand.\n");
+ return IMSM_STATUS_ERROR;
+ }
+ max_size = round_member_size_to_mb(free_size + current_size);
+
+ if (geo->size == MAX_SIZE)
+ new_size = max_size;
+ else
+ new_size = round_member_size_to_mb(geo->size * 2);
+
+ if (new_size == 0) {
+ pr_err("imsm: Rounded requested size is 0.\n");
+ return IMSM_STATUS_ERROR;
+ }
+
+ if (new_size > max_size) {
+ pr_err("imsm: Rounded requested size (%llu) is larger than free space available (%llu).\n",
+ new_size, max_size);
+ return IMSM_STATUS_ERROR;
+ }
+
+ if (new_size == current_size) {
+ pr_err("imsm: Rounded requested size (%llu) is same as current size (%llu).\n",
+ new_size, current_size);
+ return IMSM_STATUS_ERROR;
+ }
+
+ if (new_size < current_size) {
+ pr_err("imsm: Size reduction is not supported, rounded requested size (%llu) is smaller than current (%llu).\n",
+ new_size, current_size);
+ return IMSM_STATUS_ERROR;
+ }
+
+success:
+ dprintf("imsm: New size per member is %llu.\n", new_size);
+ geo->size = data_disks * new_size;
+ geo->raid_disks = dev->vol.map->num_members;
+ return IMSM_STATUS_OK;
+}
+
/***************************************************************************
* Function: imsm_analyze_change
* Description: Function analyze change for single volume
@@ -11644,13 +11746,6 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
int devNumChange = 0;
/* imsm compatible layout value for array geometry verification */
int imsm_layout = -1;
- int data_disks;
- struct imsm_dev *dev;
- struct imsm_map *map;
- struct intel_super *super;
- unsigned long long current_size;
- unsigned long long free_size;
- unsigned long long max_size;
imsm_status_t rv;
getinfo_super_imsm_volume(st, &info, NULL);
@@ -11733,95 +11828,20 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
geo->chunksize = info.array.chunk_size;
}
- chunk = geo->chunksize / 1024;
-
- super = st->sb;
- dev = get_imsm_dev(super, super->current_vol);
- map = get_imsm_map(dev, MAP_0);
- data_disks = imsm_num_data_members(map);
- /* compute current size per disk member
- */
- current_size = info.custom_array_size / data_disks;
-
- if (geo->size > 0 && geo->size != MAX_SIZE) {
- /* align component size
- */
- geo->size = imsm_component_size_alignment_check(
- get_imsm_raid_level(dev->vol.map),
- chunk * 1024, super->sector_size,
- geo->size * 2);
- if (geo->size == 0) {
- pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is 0).\n",
- current_size);
- goto analyse_change_exit;
- }
- }
-
- if (current_size != geo->size && geo->size > 0) {
+ if (geo->size > 0) {
if (change != -1) {
pr_err("Error. Size change should be the only one at a time.\n");
change = -1;
goto analyse_change_exit;
}
- if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
- pr_err("Error. The last volume in container can be expanded only (%i/%s).\n",
- super->current_vol, st->devnm);
- goto analyse_change_exit;
- }
- /* check the maximum available size
- */
- rv = imsm_get_free_size(super, dev->vol.map->num_members,
- 0, chunk, &free_size);
+ rv = imsm_analyze_expand(st, geo, &info, direction);
if (rv != IMSM_STATUS_OK)
- /* Cannot find maximum available space
- */
- max_size = 0;
- else {
- max_size = free_size + current_size;
- /* align component size
- */
- max_size = imsm_component_size_alignment_check(
- get_imsm_raid_level(dev->vol.map),
- chunk * 1024, super->sector_size,
- max_size);
- }
- if (geo->size == MAX_SIZE) {
- /* requested size change to the maximum available size
- */
- if (max_size == 0) {
- pr_err("Error. Cannot find maximum available space.\n");
- change = -1;
- goto analyse_change_exit;
- } else
- geo->size = max_size;
- }
-
- if (direction == ROLLBACK_METADATA_CHANGES) {
- /* accept size for rollback only
- */
- } else {
- /* round size due to metadata compatibility
- */
- geo->size = (geo->size >> SECT_PER_MB_SHIFT)
- << SECT_PER_MB_SHIFT;
- dprintf("Prepare update for size change to %llu\n",
- geo->size );
- if (current_size >= geo->size) {
- pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is %llu).\n",
- current_size, geo->size);
- goto analyse_change_exit;
- }
- if (max_size && geo->size > max_size) {
- pr_err("Error. Requested size is larger than maximum available size (maximum available size is %llu, requested size /rounded/ is %llu).\n",
- max_size, geo->size);
- goto analyse_change_exit;
- }
- }
- geo->size *= data_disks;
- geo->raid_disks = dev->vol.map->num_members;
+ goto analyse_change_exit;
change = CH_ARRAY_SIZE;
}
+
+ chunk = geo->chunksize / 1024;
if (!validate_geometry_imsm(st,
geo->level,
imsm_layout,