Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15:Update
mdadm
0215-imsm-do-not-use-blocks_per_member-in-array...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0215-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch of Package mdadm
From 444909385fdaccf961308c4319d7029b82bf8bb1 Mon Sep 17 00:00:00 2001 From: Mariusz Dabrowski <mariusz.dabrowski@intel.com> Date: Thu, 5 Apr 2018 13:38:38 +0200 Subject: [PATCH] imsm: do not use blocks_per_member in array size calculations Git-commit: 444909385fdaccf961308c4319d7029b82bf8bb1 Patch-mainline: mdadm-4.0+ References: bsc#1101110 mdadm assumes that blocks_per_member value is equal to num_data_stripes * blocks_per_stripe but it is not true. For IMSM arrays created in OROM NUM_BLOCKS_DIRTY_STRIPE_REGION sectors are added up to this value. Because of this mdadm shows invalid size of arrays created in OROM and to fix this we need to use array size calculation based on num data stripes and blocks per stripe. Signed-off-by: Mariusz Dabrowski <mariusz.dabrowski@intel.com> Signed-off-by: Jes Sorensen <jsorensen@fb.com> Signed-off-by: Coly Li <colyli@suse.de> --- super-intel.c | 105 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/super-intel.c b/super-intel.c index 3fc3cf4..c55c85f 100644 --- a/super-intel.c +++ b/super-intel.c @@ -1233,6 +1233,20 @@ static void set_imsm_dev_size(struct imsm_dev *dev, unsigned long long n) split_ull(n, &dev->size_low, &dev->size_high); } +static unsigned long long per_dev_array_size(struct imsm_map *map) +{ + unsigned long long array_size = 0; + + if (map == NULL) + return array_size; + + array_size = num_data_stripes(map) * map->blocks_per_strip; + if (get_imsm_raid_level(map) == 1 || get_imsm_raid_level(map) == 10) + array_size *= 2; + + return array_size; +} + static struct extent *get_extents(struct intel_super *super, struct dl *dl) { /* find a list of used extents on the given physical device */ @@ -1259,7 +1273,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 = blocks_per_member(map); + e->size = per_dev_array_size(map); e++; } } @@ -2787,6 +2801,36 @@ static __u8 imsm_num_data_members(struct imsm_map *map) } } +static unsigned long long calc_component_size(struct imsm_map *map, + struct imsm_dev *dev) +{ + unsigned long long component_size; + unsigned long long dev_size = imsm_dev_size(dev); + unsigned long long calc_dev_size = 0; + unsigned int member_disks = imsm_num_data_members(map); + + if (member_disks == 0) + return 0; + + component_size = per_dev_array_size(map); + calc_dev_size = component_size * member_disks; + + /* Component size is rounded to 1MB so difference between size from + * metadata and size calculated from num_data_stripes equals up to + * 2048 blocks per each device. If the difference is higher it means + * that array size was expanded and num_data_stripes was not updated. + */ + if ((unsigned int)abs(calc_dev_size - dev_size) > + (1 << SECT_PER_MB_SHIFT) * member_disks) { + component_size = dev_size / member_disks; + dprintf("Invalid num_data_stripes in metadata; expected=%llu, found=%llu\n", + component_size / map->blocks_per_strip, + num_data_stripes(map)); + } + + return component_size; +} + static __u32 parity_segment_depth(struct imsm_dev *dev) { struct imsm_map *map = get_imsm_map(dev, MAP_0); @@ -3306,14 +3350,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, } info->data_offset = pba_of_lba0(map_to_analyse); - - if (info->array.level == 5) { - info->component_size = num_data_stripes(map_to_analyse) * - map_to_analyse->blocks_per_strip; - } else { - info->component_size = blocks_per_member(map_to_analyse); - } - + info->component_size = calc_component_size(map, dev); info->component_size = imsm_component_size_aligment_check( info->array.level, info->array.chunk_size, @@ -3381,7 +3418,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, used_disks = imsm_num_data_members(prev_map); if (used_disks > 0) { - array_blocks = blocks_per_member(map) * + array_blocks = per_dev_array_size(map) * used_disks; info->custom_array_size = round_size_to_mb(array_blocks, @@ -5383,9 +5420,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, vol->curr_migr_unit = 0; map = get_imsm_map(dev, MAP_0); set_pba_of_lba0(map, super->create_offset); - set_blocks_per_member(map, info_to_blocks_per_member(info, - size_per_member / - BLOCKS_PER_KB)); map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); map->failed_disk_num = ~0; if (info->level > 0) @@ -5417,6 +5451,11 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, num_data_stripes /= map->num_domains; set_num_data_stripes(map, num_data_stripes); + size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION; + set_blocks_per_member(map, info_to_blocks_per_member(info, + size_per_member / + BLOCKS_PER_KB)); + map->num_members = info->raid_disks; for (i = 0; i < map->num_members; i++) { /* initialized in add_to_super */ @@ -7821,18 +7860,14 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra info_d->events = __le32_to_cpu(mpb->generation_num); info_d->data_offset = pba_of_lba0(map); + info_d->component_size = calc_component_size(map, dev); if (map->raid_level == 5) { - info_d->component_size = - num_data_stripes(map) * - map->blocks_per_strip; info_d->ppl_sector = this->ppl_sector; info_d->ppl_size = this->ppl_size; if (this->consistency_policy == CONSISTENCY_POLICY_PPL && recovery_start == 0) this->resync_start = 0; - } else { - info_d->component_size = blocks_per_member(map); } info_d->bb.supported = 1; @@ -8156,7 +8191,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev, if (new_size <= 0) /* OLCE size change is caused by added disks */ - array_blocks = blocks_per_member(map) * used_disks; + array_blocks = per_dev_array_size(map) * used_disks; else /* Online Volume Size Change * Using available free space @@ -8273,7 +8308,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent) used_disks = imsm_num_data_members(map); if (used_disks > 0) { array_blocks = - blocks_per_member(map) * + per_dev_array_size(map) * used_disks; array_blocks = round_size_to_mb(array_blocks, @@ -8715,11 +8750,11 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot, pos = 0; array_start = pba_of_lba0(map); array_end = array_start + - blocks_per_member(map) - 1; + per_dev_array_size(map) - 1; do { /* check that we can start at pba_of_lba0 with - * blocks_per_member of space + * num_data_stripes*blocks_per_stripe of space */ if (array_start >= pos && array_end < ex[j].start) { found = 1; @@ -9145,6 +9180,12 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * set_num_data_stripes(map, num_data_stripes); } + /* ensure blocks_per_member has valid value + */ + set_blocks_per_member(map, + per_dev_array_size(map) + + NUM_BLOCKS_DIRTY_STRIPE_REGION); + /* add disk */ if (u->new_level != 5 || migr_map->raid_level != 0 || @@ -9211,15 +9252,21 @@ static int apply_size_change_update(struct imsm_update_size_change *u, int used_disks = imsm_num_data_members(map); unsigned long long blocks_per_member; unsigned long long num_data_stripes; + unsigned long long new_size_per_disk; + + if (used_disks == 0) + return 0; /* calculate new size */ - blocks_per_member = u->new_size / used_disks; - num_data_stripes = blocks_per_member / + new_size_per_disk = u->new_size / used_disks; + blocks_per_member = new_size_per_disk + + NUM_BLOCKS_DIRTY_STRIPE_REGION; + num_data_stripes = new_size_per_disk / map->blocks_per_strip; num_data_stripes /= map->num_domains; dprintf("(size: %llu, blocks per member: %llu, num_data_stipes: %llu)\n", - u->new_size, blocks_per_member, + u->new_size, new_size_per_disk, num_data_stripes); set_blocks_per_member(map, blocks_per_member); set_num_data_stripes(map, num_data_stripes); @@ -9476,7 +9523,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u, unsigned long long num_data_stripes; map->num_domains = 1; - num_data_stripes = blocks_per_member(map); + num_data_stripes = imsm_dev_size(dev) / 2; num_data_stripes /= map->blocks_per_strip; num_data_stripes /= map->num_domains; set_num_data_stripes(map, num_data_stripes); @@ -9692,7 +9739,7 @@ static void imsm_process_update(struct supertype *st, new_map = get_imsm_map(&u->dev, MAP_0); new_start = pba_of_lba0(new_map); - new_end = new_start + blocks_per_member(new_map); + new_end = new_start + per_dev_array_size(new_map); inf = get_disk_info(u); /* handle activate_spare versus create race: @@ -9703,7 +9750,7 @@ static void imsm_process_update(struct supertype *st, dev = get_imsm_dev(super, i); map = get_imsm_map(dev, MAP_0); start = pba_of_lba0(map); - end = start + blocks_per_member(map); + end = start + per_dev_array_size(map); if ((new_start >= start && new_start <= end) || (start >= new_start && start <= new_end)) /* overlap */; @@ -10492,7 +10539,7 @@ static struct md_bb *imsm_get_badblocks(struct active_array *a, int slot) return NULL; get_volume_badblocks(super->bbm_log, ord_to_idx(ord), pba_of_lba0(map), - blocks_per_member(map), &super->bb); + per_dev_array_size(map), &super->bb); return &super->bb; } -- 2.18.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor