From 8d2a04e139c44f4d157b36ccfe85a19b44da02e8 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Tue, 15 May 2018 12:17:39 +0100 Subject: Import patches since rc1. --- ...dadm-fix-use-after-free-after-free_mdstat.patch | 37 +++ ...create-RAID-volume-with-link-to-container.patch | 35 +++ ...sh-Fix-some-total-breakage-in-the-test-sc.patch | 80 +++++++ .../0004-imsm-change-reserved-space-to-4MB.patch | 32 +++ ...dd-functions-to-get-and-set-imsm-dev-size.patch | 136 +++++++++++ ...lready-existing-map-to-imsm_num_data_memb.patch | 178 ++++++++++++++ ...-use-blocks_per_member-in-array-size-calc.patch | 266 +++++++++++++++++++++ ...ate-IMSM-volume-with-size-smaller-than-1M.patch | 57 +++++ ...-grow-correct-size-and-chunk_size-casting.patch | 32 +++ debian/patches/series | 9 + 10 files changed, 862 insertions(+) create mode 100644 debian/patches/0001-mdadm-fix-use-after-free-after-free_mdstat.patch create mode 100644 debian/patches/0002-imsm-Allow-create-RAID-volume-with-link-to-container.patch create mode 100644 debian/patches/0003-tests-func.sh-Fix-some-total-breakage-in-the-test-sc.patch create mode 100644 debian/patches/0004-imsm-change-reserved-space-to-4MB.patch create mode 100644 debian/patches/0005-imsm-add-functions-to-get-and-set-imsm-dev-size.patch create mode 100644 debian/patches/0006-imsm-pass-already-existing-map-to-imsm_num_data_memb.patch create mode 100644 debian/patches/0007-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch create mode 100644 debian/patches/0008-Prevent-create-IMSM-volume-with-size-smaller-than-1M.patch create mode 100644 debian/patches/0009-mdadm-grow-correct-size-and-chunk_size-casting.patch (limited to 'debian/patches') diff --git a/debian/patches/0001-mdadm-fix-use-after-free-after-free_mdstat.patch b/debian/patches/0001-mdadm-fix-use-after-free-after-free_mdstat.patch new file mode 100644 index 00000000..4d8ce04b --- /dev/null +++ b/debian/patches/0001-mdadm-fix-use-after-free-after-free_mdstat.patch @@ -0,0 +1,37 @@ +From 1c7c65a3e5d3e5f6d32bfa4cf0d872f87c654eb2 Mon Sep 17 00:00:00 2001 +From: Zhipeng Xie +Date: Tue, 10 Apr 2018 09:25:39 +0800 +Subject: [PATCH 1/9] mdadm: fix use-after-free after free_mdstat + +e->percent access the mdstat_ent which was already freed in free_mdstat + +Signed-off-by: Zhipeng Xie +Signed-off-by: Jes Sorensen +--- + Detail.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Detail.c b/Detail.c +index 4dcf81dd..860241ce 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -561,7 +561,6 @@ int Detail(char *dev, struct context *c) + printf(" %7s Status : %d%% complete\n", + sync_action[e->resync], e->percent); + } +- free_mdstat(ms); + + if ((st && st->sb) && (info && info->reshape_active)) { + #if 0 +@@ -609,6 +608,8 @@ This is pretty boring + printf("\n"); + } else if (e && e->percent >= 0) + printf("\n"); ++ free_mdstat(ms); ++ + if (st && st->sb) + st->ss->detail_super(st, c->homehost); + +-- +2.17.0 + diff --git a/debian/patches/0002-imsm-Allow-create-RAID-volume-with-link-to-container.patch b/debian/patches/0002-imsm-Allow-create-RAID-volume-with-link-to-container.patch new file mode 100644 index 00000000..d23c534e --- /dev/null +++ b/debian/patches/0002-imsm-Allow-create-RAID-volume-with-link-to-container.patch @@ -0,0 +1,35 @@ +From b91ad097d6eecb85cf28915836370288709fbda8 Mon Sep 17 00:00:00 2001 +From: Michal Zylowski +Date: Wed, 4 Apr 2018 14:20:17 +0200 +Subject: [PATCH 2/9] imsm: Allow create RAID volume with link to container + +After 1db03765("Subdevs can't be all missing when create raid device") +raid volume can't be created with link to container. This feature should +not be blocked in Create function. IMSM code forbids creation of +container with missing disk, so case like all dev's missing is already +handled. + +Permit IMSM volume creation when devices are given as link to container. + +Signed-off-by: Michal Zylowski +Signed-off-by: Jes Sorensen +--- + Create.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Create.c b/Create.c +index 50142d81..04b1dfc9 100644 +--- a/Create.c ++++ b/Create.c +@@ -475,7 +475,7 @@ int Create(struct supertype *st, char *mddev, + close(fd); + } + } +- if (missing_disks == dnum) { ++ if (missing_disks == dnum && !have_container) { + pr_err("Subdevs can't be all missing\n"); + return 1; + } +-- +2.17.0 + diff --git a/debian/patches/0003-tests-func.sh-Fix-some-total-breakage-in-the-test-sc.patch b/debian/patches/0003-tests-func.sh-Fix-some-total-breakage-in-the-test-sc.patch new file mode 100644 index 00000000..320d1f07 --- /dev/null +++ b/debian/patches/0003-tests-func.sh-Fix-some-total-breakage-in-the-test-sc.patch @@ -0,0 +1,80 @@ +From 59416da78fc66084f721163b914913dc1da37b44 Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Wed, 11 Apr 2018 17:01:50 -0400 +Subject: [PATCH 3/9] tests/func.sh: Fix some total breakage in the test + scripts + +We will never mandate an obsolete file system such as ext[2-4] for +running the test suite, nor should the test version of mdadm be +installed on the system for the tests to be run. + +Signed-off-by: Jes Sorensen +Fixes: 20d10b4be873ba ("mdadm/test: Refactor and revamp 'test' script") +--- + test | 2 +- + tests/func.sh | 22 +++------------------- + 2 files changed, 4 insertions(+), 20 deletions(-) + +diff --git a/test b/test +index 111a2e74..711a3c7a 100755 +--- a/test ++++ b/test +@@ -5,7 +5,7 @@ mdadm=$PWD/mdadm + targetdir="/var/tmp" + logdir="$targetdir" + config=/tmp/mdadm.conf +-testdir= ++testdir=$PWD/tests + devlist= + + savelogs=0 +diff --git a/tests/func.sh b/tests/func.sh +index a6995f1b..9710a53b 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -101,8 +101,8 @@ check_env() { + echo "test: testing can only be done as 'root'." + exit 1 + } +- [ -x "raid6check" -a -x $mdadm ] || { +- echo "test: please run 'make everything' before perform testing." ++ [ \! -x $mdadm ] && { ++ echo "test: please run make everything before perform testing." + exit 1 + } + cmds=(mdadm lsblk df udevadm losetup mkfs.ext3 fsck seq) +@@ -113,23 +113,6 @@ check_env() { + exit 1 + } + done +- mdadm_src_ver="$($mdadm -V 2>&1)" +- mdadm_sbin_ver="$($(which mdadm) -V 2>&1)" +- if [ "$mdadm_src_ver" != "$mdadm_sbin_ver" ] +- then +- # it's nessesary to 'make install' mdadm to /SBIN/DIR, +- # such as systemd/mdadm-grow-continue@.service, would +- # run as an instance by systemd when reshape happens, +- # thus ensure that the correct mdadm is in testing. +- echo "test: please run 'make install' before testing." +- exit 1 +- fi +- if ! $(df -T . | grep -iq ext) +- then +- # 'external file' bitmap only supports with ext[2-4] file system +- echo "test: please run test suite with ext[2-4] file system." +- exit 1 +- fi + if $(lsblk -a | grep -iq raid) + then + # donot run mdadm -Ss directly if there are RAIDs working. +@@ -231,6 +214,7 @@ check() { + if [ $? -eq 0 ]; then + die "This command shouldn't run successfully" + fi ++ ;; + spares ) + spares=$(tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0) + [ $spares -ne $2 ] && +-- +2.17.0 + diff --git a/debian/patches/0004-imsm-change-reserved-space-to-4MB.patch b/debian/patches/0004-imsm-change-reserved-space-to-4MB.patch new file mode 100644 index 00000000..fa5a593a --- /dev/null +++ b/debian/patches/0004-imsm-change-reserved-space-to-4MB.patch @@ -0,0 +1,32 @@ +From 611d95290dd41d73bd8f9cc06f7ec293a40b819e Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Thu, 5 Apr 2018 13:38:35 +0200 +Subject: [PATCH 4/9] imsm: change reserved space to 4MB + +Due to compatibility to the newest OROM, imsm reserved space has to be +expanded to 4MB. + +Signed-off-by: Mariusz Dabrowski +Signed-off-by: Jes Sorensen +--- + super-intel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index fb1b6936..52011e5b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -88,8 +88,8 @@ + #define MPB_ATTRIB_IGNORED (MPB_ATTRIB_NEVER_USE) + + #define MPB_SECTOR_CNT 2210 +-#define IMSM_RESERVED_SECTORS 4096 +-#define NUM_BLOCKS_DIRTY_STRIPE_REGION 2056 ++#define IMSM_RESERVED_SECTORS 8192 ++#define NUM_BLOCKS_DIRTY_STRIPE_REGION 2048 + #define SECT_PER_MB_SHIFT 11 + #define MAX_SECTOR_SIZE 4096 + #define MULTIPLE_PPL_AREA_SIZE_IMSM (1024 * 1024) /* Size of the whole +-- +2.17.0 + diff --git a/debian/patches/0005-imsm-add-functions-to-get-and-set-imsm-dev-size.patch b/debian/patches/0005-imsm-add-functions-to-get-and-set-imsm-dev-size.patch new file mode 100644 index 00000000..dfdc7f3a --- /dev/null +++ b/debian/patches/0005-imsm-add-functions-to-get-and-set-imsm-dev-size.patch @@ -0,0 +1,136 @@ +From fcc2c9daede11fcc67e4032fd6fa8da198aaa319 Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Thu, 5 Apr 2018 13:38:36 +0200 +Subject: [PATCH 5/9] imsm: add functions to get and set imsm dev size + +Signed-off-by: Mariusz Dabrowski +Signed-off-by: Jes Sorensen +--- + super-intel.c | 41 +++++++++++++++++++++-------------------- + 1 file changed, 21 insertions(+), 20 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 52011e5b..fe2a705b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1201,6 +1201,13 @@ static unsigned long long num_data_stripes(struct imsm_map *map) + return join_u32(map->num_data_stripes_lo, map->num_data_stripes_hi); + } + ++static unsigned long long imsm_dev_size(struct imsm_dev *dev) ++{ ++ if (dev == NULL) ++ return 0; ++ return join_u32(dev->size_low, dev->size_high); ++} ++ + static void set_total_blocks(struct imsm_disk *disk, unsigned long long n) + { + split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi); +@@ -1221,6 +1228,11 @@ static void set_num_data_stripes(struct imsm_map *map, unsigned long long n) + split_ull(n, &map->num_data_stripes_lo, &map->num_data_stripes_hi); + } + ++static void set_imsm_dev_size(struct imsm_dev *dev, unsigned long long n) ++{ ++ split_ull(n, &dev->size_low, &dev->size_high); ++} ++ + static struct extent *get_extents(struct intel_super *super, struct dl *dl) + { + /* find a list of used extents on the given physical device */ +@@ -1503,9 +1515,7 @@ static void print_imsm_dev(struct intel_super *super, + } else + printf(" This Slot : ?\n"); + printf(" Sector Size : %u\n", super->sector_size); +- sz = __le32_to_cpu(dev->size_high); +- sz <<= 32; +- sz += __le32_to_cpu(dev->size_low); ++ sz = imsm_dev_size(dev); + printf(" Array Size : %llu%s\n", + (unsigned long long)sz * 512 / super->sector_size, + human_size(sz * 512)); +@@ -1634,8 +1644,7 @@ void convert_to_4k(struct intel_super *super) + struct imsm_dev *dev = __get_imsm_dev(mpb, i); + struct imsm_map *map = get_imsm_map(dev, MAP_0); + /* dev */ +- split_ull((join_u32(dev->size_low, dev->size_high)/IMSM_4K_DIV), +- &dev->size_low, &dev->size_high); ++ set_imsm_dev_size(dev, imsm_dev_size(dev)/IMSM_4K_DIV); + dev->vol.curr_migr_unit /= IMSM_4K_DIV; + + /* map0 */ +@@ -1762,8 +1771,7 @@ void convert_from_4k(struct intel_super *super) + struct imsm_dev *dev = __get_imsm_dev(mpb, i); + struct imsm_map *map = get_imsm_map(dev, MAP_0); + /* dev */ +- split_ull((join_u32(dev->size_low, dev->size_high)*IMSM_4K_DIV), +- &dev->size_low, &dev->size_high); ++ set_imsm_dev_size(dev, imsm_dev_size(dev)*IMSM_4K_DIV); + dev->vol.curr_migr_unit *= IMSM_4K_DIV; + + /* map0 */ +@@ -3240,9 +3248,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + info->array.chunk_size = + __le16_to_cpu(map_to_analyse->blocks_per_strip) << 9; + info->array.state = !(dev->vol.dirty & RAIDVOL_DIRTY); +- info->custom_array_size = __le32_to_cpu(dev->size_high); +- info->custom_array_size <<= 32; +- info->custom_array_size |= __le32_to_cpu(dev->size_low); ++ info->custom_array_size = imsm_dev_size(dev); + info->recovery_blocked = imsm_reshape_blocks_arrays_changes(st->sb); + + if (is_gen_migration(dev)) { +@@ -5370,8 +5376,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + array_blocks = round_size_to_mb(array_blocks, data_disks); + size_per_member = array_blocks / data_disks; + +- dev->size_low = __cpu_to_le32((__u32) array_blocks); +- dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32)); ++ set_imsm_dev_size(dev, array_blocks); + dev->status = (DEV_READ_COALESCING | DEV_WRITE_COALESCING); + vol = &dev->vol; + vol->migr_state = 0; +@@ -7733,7 +7738,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + level, /* RAID level */ + imsm_level_to_layout(level), + map->num_members, /* raid disks */ +- &chunk, join_u32(dev->size_low, dev->size_high), ++ &chunk, imsm_dev_size(dev), + 1 /* verbose */)) { + pr_err("IMSM RAID geometry validation failed. Array %s activation is blocked.\n", + dev->volume); +@@ -8143,9 +8148,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev, + /* when problems occures + * return current array_blocks value + */ +- array_blocks = __le32_to_cpu(dev->size_high); +- array_blocks = array_blocks << 32; +- array_blocks += __le32_to_cpu(dev->size_low); ++ array_blocks = imsm_dev_size(dev); + + return array_blocks; + } +@@ -8165,8 +8168,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev, + } + + array_blocks = round_size_to_mb(array_blocks, used_disks); +- dev->size_low = __cpu_to_le32((__u32)array_blocks); +- dev->size_high = __cpu_to_le32((__u32)(array_blocks >> 32)); ++ set_imsm_dev_size(dev, array_blocks); + + return array_blocks; + } +@@ -9139,8 +9141,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * + map->blocks_per_strip = + __cpu_to_le16(u->new_chunksize * 2); + num_data_stripes = +- (join_u32(dev->size_low, dev->size_high) +- / used_disks); ++ imsm_dev_size(dev) / used_disks; + num_data_stripes /= map->blocks_per_strip; + num_data_stripes /= map->num_domains; + set_num_data_stripes(map, num_data_stripes); +-- +2.17.0 + diff --git a/debian/patches/0006-imsm-pass-already-existing-map-to-imsm_num_data_memb.patch b/debian/patches/0006-imsm-pass-already-existing-map-to-imsm_num_data_memb.patch new file mode 100644 index 00000000..0a406e80 --- /dev/null +++ b/debian/patches/0006-imsm-pass-already-existing-map-to-imsm_num_data_memb.patch @@ -0,0 +1,178 @@ +From 9529d3436771d9f38884861683dee3b40ab9d180 Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Thu, 5 Apr 2018 13:38:37 +0200 +Subject: [PATCH 6/9] imsm: pass already existing map to imsm_num_data_members + +In almost every place where imsm_num_data_members is called there is +already existing map so it can be used it to avoid mistake when specifying +map for imsm_num_data_members. + +Signed-off-by: Mariusz Dabrowski +Signed-off-by: Jes Sorensen +--- + super-intel.c | 41 +++++++++++++++++++++-------------------- + 1 file changed, 21 insertions(+), 20 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index fe2a705b..3fc3cf4c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2767,13 +2767,11 @@ static __u32 num_stripes_per_unit_rebuild(struct imsm_dev *dev) + return num_stripes_per_unit_resync(dev); + } + +-static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map) ++static __u8 imsm_num_data_members(struct imsm_map *map) + { + /* named 'imsm_' because raid0, raid1 and raid10 + * counter-intuitively have the same number of data disks + */ +- struct imsm_map *map = get_imsm_map(dev, second_map); +- + switch (get_imsm_raid_level(map)) { + case 0: + return map->num_members; +@@ -2862,7 +2860,7 @@ static __u64 blocks_per_migr_unit(struct intel_super *super, + */ + stripes_per_unit = num_stripes_per_unit_resync(dev); + migr_chunk = migr_strip_blocks_resync(dev); +- disks = imsm_num_data_members(dev, MAP_0); ++ disks = imsm_num_data_members(map); + blocks_per_unit = stripes_per_unit * migr_chunk * disks; + stripe = __le16_to_cpu(map->blocks_per_strip) * disks; + segment = blocks_per_unit / stripe; +@@ -3381,7 +3379,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + (unsigned long long)blocks_per_unit, + info->reshape_progress); + +- used_disks = imsm_num_data_members(dev, MAP_1); ++ used_disks = imsm_num_data_members(prev_map); + if (used_disks > 0) { + array_blocks = blocks_per_member(map) * + used_disks; +@@ -8140,9 +8138,9 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev) + static unsigned long long imsm_set_array_size(struct imsm_dev *dev, + long long new_size) + { +- int used_disks = imsm_num_data_members(dev, MAP_0); + unsigned long long array_blocks; +- struct imsm_map *map; ++ struct imsm_map *map = get_imsm_map(dev, MAP_0); ++ int used_disks = imsm_num_data_members(map); + + if (used_disks == 0) { + /* when problems occures +@@ -8155,17 +8153,15 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev, + + /* set array size in metadata + */ +- if (new_size <= 0) { ++ if (new_size <= 0) + /* OLCE size change is caused by added disks + */ +- map = get_imsm_map(dev, MAP_0); + array_blocks = blocks_per_member(map) * used_disks; +- } else { ++ else + /* Online Volume Size Change + * Using available free space + */ + array_blocks = new_size; +- } + + array_blocks = round_size_to_mb(array_blocks, used_disks); + set_imsm_dev_size(dev, array_blocks); +@@ -8274,7 +8270,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent) + int used_disks; + struct mdinfo *mdi; + +- used_disks = imsm_num_data_members(dev, MAP_0); ++ used_disks = imsm_num_data_members(map); + if (used_disks > 0) { + array_blocks = + blocks_per_member(map) * +@@ -9132,8 +9128,10 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * + */ + if (u->new_chunksize > 0) { + unsigned long long num_data_stripes; ++ struct imsm_map *dest_map = ++ get_imsm_map(dev, MAP_0); + int used_disks = +- imsm_num_data_members(dev, MAP_0); ++ imsm_num_data_members(dest_map); + + if (used_disks == 0) + return ret_val; +@@ -9210,7 +9208,7 @@ static int apply_size_change_update(struct imsm_update_size_change *u, + if (id->index == (unsigned)u->subdev) { + struct imsm_dev *dev = get_imsm_dev(super, u->subdev); + struct imsm_map *map = get_imsm_map(dev, MAP_0); +- int used_disks = imsm_num_data_members(dev, MAP_0); ++ int used_disks = imsm_num_data_members(map); + unsigned long long blocks_per_member; + unsigned long long num_data_stripes; + +@@ -10589,7 +10587,7 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev, + max(map_dest->blocks_per_strip, map_src->blocks_per_strip); + migr_rec->dest_depth_per_unit *= + max(map_dest->blocks_per_strip, map_src->blocks_per_strip); +- new_data_disks = imsm_num_data_members(dev, MAP_0); ++ new_data_disks = imsm_num_data_members(map_dest); + migr_rec->blocks_per_unit = + __cpu_to_le32(migr_rec->dest_depth_per_unit * new_data_disks); + migr_rec->dest_depth_per_unit = +@@ -10657,7 +10655,7 @@ int save_backup_imsm(struct supertype *st, + int dest_layout = 0; + int dest_chunk; + unsigned long long start; +- int data_disks = imsm_num_data_members(dev, MAP_0); ++ int data_disks = imsm_num_data_members(map_dest); + + targets = xmalloc(new_disks * sizeof(int)); + +@@ -11279,6 +11277,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + 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; +@@ -11369,7 +11368,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + + super = st->sb; + dev = get_imsm_dev(super, super->current_vol); +- data_disks = imsm_num_data_members(dev , MAP_0); ++ 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; +@@ -11838,7 +11838,7 @@ static int imsm_manage_reshape( + struct intel_dev *dv; + unsigned int sector_size = super->sector_size; + struct imsm_dev *dev = NULL; +- struct imsm_map *map_src; ++ struct imsm_map *map_src, *map_dest; + int migr_vol_qan = 0; + int ndata, odata; /* [bytes] */ + int chunk; /* [bytes] */ +@@ -11876,12 +11876,13 @@ static int imsm_manage_reshape( + goto abort; + } + ++ map_dest = get_imsm_map(dev, MAP_0); + map_src = get_imsm_map(dev, MAP_1); + if (map_src == NULL) + goto abort; + +- ndata = imsm_num_data_members(dev, MAP_0); +- odata = imsm_num_data_members(dev, MAP_1); ++ ndata = imsm_num_data_members(map_dest); ++ odata = imsm_num_data_members(map_src); + + chunk = __le16_to_cpu(map_src->blocks_per_strip) * 512; + old_data_stripe_length = odata * chunk; +-- +2.17.0 + diff --git a/debian/patches/0007-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch b/debian/patches/0007-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch new file mode 100644 index 00000000..f0fc0c42 --- /dev/null +++ b/debian/patches/0007-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch @@ -0,0 +1,266 @@ +From 444909385fdaccf961308c4319d7029b82bf8bb1 Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Thu, 5 Apr 2018 13:38:38 +0200 +Subject: [PATCH 7/9] imsm: do not use blocks_per_member in array size + calculations + +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 +Signed-off-by: Jes Sorensen +--- + super-intel.c | 105 ++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 76 insertions(+), 29 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 3fc3cf4c..c55c85f1 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.17.0 + diff --git a/debian/patches/0008-Prevent-create-IMSM-volume-with-size-smaller-than-1M.patch b/debian/patches/0008-Prevent-create-IMSM-volume-with-size-smaller-than-1M.patch new file mode 100644 index 00000000..ab361401 --- /dev/null +++ b/debian/patches/0008-Prevent-create-IMSM-volume-with-size-smaller-than-1M.patch @@ -0,0 +1,57 @@ +From 54865c30d5b94920318950e29a4f6c1ce075cae8 Mon Sep 17 00:00:00 2001 +From: Roman Sobanski +Date: Wed, 25 Apr 2018 11:25:06 +0200 +Subject: [PATCH 8/9] Prevent create IMSM volume with size smaller than 1M or + chunk + +Block creation of the imsm volume when given size is smaller than 1M and +print appropriate message. + +Commit b53bfba6119d3f6f56eb9e10e5a59da6901af159 +(imsm: use rounded size for metadata initialization) introduces issue with +rounding volume sizes smaller than 1M to 0. There is an inconsistency when +size smaller than 1M was given depends of what we give as target device: +1) When block devices was given created volume has maximum available size. +2) When container symlink was given created volume has size 0. Additionally +it causes below call trace: + +[69587.891556] WARNING: CPU: 28 PID: 22485 at ../drivers/md/md.c:7582 md_seq_show+0x764/0x770 [md_mod] +[69588.066405] Call Trace: +[69588.066409] seq_read+0x336/0x430 +[69588.066411] proc_reg_read+0x40/0x70 +[69588.066412] __vfs_read+0x26/0x140 +[69588.066414] vfs_read+0x89/0x130 +[69588.066415] SyS_read+0x42/0x90 +[69588.066417] do_syscall_64+0x74/0x140 +[69588.066419] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 + +Signed-off-by: Roman Sobanski +Signed-off-by: Jes Sorensen +--- + super-intel.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/super-intel.c b/super-intel.c +index c55c85f1..520abf5d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7358,6 +7358,16 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + verbose); + } + ++ if (size && ((size < 1024) || (*chunk != UnSet && ++ size < (unsigned long long) *chunk))) { ++ pr_err("Given size must be greater than 1M and chunk size.\n"); ++ /* Depends on algorithm in Create.c : ++ * if container was given (dev == NULL) return -1, ++ * if block device was given ( dev != NULL) return 0. ++ */ ++ return dev ? -1 : 0; ++ } ++ + if (!dev) { + if (st->sb) { + struct intel_super *super = st->sb; +-- +2.17.0 + diff --git a/debian/patches/0009-mdadm-grow-correct-size-and-chunk_size-casting.patch b/debian/patches/0009-mdadm-grow-correct-size-and-chunk_size-casting.patch new file mode 100644 index 00000000..34ef5c8a --- /dev/null +++ b/debian/patches/0009-mdadm-grow-correct-size-and-chunk_size-casting.patch @@ -0,0 +1,32 @@ +From 5d518de84e7cd3382b4984cc1243ddb4102aa4f4 Mon Sep 17 00:00:00 2001 +From: Roman Sobanski +Date: Fri, 27 Apr 2018 12:12:21 +0200 +Subject: [PATCH 9/9] mdadm/grow: correct size and chunk_size casting + +With commit 4b74a905a67e +("mdadm/grow: Component size must be larger than chunk size") mdadm returns +incorrect message if size given to grow was greater than 2 147 483 647 K. +Cast chunk_size to "unsigned long long" instead of casting size to "int". + +Signed-off-by: Roman Sobanski +Signed-off-by: Jes Sorensen +--- + Grow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index 87229692..a4be7e7b 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1821,7 +1821,7 @@ int Grow_reshape(char *devname, int fd, + } + + if (array.level > 1 && s->size > 1 && +- (array.chunk_size / 1024) > (int)s->size) { ++ (unsigned long long) (array.chunk_size / 1024) > s->size) { + pr_err("component size must be larger than chunk size.\n"); + return 1; + } +-- +2.17.0 + diff --git a/debian/patches/series b/debian/patches/series index 728fabf4..5cf73e5f 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,12 @@ +0001-mdadm-fix-use-after-free-after-free_mdstat.patch +0002-imsm-Allow-create-RAID-volume-with-link-to-container.patch +0003-tests-func.sh-Fix-some-total-breakage-in-the-test-sc.patch +0004-imsm-change-reserved-space-to-4MB.patch +0005-imsm-add-functions-to-get-and-set-imsm-dev-size.patch +0006-imsm-pass-already-existing-map-to-imsm_num_data_memb.patch +0007-imsm-do-not-use-blocks_per_member-in-array-size-calc.patch +0008-Prevent-create-IMSM-volume-with-size-smaller-than-1M.patch +0009-mdadm-grow-correct-size-and-chunk_size-casting.patch debian-conffile-location.diff debian-no-Werror.diff sha1-includes.diff -- cgit v1.2.3