From 6148d71c1decc8355d58553da944fd7b6a7fbf35 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 30 Apr 2012 17:46:25 +0200 Subject: [PATCH] Fix a large number of bzs: - Fix Monitor mode sometimes crashes when a resync completes - Fix missing symlink for mdadm container device when incremental creates the array - Make sure when creating a second array in a container that the second array uses all available space since leaving space for a third array is invalid - Validate the number of imsm volumes per controller - Fix issues with imsm arrays and disks larger than 2TB - Add support for expanding imsm arrays/containers - The support for expanding imsm arrays/containers was accepted upstream, update to the official patches from there - Fix for the issue of --add not being very smart - Fix an issue causing rebuilds to fail to restart on reboot (data corrupter level problem) - Reset the bad flag on map file updates - Correctly fix failure when trying to add internal bitmap to 1.0 arrays - Resolves: bz817023 (f17) bz817024 (f17) bz817026 (f17) bz817028 (f17) - Resolves: bz817029 (f17) bz817032 (f17) bz817038 (f17) bz808774 (f17) - Resolves: bz817039 (f17) bz817042 (f17) Signed-off-by: Jes Sorensen --- ...2.3-Bitmap_offset-is-a-signed-number.patch | 66 +++ ...cond-array-is-in-read-only-state-dur.patch | 85 +++ ...X-Detect-error-and-rollback-metadata.patch | 62 +++ ...3.2.3-FIX-Extend-size-of-raid0-array.patch | 84 +++ ...IX-Respect-metadata-size-limitations.patch | 50 ++ ...is-possible-as-standalone-change-onl.patch | 30 ++ ...IX-Support-metadata-changes-rollback.patch | 118 +++++ ...tension-of-bitmap_offset-in-super1.c.patch | 40 ++ ...set_num_signed-and-use-it-to-set-bit.patch | 68 +++ ...-Manage-allow-re-add-to-failed-array.patch | 66 +++ ...covery-while-adding-multiple-devices.patch | 66 +++ ...age-replace-return-1-with-goto-abort.patch | 347 ++++++++++++ ...it-of-1024-when-scanning-for-devices.patch | 81 +++ ...estrictions-on-when-add-is-permitted.patch | 85 +++ ...3-Remove-avail_disks-arg-from-enough.patch | 171 ++++++ ...m-3.2.3-Reset-bad-flag-on-map-update.patch | 32 ++ ...sk-over-2TB-is-used-to-create-contai.patch | 52 ++ ...-size-in-validate_geometry_imsm_orom.patch | 69 +++ ...-not-used-after-loading-metadata-fro.patch | 72 +++ ...-3.2.3-fix-Monitor-sometimes-crashes.patch | 34 ++ ...ainer-creation-with-incremental-used.patch | 34 ++ ...orrect-extending-size-of-raid0-array.patch | 31 ++ ...imsm-Add-function-imsm_get_free_size.patch | 63 +++ ...adata-update-for-volume-size-expansi.patch | 238 +++++++++ ...e-size-change-for-external-metatdata.patch | 129 +++++ ...ume-size-expand-support-to-imsm_anal.patch | 103 ++++ ...m-FIX-Component-size-alignment-check.patch | 126 +++++ ...IX-Support-metadata-changes-rollback.patch | 130 +++++ ...function-imsm_num_data_members-for-R.patch | 36 ++ ...ting-max-size-for-size-change-operat.patch | 60 +++ ...m-avoid-overflows-for-disks-over-1TB.patch | 484 +++++++++++++++++ ...imum-volumes-per-controller-in-detai.patch | 29 + ...build-does-not-continue-after-reboot.patch | 62 +++ ...ond-array-need-to-have-the-whole-ava.patch | 40 ++ ...x-thunderdome-may-drop-2tb-attribute.patch | 33 ++ ...uper_all-supports-loading-metadata-f.patch | 157 ++++++ ..._super_imsm_all-function-refactoring.patch | 261 +++++++++ ...msm-set-2tb-disk-attribute-for-spare.patch | 30 ++ ...e-number-of-imsm-volumes-per-control.patch | 497 ++++++++++++++++++ ...mes-disks-support-in-detail-platform.patch | 39 ++ ....3-simplify-calculating-array_blocks.patch | 47 ++ mdadm.spec | 107 +++- 42 files changed, 4413 insertions(+), 1 deletion(-) create mode 100644 mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch create mode 100644 mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch create mode 100644 mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch create mode 100644 mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch create mode 100644 mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch create mode 100644 mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch create mode 100644 mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch create mode 100644 mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch create mode 100644 mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch create mode 100644 mdadm-3.2.3-Manage-allow-re-add-to-failed-array.patch create mode 100644 mdadm-3.2.3-Manage-freeze-recovery-while-adding-multiple-devices.patch create mode 100644 mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch create mode 100644 mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch create mode 100644 mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch create mode 100644 mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch create mode 100644 mdadm-3.2.3-Reset-bad-flag-on-map-update.patch create mode 100644 mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch create mode 100644 mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch create mode 100644 mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch create mode 100644 mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch create mode 100644 mdadm-3.2.3-fix-container-creation-with-incremental-used.patch create mode 100644 mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch create mode 100644 mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch create mode 100644 mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch create mode 100644 mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch create mode 100644 mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch create mode 100644 mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch create mode 100644 mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch create mode 100644 mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch create mode 100644 mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch create mode 100644 mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch create mode 100644 mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch create mode 100644 mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch create mode 100644 mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch create mode 100644 mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch create mode 100644 mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch create mode 100644 mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch create mode 100644 mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch create mode 100644 mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch create mode 100644 mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch create mode 100644 mdadm-3.2.3-simplify-calculating-array_blocks.patch diff --git a/mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch b/mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch new file mode 100644 index 0000000..f40fe62 --- /dev/null +++ b/mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch @@ -0,0 +1,66 @@ +From fbdef49811c9e2b54e2064d9af68cfffa77c6e77 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 4 Apr 2012 14:00:42 +1000 +Subject: [PATCH] Bitmap_offset is a signed number + +As the bitmap can be before the superblock, bitmap_offset is signed. +But some of the code didn't honour that :-( + +Signed-off-by: NeilBrown +--- + mdadm.h | 2 +- + super1.c | 4 ++-- + sysfs.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/mdadm.h b/mdadm.h +index 941cffa..9f58800 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -211,7 +211,7 @@ struct mdinfo { + unsigned long long recovery_start; /* per-device rebuild position */ + #define MaxSector (~0ULL) /* resync/recovery complete position */ + }; +- unsigned long bitmap_offset; /* 0 == none, 1 == a file */ ++ long bitmap_offset; /* 0 == none, 1 == a file */ + unsigned long safe_mode_delay; /* ms delay to mark clean */ + int new_level, delta_disks, new_layout, new_chunk; + int errors; +diff --git a/super1.c b/super1.c +index 20f4c86..2770a7f 100644 +--- a/super1.c ++++ b/super1.c +@@ -620,7 +620,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + info->data_offset = __le64_to_cpu(sb->data_offset); + info->component_size = __le64_to_cpu(sb->size); + if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) +- info->bitmap_offset = __le32_to_cpu(sb->bitmap_offset); ++ info->bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset); + + info->disk.major = 0; + info->disk.minor = 0; +@@ -1636,7 +1636,7 @@ add_internal_bitmap1(struct supertype *st, + offset = -room; + } + +- sb->bitmap_offset = __cpu_to_le32(offset); ++ sb->bitmap_offset = (long)__cpu_to_le32(offset); + + sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) + | MD_FEATURE_BITMAP_OFFSET); +diff --git a/sysfs.c b/sysfs.c +index cddabae..a1007cf 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -226,7 +226,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options) + else if (strncmp(buf, "none", 4) == 0) + sra->bitmap_offset = 0; + else if (buf[0] == '+') +- sra->bitmap_offset = strtoul(buf+1, NULL, 10); ++ sra->bitmap_offset = strtol(buf+1, NULL, 10); + else + goto abort; + } +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch b/mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch new file mode 100644 index 0000000..4f8d3b0 --- /dev/null +++ b/mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch @@ -0,0 +1,85 @@ +From 4aecb54a211a77aa0589aa2abb8acd992ae8795a Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:08 +0200 +Subject: [PATCH 14/14] FIX: Assembled second array is in read only state + during reshape + +When arrays using external metadata are assembled, and one of array +in container is under reshape, second array will remain in read only +state (not auto read only). It is caused by array fact that array +is frozen and mdmon doesn't has opportunity to switch array in r/w mode. + +Freezing not reshaped array just after it is being assembled allows mdmon +to enable it for writing. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Assemble.c | 29 +++++++++++++++++++++-------- + 1 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 23695e7..080993d 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1558,6 +1558,7 @@ int assemble_container_content(struct supertype *st, int mdfd, + int expansion = 0; + struct map_ent *map = NULL; + int old_raid_disks; ++ int start_reshape; + + sysfs_init(content, mdfd, 0); + +@@ -1569,7 +1570,17 @@ int assemble_container_content(struct supertype *st, int mdfd, + return 1; + } + +- if (st->ss->external && content->recovery_blocked) ++ /* There are two types of reshape: container wide or sub-array specific ++ * Check if metadata requests blocking container wide reshapes ++ */ ++ start_reshape = (content->reshape_active && ++ !((content->reshape_active == CONTAINER_RESHAPE) && ++ (content->array.state & (1<ss->external && content->recovery_blocked && start_reshape) + block_subarray(content); + + if (sra) +@@ -1595,14 +1606,7 @@ int assemble_container_content(struct supertype *st, int mdfd, + (working + preexist + expansion) >= + content->array.working_disks) { + int err; +- int start_reshape; + +- /* There are two types of reshape: container wide or sub-array specific +- * Check if metadata requests blocking container wide reshapes +- */ +- start_reshape = (content->reshape_active && +- !((content->reshape_active == CONTAINER_RESHAPE) && +- (content->array.state & (1<array.raid_disks + expansion; + if (restore_backup(st, content, +@@ -1646,6 +1650,15 @@ int assemble_container_content(struct supertype *st, int mdfd, + } + if (!err) + sysfs_set_safemode(content, content->safe_mode_delay); ++ ++ /* Block subarray here if it is not reshaped now ++ * It has be blocked a little later to allow mdmon to switch in ++ * in to R/W state ++ */ ++ if (st->ss->external && content->recovery_blocked && ++ !start_reshape) ++ block_subarray(content); ++ + if (verbose >= 0) { + if (err) + fprintf(stderr, Name +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch b/mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch new file mode 100644 index 0000000..a9bf745 --- /dev/null +++ b/mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch @@ -0,0 +1,62 @@ +From 65a9798b58b4e4de0157043e2b30a738c27eff43 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:03 +0200 +Subject: [PATCH 09/14] FIX: Detect error and rollback metadata + +Some setting size error cases were not detected. +When error occurs, stop setting new size action and rollback metadata +changes. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 13 +++++++++++-- + 1 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 86d1020..1b45199 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1665,9 +1665,12 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + * understands '0' to mean 'max'. + */ + min_csize = 0; ++ rv = 0; + for (mdi = sra->devs; mdi; mdi = mdi->next) { +- if (sysfs_set_num(sra, mdi, "size", size) < 0) ++ if (sysfs_set_num(sra, mdi, "size", size) < 0) { ++ rv = 1; + break; ++ } + if (array.not_persistent == 0 && + array.major_version == 0 && + get_linux_version() < 3001000) { +@@ -1682,11 +1685,16 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + } + } + } ++ if (rv) { ++ fprintf(stderr, Name ": Cannot set size on " ++ "array members.\n"); ++ goto size_change_error; ++ } + if (min_csize && size > min_csize) { + fprintf(stderr, Name ": Cannot safely make this array " + "use more than 2TB per device on this kernel.\n"); + rv = 1; +- goto release; ++ goto size_change_error; + } + if (min_csize && size == 0) { + /* Don't let the kernel choose a size - it will get +@@ -1748,6 +1756,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + ioctl(fd, GET_ARRAY_INFO, &array); + } + ++size_change_error: + if (rv != 0) { + int err = errno; + +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch b/mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch new file mode 100644 index 0000000..d36ca59 --- /dev/null +++ b/mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch @@ -0,0 +1,84 @@ +From 44f6f18113b1764a9d1234d3ff9a6bac968b03b8 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:01 +0200 +Subject: [PATCH 07/14] FIX: Extend size of raid0 array + +For raid0, takeover operation is required for size change. +Add takeover to degraded raid4 before size change and back to raid0 after. +Array information has to be read again from md after takeover. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 35 +++++++++++++++++++++++++++++++++++ + 1 files changed, 35 insertions(+), 0 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 8c7bafc..e8f6554 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + long long orig_size = get_component_size(fd)/2; + long long min_csize; + struct mdinfo *mdi; ++ int raid0_takeover = 0; + + if (orig_size == 0) + orig_size = array.size; +@@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + "2TB per device\n"); + size = min_csize; + } ++ if (st->ss->external) { ++ if (sra->array.level == 0) { ++ rv = sysfs_set_str(sra, NULL, "level", ++ "raid5"); ++ if (!rv) { ++ raid0_takeover = 1; ++ /* get array parametes after takeover ++ * to chane one parameter at time only ++ */ ++ rv = ioctl(fd, GET_ARRAY_INFO, &array); ++ } ++ } ++ /* make sure mdmon is ++ * aware of the new level */ ++ if (!mdmon_running(st->container_dev)) ++ start_mdmon(st->container_dev); ++ ping_monitor(container); ++ if (mdmon_running(st->container_dev) && ++ st->update_tail == NULL) ++ st->update_tail = &st->updates; ++ } ++ + array.size = size; + if (array.size != size) { + /* got truncated to 32bit, write to +@@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + rv = -1; + } else { + rv = ioctl(fd, SET_ARRAY_INFO, &array); ++ + /* manage array size when it is managed externally + */ + if ((rv == 0) && st->ss->external) + rv = set_array_size(st, sra, sra->text_version); + } + ++ if (raid0_takeover) { ++ /* do not recync non-existing parity, ++ * we will drop it anyway ++ */ ++ sysfs_set_str(sra, NULL, "sync_action", "idle"); ++ /* go back to raid0, drop parity disk ++ */ ++ sysfs_set_str(sra, NULL, "level", "raid0"); ++ ioctl(fd, GET_ARRAY_INFO, &array); ++ } ++ + if (rv != 0) { + int err = errno; + +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch b/mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch new file mode 100644 index 0000000..0a76c6c --- /dev/null +++ b/mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch @@ -0,0 +1,50 @@ +From 7e7e9a4d72323fe0298c9f5741245b0f11165a31 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:02 +0200 +Subject: [PATCH 08/14] FIX: Respect metadata size limitations + +When reshape_super() updates metadata with new size, due to some metadata +limitations saved value can be different than requested value by user. +Update size (read it from metadata) for setting it in md. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 21 +++++++++++++++++++++ + 1 files changed, 21 insertions(+), 0 deletions(-) + +diff --git a/Grow.c b/Grow.c +index e8f6554..86d1020 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1637,6 +1637,27 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + goto release; + } + sync_metadata(st); ++ if (st->ss->external) { ++ /* metadata can have size limitation ++ * update size value according to metadata information ++ */ ++ struct mdinfo *sizeinfo = ++ st->ss->container_content(st, subarray); ++ if (sizeinfo) { ++ unsigned long long new_size = ++ sizeinfo->custom_array_size/2; ++ int data_disks = get_data_disks( ++ sizeinfo->array.level, ++ sizeinfo->array.layout, ++ sizeinfo->array.raid_disks); ++ new_size /= data_disks; ++ dprintf("Metadata size correction from %llu to " ++ "%llu (%llu)\n", orig_size, new_size, ++ new_size * data_disks); ++ size = new_size; ++ sysfs_free(sizeinfo); ++ } ++ } + + /* Update the size of each member device in case + * they have been resized. This will never reduce +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch b/mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch new file mode 100644 index 0000000..30e703c --- /dev/null +++ b/mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch @@ -0,0 +1,30 @@ +From 58d26a2a81c4ad93ccce88865f2c4ac2588bec69 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:07 +0200 +Subject: [PATCH 13/14] FIX: Size change is possible as standalone change only + +Size change is possible as standalone change only. To make sure size change +is not requested pass '-1' as size parameter. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 1b45199..389992e 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1973,7 +1973,7 @@ size_change_error: + /* Impose these changes on a single array. First + * check that the metadata is OK with the change. */ + +- if (reshape_super(st, info.component_size, info.new_level, ++ if (reshape_super(st, -1, info.new_level, + info.new_layout, info.new_chunk, + info.array.raid_disks, info.delta_disks, + backup_file, devname, APPLY_METADATA_CHANGES, +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch b/mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch new file mode 100644 index 0000000..6fce01f --- /dev/null +++ b/mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch @@ -0,0 +1,118 @@ +From 016e00f54635138ce34b9e4ba18d37e182288bd1 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:51:59 +0200 +Subject: [PATCH 05/14] FIX: Support metadata changes rollback + +Function reshape_super() guards metadata changes. +It is used to apply changes rollback in error case also. +As change (apply and rollback) can be not bi-directional reshape_super() +has to know if current action is metadata change that should be guarded +using metadata restrictions, or this is metadata rollback change +executed due to error occurrence. + +In second case change has to be unconditional. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 16 ++++++++++------ + mdadm.h | 4 ++++ + super-intel.c | 2 +- + 3 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 5fd44aa..8c7bafc 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -650,7 +650,7 @@ static void wait_reshape(struct mdinfo *sra) + static int reshape_super(struct supertype *st, long long size, int level, + int layout, int chunksize, int raid_disks, + int delta_disks, char *backup_file, char *dev, +- int verbose) ++ int direction, int verbose) + { + /* nothing extra to check in the native case */ + if (!st->ss->external) +@@ -664,7 +664,7 @@ static int reshape_super(struct supertype *st, long long size, int level, + + return st->ss->reshape_super(st, size, level, layout, chunksize, + raid_disks, delta_disks, backup_file, dev, +- verbose); ++ direction, verbose); + } + + static void sync_metadata(struct supertype *st) +@@ -1631,7 +1631,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + orig_size = array.size; + + if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL, +- devname, !quiet)) { ++ devname, APPLY_METADATA_CHANGES, !quiet)) { + rv = 1; + goto release; + } +@@ -1697,7 +1697,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + + /* restore metadata */ + if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, +- UnSet, NULL, devname, !quiet) == 0) ++ UnSet, NULL, devname, ++ ROLLBACK_METADATA_CHANGES, ++ !quiet) == 0) + sync_metadata(st); + fprintf(stderr, Name ": Cannot set device size for %s: %s\n", + devname, strerror(err)); +@@ -1909,7 +1911,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + if (reshape_super(st, info.component_size, info.new_level, + info.new_layout, info.new_chunk, + info.array.raid_disks, info.delta_disks, +- backup_file, devname, quiet)) { ++ backup_file, devname, APPLY_METADATA_CHANGES, ++ quiet)) { + rv = 1; + goto release; + } +@@ -2608,7 +2611,8 @@ int reshape_container(char *container, char *devname, + reshape_super(st, -1, info->new_level, + info->new_layout, info->new_chunk, + info->array.raid_disks, info->delta_disks, +- backup_file, devname, quiet)) { ++ backup_file, devname, APPLY_METADATA_CHANGES, ++ quiet)) { + unfreeze(st); + return 1; + } +diff --git a/mdadm.h b/mdadm.h +index 9f58800..686d4b4 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -740,9 +740,13 @@ extern struct superswitch { + * initialized to indicate if reshape is being performed at the + * container or subarray level + */ ++#define APPLY_METADATA_CHANGES 1 ++#define ROLLBACK_METADATA_CHANGES 0 ++ + int (*reshape_super)(struct supertype *st, long long size, int level, + int layout, int chunksize, int raid_disks, + int delta_disks, char *backup, char *dev, ++ int direction, + int verbose); /* optional */ + int (*manage_reshape)( /* optional */ + int afd, struct mdinfo *sra, struct reshape *reshape, +diff --git a/super-intel.c b/super-intel.c +index ac8922f..32a53d1 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -10018,7 +10018,7 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo) + static int imsm_reshape_super(struct supertype *st, long long size, int level, + int layout, int chunksize, int raid_disks, + int delta_disks, char *backup, char *dev, +- int verbose) ++ int direction, int verbose) + { + int ret_val = 1; + struct geo_params geo; +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch b/mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch new file mode 100644 index 0000000..cf4528e --- /dev/null +++ b/mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch @@ -0,0 +1,40 @@ +From 119374a0ac7d6a73cd296134b0151aa213bbee42 Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Thu, 26 Apr 2012 16:55:10 +0200 +Subject: [PATCH 1/2] Fix sign extension of bitmap_offset in super1.c + +fbdef49811c9e2b54e2064d9af68cfffa77c6e77 incorrectly tried to fix sign +extension of the bitmap offset. However mdinfo->bitmap_offset is a u32 +and needs to be converted to a 32 bit signed integer before the sign +extension. + +Signed-off-by: Jes Sorensen +--- + super1.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/super1.c b/super1.c +index 36369d8..be77c33 100644 +--- a/super1.c ++++ b/super1.c +@@ -620,7 +620,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + info->data_offset = __le64_to_cpu(sb->data_offset); + info->component_size = __le64_to_cpu(sb->size); + if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) +- info->bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset); ++ info->bitmap_offset = (int32_t)__le32_to_cpu(sb->bitmap_offset); + + info->disk.major = 0; + info->disk.minor = 0; +@@ -1651,7 +1651,7 @@ add_internal_bitmap1(struct supertype *st, + offset = -room; + } + +- sb->bitmap_offset = (long)__cpu_to_le32(offset); ++ sb->bitmap_offset = (int32_t)__cpu_to_le32(offset); + + sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) + | MD_FEATURE_BITMAP_OFFSET); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch b/mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch new file mode 100644 index 0000000..6476bb6 --- /dev/null +++ b/mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch @@ -0,0 +1,68 @@ +From 7b5ec34bb072781c0efbba8b21a941fff4d6ae7f Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Thu, 26 Apr 2012 17:05:22 +0200 +Subject: [PATCH 2/2] Introduce sysfs_set_num_signed() and use it to set + bitmap/offset + +mdinfo->bitmap_offset is a signed long and needs to be treated as +such when passed to the kernel. + +This resolves the problem with adding internal bitmaps to a 1.0 array. + +Signed-off-by: Jes Sorensen +--- + Grow.c | 4 ++-- + mdadm.h | 2 ++ + sysfs.c | 8 ++++++++ + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/Grow.c b/Grow.c +index b4b9ff2..0b0d718 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -424,8 +424,8 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int + if (offset_setable) { + st->ss->getinfo_super(st, mdi, NULL); + sysfs_init(mdi, fd, -1); +- rv = sysfs_set_num(mdi, NULL, "bitmap/location", +- mdi->bitmap_offset); ++ rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location", ++ mdi->bitmap_offset); + } else { + array.state |= (1< +Date: Wed, 7 Mar 2012 15:25:57 +1100 +Subject: [PATCH] Manage: allow --re-add to failed array. + +If both "legs" of a RAID1 (or equivalent in RAID10) fail, then one +of the becomes available again it maybe appropriate to re-add the +failed device(s). +So remove the restriction that an array must has 'enough' devices +before being re-added, and if there is no-where to read a superblock +from for matching, then assume the kernel will do necessary checks. + +Signed-off-by: NeilBrown +--- + Manage.c | 16 +++++++++++++--- + 1 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/Manage.c b/Manage.c +index d9775de..4cf6e58 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -723,7 +723,13 @@ int Manage_subdevs(char *devname, int fd, + break; + } + /* FIXME this is a bad test to be using */ +- if (!tst->sb) { ++ if (!tst->sb && ++ dv->re_add) { ++ /* we are re-adding a device to a ++ * completely dead array - have to depend ++ * on kernel to check ++ */ ++ } else if (!tst->sb) { + close(tfd); + st->ss->free_super(st); + fprintf(stderr, Name ": cannot load array metadata from %s\n", devname); +@@ -747,12 +753,16 @@ int Manage_subdevs(char *devname, int fd, + * and was temporarily removed, and is now being re-added. + * If so, we can simply re-add it. + */ +- tst->ss->uuid_from_super(tst, duuid); + + if (st->sb) { + struct mdinfo mdi; + st->ss->getinfo_super(st, &mdi, NULL); + st->ss->uuid_from_super(st, ouuid); ++ if (tst->sb) ++ tst->ss->uuid_from_super(tst, duuid); ++ else ++ /* Assume uuid matches: kernel will check */ ++ memcpy(duuid, ouuid, sizeof(ouuid)); + if ((mdi.disk.state & (1< +Date: Thu, 22 Mar 2012 16:15:03 +1100 +Subject: [PATCH 3/3] Manage: freeze recovery while adding multiple devices. + +If the kernel supports it, freeze recovery over multiple adds, +so that they can all be added to the array at the same time and +be recovered in parallel. + +Signed-off-by: NeilBrown +--- + Manage.c | 13 +++++++++++++ + 1 files changed, 13 insertions(+), 0 deletions(-) + +diff --git a/Manage.c b/Manage.c +index f53fe27..7deba3a 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -416,12 +416,15 @@ int Manage_subdevs(char *devname, int fd, + int lfd = -1; + int sysfd = -1; + int count = 0; /* number of actions taken */ ++ struct mdinfo info; ++ int frozen = 0; + + if (ioctl(fd, GET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": cannot get array info for %s\n", + devname); + goto abort; + } ++ sysfs_init(&info, fd, 0); + + /* array.size is only 32 bit and may be truncated. + * So read from sysfs if possible, and record number of sectors +@@ -629,6 +632,12 @@ int Manage_subdevs(char *devname, int fd, + dv->devname, strerror(errno)); + goto abort; + } ++ if (!frozen) { ++ if (sysfs_freeze_array(&info) == 1) ++ frozen = 1; ++ else ++ frozen = -1; ++ } + + st = dup_super(tst); + +@@ -1166,11 +1175,15 @@ int Manage_subdevs(char *devname, int fd, + break; + } + } ++ if (frozen > 0) ++ sysfs_set_str(&info, NULL, "sync_action","idle"); + if (test && count == 0) + return 2; + return 0; + + abort: ++ if (frozen > 0) ++ sysfs_set_str(&info, NULL, "sync_action","idle"); + return 1; + } + +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch b/mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch new file mode 100644 index 0000000..a9d594d --- /dev/null +++ b/mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch @@ -0,0 +1,347 @@ +From bcbb3112d2801594358153956191e4cff6021de3 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 22 Mar 2012 16:07:02 +1100 +Subject: [PATCH 2/3] Manage: replace 'return 1' with 'goto abort'. + +This will allow exit processing in next patch + +Signed-off-by: NeilBrown +--- + Manage.c | 75 ++++++++++++++++++++++++++++++++----------------------------- + 1 files changed, 39 insertions(+), 36 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 4cf6e58..f53fe27 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -420,7 +420,7 @@ int Manage_subdevs(char *devname, int fd, + if (ioctl(fd, GET_ARRAY_INFO, &array)) { + fprintf(stderr, Name ": cannot get array info for %s\n", + devname); +- return 1; ++ goto abort; + } + + /* array.size is only 32 bit and may be truncated. +@@ -435,7 +435,7 @@ int Manage_subdevs(char *devname, int fd, + if (!tst) { + fprintf(stderr, Name ": unsupport array - version %d.%d\n", + array.major_version, array.minor_version); +- return 1; ++ goto abort; + } + + stb.st_rdev = 0; +@@ -457,7 +457,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": %s only meaningful " + "with -r, not -%c\n", + dv->devname, dv->disposition); +- return 1; ++ goto abort; + } + for (; j < 1024 && remaining_disks > 0; j++) { + unsigned dev; +@@ -490,7 +490,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": %s only meaningful " + "with -r of -f, not -%c\n", + dv->devname, dv->disposition); +- return 1; ++ goto abort; + } + for (; j < 1024 && remaining_disks > 0; j++) { + int sfd; +@@ -530,7 +530,7 @@ int Manage_subdevs(char *devname, int fd, + if (dv->disposition != 'a' || dv->re_add == 0) { + fprintf(stderr, Name ": 'missing' only meaningful " + "with --re-add\n"); +- return 1; ++ goto abort; + } + if (add_devlist == NULL) + add_devlist = conf_get_devs(); +@@ -554,7 +554,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": %s only meaningful " + "with -r or -f, not -%c\n", + dv->devname, dv->disposition); +- return 1; ++ goto abort; + } + + sprintf(dname, "dev-%s", dv->devname); +@@ -576,7 +576,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": %s does not appear " + "to be a component of %s\n", + dv->devname, devname); +- return 1; ++ goto abort; + } + } + } else { +@@ -595,7 +595,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname, strerror(errno)); + if (tfd >= 0) + close(tfd); +- return 1; ++ goto abort; + } + close(tfd); + tfd = -1; +@@ -604,21 +604,21 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": %s is not a " + "block device.\n", + dv->devname); +- return 1; ++ goto abort; + } + } + switch(dv->disposition){ + default: + fprintf(stderr, Name ": internal error - devmode[%s]=%d\n", + dv->devname, dv->disposition); +- return 1; ++ goto abort; + case 'a': + /* add the device */ + if (subarray) { + fprintf(stderr, Name ": Cannot add disks to a" + " \'member\' array, perform this" + " operation on the parent container\n"); +- return 1; ++ goto abort; + } + /* Make sure it isn't in use (in 2.6 or later) */ + tfd = dev_open(add_dev, O_RDONLY|O_EXCL|O_DIRECT); +@@ -627,7 +627,7 @@ int Manage_subdevs(char *devname, int fd, + if (tfd < 0) { + fprintf(stderr, Name ": Cannot open %s: %s\n", + dv->devname, strerror(errno)); +- return 1; ++ goto abort; + } + + st = dup_super(tst); +@@ -639,7 +639,7 @@ int Manage_subdevs(char *devname, int fd, + if (!get_dev_size(tfd, dv->devname, &ldsize)) { + st->ss->free_super(st); + close(tfd); +- return 1; ++ goto abort; + } + } else if (!get_dev_size(tfd, NULL, &ldsize)) { + st->ss->free_super(st); +@@ -661,7 +661,7 @@ int Manage_subdevs(char *devname, int fd, + add_dev, devname); + st->ss->free_super(st); + close(tfd); +- return 1; ++ goto abort; + } + fprintf(stderr, Name + ": %s is larger than %s can " +@@ -686,7 +686,7 @@ int Manage_subdevs(char *devname, int fd, + + fprintf(stderr, Name ": hot add failed for %s: %s\n", + add_dev, strerror(errno)); +- return 1; ++ goto abort; + } + + if (array.not_persistent == 0 || tst->ss->external) { +@@ -733,7 +733,7 @@ int Manage_subdevs(char *devname, int fd, + close(tfd); + st->ss->free_super(st); + fprintf(stderr, Name ": cannot load array metadata from %s\n", devname); +- return 1; ++ goto abort; + } + + /* Make sure device is large enough */ +@@ -746,7 +746,7 @@ int Manage_subdevs(char *devname, int fd, + continue; + fprintf(stderr, Name ": %s not large enough to join array\n", + dv->devname); +- return 1; ++ goto abort; + } + + /* Possibly this device was recently part of the array +@@ -799,7 +799,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": failed to open %s for" + " superblock update during re-add\n", dv->devname); + st->ss->free_super(st); +- return 1; ++ goto abort; + } + + if (dv->writemostly == 1) +@@ -822,7 +822,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name ": failed to update" + " superblock during re-add\n"); + st->ss->free_super(st); +- return 1; ++ goto abort; + } + } + /* don't even try if disk is marked as faulty */ +@@ -840,7 +840,7 @@ int Manage_subdevs(char *devname, int fd, + st->ss->free_super(st); + if (add_dev != dv->devname) + continue; +- return 1; ++ goto abort; + } + skip_re_add: + re_add_failed = 1; +@@ -864,7 +864,7 @@ int Manage_subdevs(char *devname, int fd, + fprintf(stderr, Name + ": --re-add for %s to %s is not possible\n", + dv->devname, devname); +- return 1; ++ goto abort; + } + if (re_add_failed) { + fprintf(stderr, Name ": %s reports being an active member for %s, but a --re-add fails.\n", +@@ -875,7 +875,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname); + if (tfd >= 0) + close(tfd); +- return 1; ++ goto abort; + } + } else { + /* non-persistent. Must ensure that new drive +@@ -886,7 +886,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname); + if (tfd >= 0) + close(tfd); +- return 1; ++ goto abort; + } + } + /* committed to really trying this device now*/ +@@ -921,11 +921,11 @@ int Manage_subdevs(char *devname, int fd, + if (tst->ss->add_to_super(tst, &disc, dfd, + dv->devname)) { + close(dfd); +- return 1; ++ goto abort; + } + if (tst->ss->write_init_super(tst)) { + close(dfd); +- return 1; ++ goto abort; + } + } else if (dv->re_add) { + /* this had better be raid1. +@@ -974,7 +974,7 @@ int Manage_subdevs(char *devname, int fd, + " could not get exclusive access to container\n", + dv->devname); + tst->ss->free_super(tst); +- return 1; ++ goto abort; + } + + dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); +@@ -984,7 +984,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname)) { + close(dfd); + close(container_fd); +- return 1; ++ goto abort; + } + if (tst->update_tail) + flush_metadata_updates(tst); +@@ -997,7 +997,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname); + close(container_fd); + tst->ss->free_super(tst); +- return 1; ++ goto abort; + } + sra->array.level = LEVEL_CONTAINER; + /* Need to set data_offset and component_size */ +@@ -1013,7 +1013,7 @@ int Manage_subdevs(char *devname, int fd, + " failed for %s\n", dv->devname); + close(container_fd); + sysfs_free(sra); +- return 1; ++ goto abort; + } + ping_monitor_by_id(devnum); + sysfs_free(sra); +@@ -1023,7 +1023,7 @@ int Manage_subdevs(char *devname, int fd, + if (ioctl(fd, ADD_NEW_DISK, &disc)) { + fprintf(stderr, Name ": add new device failed for %s as %d: %s\n", + dv->devname, j, strerror(errno)); +- return 1; ++ goto abort; + } + } + if (verbose >= 0) +@@ -1038,7 +1038,7 @@ int Manage_subdevs(char *devname, int fd, + " operation on the parent container\n"); + if (sysfd >= 0) + close(sysfd); +- return 1; ++ goto abort; + } + if (tst->ss->external) { + /* To remove a device from a container, we must +@@ -1058,7 +1058,7 @@ int Manage_subdevs(char *devname, int fd, + " to container - odd\n"); + if (sysfd >= 0) + close(sysfd); +- return 1; ++ goto abort; + } + /* in the detached case it is not possible to + * check if we are the unique holder, so just +@@ -1075,7 +1075,7 @@ int Manage_subdevs(char *devname, int fd, + errno == EEXIST ? "still in use": + "not a member"); + close(lfd); +- return 1; ++ goto abort; + } + } + /* FIXME check that it is a current member */ +@@ -1118,7 +1118,7 @@ int Manage_subdevs(char *devname, int fd, + strerror(errno)); + if (lfd >= 0) + close(lfd); +- return 1; ++ goto abort; + } + if (tst->ss->external) { + /* +@@ -1131,7 +1131,7 @@ int Manage_subdevs(char *devname, int fd, + + if (!name) { + fprintf(stderr, Name ": unable to get container name\n"); +- return 1; ++ goto abort; + } + + ping_manager(name); +@@ -1154,7 +1154,7 @@ int Manage_subdevs(char *devname, int fd, + dnprintable, strerror(errno)); + if (sysfd >= 0) + close(sysfd); +- return 1; ++ goto abort; + } + if (sysfd >= 0) + close(sysfd); +@@ -1169,6 +1169,9 @@ int Manage_subdevs(char *devname, int fd, + if (test && count == 0) + return 2; + return 0; ++ ++abort: ++ return 1; + } + + int autodetect(void) +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch b/mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch new file mode 100644 index 0000000..07e8671 --- /dev/null +++ b/mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch @@ -0,0 +1,81 @@ +From 480f3566411675ec41f18e5f6e15429f891e144c Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 18 Apr 2012 09:06:02 +1000 +Subject: [PATCH] Raid limit of 1024 when scanning for devices. + +When we can for devices using GET_DISK_INFO we currently +limit to 1024. But some arrays can have more than this. +So raise it to 4096 and make the constant a #define. + +Signed-off-by: NeilBrown +--- + Manage.c | 4 ++-- + mdadm.h | 8 ++++++++ + util.c | 4 ++-- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 102c013..3767f01 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -462,7 +462,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname, dv->disposition); + goto abort; + } +- for (; j < 1024 && remaining_disks > 0; j++) { ++ for (; j < MAX_DISKS && remaining_disks > 0; j++) { + unsigned dev; + disc.number = j; + if (ioctl(fd, GET_DISK_INFO, &disc)) +@@ -495,7 +495,7 @@ int Manage_subdevs(char *devname, int fd, + dv->devname, dv->disposition); + goto abort; + } +- for (; j < 1024 && remaining_disks > 0; j++) { ++ for (; j < MAX_DISKS && remaining_disks > 0; j++) { + int sfd; + unsigned dev; + disc.number = j; +diff --git a/mdadm.h b/mdadm.h +index 686d4b4..71cef38 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1388,4 +1388,13 @@ static inline int xasprintf(char **strp, const char *fmt, ...) { + #define PROCESS_DELAYED -2 + #define PROCESS_PENDING -3 + + extern int __offroot; ++ ++/* When using "GET_DISK_INFO" it isn't certain how high ++ * we need to check. So we impose an absolute limit of ++ * MAX_DISKS. This needs to be much more than the largest ++ * number of devices any metadata can support. Currently ++ * v1.x can support 1920 ++ */ ++#define MAX_DISKS 4096 ++ +diff --git a/util.c b/util.c +index b942058..ac0f78c 100644 +--- a/util.c ++++ b/util.c +@@ -378,7 +378,7 @@ int enough_fd(int fd) + array.raid_disks <= 0) + return 0; + avail = calloc(array.raid_disks, 1); +- for (i=0; i < 1024 && array.nr_disks > 0; i++) { ++ for (i=0; i < MAX_DISKS && array.nr_disks > 0; i++) { + disk.number = i; + if (ioctl(fd, GET_DISK_INFO, &disk) != 0) + continue; +@@ -1275,7 +1275,7 @@ void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk) + int d; + + ioctl(mdfd, GET_ARRAY_INFO, ainf); +- for (d = 0 ; d < 1024 ; d++) { ++ for (d = 0 ; d < MAX_DISKS ; d++) { + if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 && + (disk->major || disk->minor)) + return; +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch b/mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch new file mode 100644 index 0000000..58c48bc --- /dev/null +++ b/mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch @@ -0,0 +1,85 @@ +From 0a999759b54f94fd63ac0ee298a549acef6f7d6f Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 18 Apr 2012 14:19:49 +1000 +Subject: [PATCH 1/3] Relax restrictions on when --add is permitted. + +The restriction that --add was not allowed on a device which +looked like a recent member of an array was overly harsh. + +The real requirement was to avoid using --add when the array had +failed, and the device being added might contain necessary +information which can only be incorporated by stopping and +re-assembling with --force. + +So change the test to reflect the need. + +Reported-by: Doug Ledford +Signed-off-by: NeilBrown +--- + Manage.c | 35 ++++++++++++++++++++++++++--------- + 1 files changed, 26 insertions(+), 9 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 3767f01..95aa270 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -448,7 +448,7 @@ int Manage_subdevs(char *devname, int fd, + char *dnprintable = dv->devname; + char *add_dev = dv->devname; + int err; +- int re_add_failed = 0; ++ int array_failed; + + next = dv->next; + jnext = 0; +@@ -851,9 +851,8 @@ int Manage_subdevs(char *devname, int fd, + continue; + goto abort; + } +- skip_re_add: +- re_add_failed = 1; + } ++ skip_re_add: + st->ss->free_super(st); + } + if (add_dev != dv->devname) { +@@ -875,12 +874,30 @@ int Manage_subdevs(char *devname, int fd, + dv->devname, devname); + goto abort; + } +- if (re_add_failed) { +- fprintf(stderr, Name ": %s reports being an active member for %s, but a --re-add fails.\n", +- dv->devname, devname); +- fprintf(stderr, Name ": not performing --add as that would convert %s in to a spare.\n", +- dv->devname); +- fprintf(stderr, Name ": To make this a spare, use \"mdadm --zero-superblock %s\" first.\n", ++ if (array.active_disks < array.raid_disks) { ++ char *avail = calloc(array.raid_disks, 1); ++ int d; ++ int found = 0; ++ ++ for (d = 0; d < MAX_DISKS && found < array.active_disks; d++) { ++ disc.number = d; ++ if (ioctl(fd, GET_DISK_INFO, &disc)) ++ continue; ++ if (disc.major == 0 && disc.minor == 0) ++ continue; ++ if (!(disc.state & (1<devname); + if (tfd >= 0) + close(tfd); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch b/mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch new file mode 100644 index 0000000..1dda32a --- /dev/null +++ b/mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch @@ -0,0 +1,171 @@ +From de5a472ea32867d002558bac0d2d2b4faf45c7c4 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 7 Feb 2012 14:04:47 +1100 +Subject: [PATCH] Remove avail_disks arg from 'enough'. + +It can easily be calculated from 'avail' and 'raid_disks', and we +will soon have a case where we don't have it easily available to pass +in. + +Signed-off-by: NeilBrown +--- + Assemble.c | 16 ++++++++-------- + Detail.c | 4 ++-- + Incremental.c | 2 +- + mdadm.h | 2 +- + util.c | 11 ++++++++--- + 5 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index fd94461..972398e 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -934,7 +934,7 @@ int Assemble(struct supertype *st, char *mddev, + } + continue; + } +- /* If this devices thinks that 'most_recent' has failed, then ++ /* If this device thinks that 'most_recent' has failed, then + * we must reject this device. + */ + if (j != most_recent && +@@ -965,7 +965,7 @@ int Assemble(struct supertype *st, char *mddev, + free(devmap); + while (force && !enough(content->array.level, content->array.raid_disks, + content->array.layout, 1, +- avail, okcnt)) { ++ avail)) { + /* Choose the newest best drive which is + * not up-to-date, update the superblock + * and add it. +@@ -1132,7 +1132,7 @@ int Assemble(struct supertype *st, char *mddev, + if (force && !clean && + !enough(content->array.level, content->array.raid_disks, + content->array.layout, clean, +- avail, okcnt)) { ++ avail)) { + change += st->ss->update_super(st, content, "force-array", + devices[chosen_drive].devname, verbose, + 0, NULL); +@@ -1331,7 +1331,7 @@ int Assemble(struct supertype *st, char *mddev, + if (runstop == 1 || + (runstop <= 0 && + ( enough(content->array.level, content->array.raid_disks, +- content->array.layout, clean, avail, okcnt) && ++ content->array.layout, clean, avail) && + (okcnt + rebuilding_cnt >= req_cnt || start_partial_ok) + ))) { + /* This array is good-to-go. +@@ -1437,13 +1437,13 @@ int Assemble(struct supertype *st, char *mddev, + mddev, strerror(errno)); + + if (!enough(content->array.level, content->array.raid_disks, +- content->array.layout, 1, avail, okcnt)) ++ content->array.layout, 1, avail)) + fprintf(stderr, Name ": Not enough devices to " + "start the array.\n"); + else if (!enough(content->array.level, + content->array.raid_disks, + content->array.layout, clean, +- avail, okcnt)) ++ avail)) + fprintf(stderr, Name ": Not enough devices to " + "start the array while not clean " + "- consider --force.\n"); +@@ -1471,12 +1471,12 @@ int Assemble(struct supertype *st, char *mddev, + if (sparecnt) + fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); + if (!enough(content->array.level, content->array.raid_disks, +- content->array.layout, 1, avail, okcnt)) ++ content->array.layout, 1, avail)) + fprintf(stderr, " - not enough to start the array.\n"); + else if (!enough(content->array.level, + content->array.raid_disks, + content->array.layout, clean, +- avail, okcnt)) ++ avail)) + fprintf(stderr, " - not enough to start the " + "array while not clean - consider " + "--force.\n"); +diff --git a/Detail.c b/Detail.c +index e7d1681..1d7e3a1 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -367,7 +367,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) + if (avail_disks == array.raid_disks) + st = ""; + else if (!enough(array.level, array.raid_disks, +- array.layout, 1, avail, avail_disks)) ++ array.layout, 1, avail)) + st = ", FAILED"; + else + st = ", degraded"; +@@ -580,7 +580,7 @@ This is pretty boring + if (brief) printf("\n"); + if (test && + !enough(array.level, array.raid_disks, array.layout, +- 1, avail, avail_disks)) ++ 1, avail)) + rv = 2; + + free(disks); +diff --git a/Incremental.c b/Incremental.c +index 60175af..b457bf3 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -486,7 +486,7 @@ int Incremental(char *devname, int verbose, int runstop, + active_disks = count_active(st, sra, mdfd, &avail, &info); + if (enough(info.array.level, info.array.raid_disks, + info.array.layout, info.array.state & 1, +- avail, active_disks) == 0) { ++ avail) == 0) { + if (verbose >= 0) + fprintf(stderr, Name + ": %s attached to %s, not enough to start (%d).\n", +diff --git a/mdadm.h b/mdadm.h +index d862b3e..45198bb 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1164,7 +1164,7 @@ extern char *fname_from_uuid(struct supertype *st, + struct mdinfo *info, char *buf, char sep); + extern unsigned long calc_csum(void *super, int bytes); + extern int enough(int level, int raid_disks, int layout, int clean, +- char *avail, int avail_disks); ++ char *avail); + extern int enough_fd(int fd); + extern int ask(char *mesg); + extern unsigned long long get_component_size(int fd); +diff --git a/util.c b/util.c +index 4ba44e6..e5f7a20 100644 +--- a/util.c ++++ b/util.c +@@ -311,10 +311,15 @@ int test_partition_from_id(dev_t id) + return rv; + } + +-int enough(int level, int raid_disks, int layout, int clean, +- char *avail, int avail_disks) ++int enough(int level, int raid_disks, int layout, int clean, char *avail) + { + int copies, first; ++ int i; ++ int avail_disks = 0; ++ ++ for (i = 0; i < raid_disks; i++) ++ avail_disks += !!avail[i]; ++ + switch (level) { + case 10: + /* This is the tricky one - we need to check +@@ -389,7 +394,7 @@ int enough_fd(int fd) + } + /* This is used on an active array, so assume it is clean */ + rv = enough(array.level, array.raid_disks, array.layout, +- 1, avail, avail_disks); ++ 1, avail); + free(avail); + return rv; + } +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-Reset-bad-flag-on-map-update.patch b/mdadm-3.2.3-Reset-bad-flag-on-map-update.patch new file mode 100644 index 0000000..cbbc5a3 --- /dev/null +++ b/mdadm-3.2.3-Reset-bad-flag-on-map-update.patch @@ -0,0 +1,32 @@ +From 52f07f57195229809c7b6d71ca81d2182d303058 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Wed, 7 Mar 2012 12:51:30 +0000 +Subject: [PATCH] Reset bad flag on map update + +Map file may miss an entry if bad flag is not cleared on update. + +This happens for example when an old entry exists in map that +has no mdstat counterpart and we create a new array with the same devnum. +Newly created array will not appear in map if update doesnt clear bad flag. + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + mapfile.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/mapfile.c b/mapfile.c +index 0bfecd0..9e2c893 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -246,6 +246,7 @@ int map_update(struct map_ent **mpp, int devnum, char *metadata, + memcpy(mp->uuid, uuid, 16); + free(mp->path); + mp->path = path ? strdup(path) : NULL; ++ mp->bad = 0; + break; + } + if (!mp) +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch b/mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch new file mode 100644 index 0000000..c10edbe --- /dev/null +++ b/mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch @@ -0,0 +1,52 @@ +From 9126b9a816b1576f58718dbb71bcaff2bfc274e3 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:18:37 +1000 +Subject: [PATCH 6/7] check that no disk over 2TB is used to create container + when no support + +Creation of a container using disks over 2TB should be allowed only when orom supports large disks + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 24 ++++++++++++++++-------- + 1 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 7803a2e..1bc9e9c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5331,14 +5331,22 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + return 0; + } + close(fd); +- if (super->orom && raiddisks > super->orom->tds) { +- if (verbose) +- fprintf(stderr, Name ": %d exceeds maximum number of" +- " platform supported disks: %d\n", +- raiddisks, super->orom->tds); +- +- free_imsm(super); +- return 0; ++ if (super->orom) { ++ if (raiddisks > super->orom->tds) { ++ if (verbose) ++ fprintf(stderr, Name ": %d exceeds maximum number of" ++ " platform supported disks: %d\n", ++ raiddisks, super->orom->tds); ++ free_imsm(super); ++ return 0; ++ } ++ if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 && ++ (ldsize >> 9) >> 32 > 0) { ++ if (verbose) ++ fprintf(stderr, Name ": %s exceeds maximum platform supported size\n", dev); ++ free_imsm(super); ++ return 0; ++ } + } + + *freesize = avail_size_imsm(st, ldsize >> 9); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch b/mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch new file mode 100644 index 0000000..96c46f6 --- /dev/null +++ b/mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch @@ -0,0 +1,69 @@ +From 2cc699afbf0a05baf02d26309eb4ad0e4e81c5d5 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:17:55 +1000 +Subject: [PATCH 5/7] check volume size in validate_geometry_imsm_orom + +When orom does not support volumes over 2TB the creation should be disallowed + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 14 ++++++++++---- + 1 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 0c38b45..7803a2e 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5860,7 +5860,7 @@ static int imsm_default_chunk(const struct imsm_orom *orom) + + static int + validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, +- int raiddisks, int *chunk, int verbose) ++ int raiddisks, int *chunk, unsigned long long size, int verbose) + { + /* check/set platform and metadata limits/defaults */ + if (super->orom && raiddisks > super->orom->dpa) { +@@ -5895,6 +5895,12 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, + layout, level); + return 0; + } ++ ++ if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 && chunk && ++ (calc_array_size(level, raiddisks, layout, *chunk, size) >> 32) > 0) { ++ pr_vrb(": platform does not support a volume size over 2TB\n"); ++ return 0; ++ } + return 1; + } + +@@ -5922,7 +5928,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, + + mpb = super->anchor; + +- if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, verbose)) { ++ if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, size, verbose)) { + fprintf(stderr, Name ": RAID gemetry validation failed. " + "Cannot proceed with the action(s).\n"); + return 0; +@@ -6187,7 +6193,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + if (st->sb) { + struct intel_super *super = st->sb; + if (!validate_geometry_imsm_orom(st->sb, level, layout, +- raiddisks, chunk, ++ raiddisks, chunk, size, + verbose)) + return 0; + /* we are being asked to automatically layout a +@@ -6598,7 +6604,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + get_imsm_raid_level(map), /* RAID level */ + imsm_level_to_layout(get_imsm_raid_level(map)), + map->num_members, /* raid disks */ +- &chunk, ++ &chunk, join_u32(dev->size_low, dev->size_high), + 1 /* verbose */)) { + fprintf(stderr, Name ": IMSM RAID geometry validation" + " failed. Array %s activation is blocked.\n", +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch b/mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch new file mode 100644 index 0000000..eb07579 --- /dev/null +++ b/mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch @@ -0,0 +1,72 @@ +From 97f81ee2635d8c1283ef857bc46d7314acffa1c3 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:15:08 +1000 +Subject: [PATCH 2/7] clear hi bits if not used after loading metadata from + disk + +Functions retrieving sizes from metadata do not need to check +2TB attribute only when we can guarantee the hi bits are always +clear when the MPB_ATTR_2TB_DISK attribute is not set. + +Therefore the following fields are cleared on metadata load +when not in use according to attribute: +struct imsm_disk.total_blocks_hi +struct imsm_map.pba_of_lba0_hi +struct imsm_map.blocks_per_member_hi +struct imsm_map.num_data_stripes_hi + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 28 +++++++++++++++++++++++++++- + 1 files changed, 27 insertions(+), 1 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index c65d39b..480b379 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -3590,6 +3590,32 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) + + static int read_imsm_migr_rec(int fd, struct intel_super *super); + ++/* clears hi bits in metadata if MPB_ATTRIB_2TB_DISK not set */ ++static void clear_hi(struct intel_super *super) ++{ ++ struct imsm_super *mpb = super->anchor; ++ int i, n; ++ if (mpb->attributes & MPB_ATTRIB_2TB_DISK) ++ return; ++ for (i = 0; i < mpb->num_disks; ++i) { ++ struct imsm_disk *disk = &mpb->disk[i]; ++ disk->total_blocks_hi = 0; ++ } ++ for (i = 0; i < mpb->num_raid_devs; ++i) { ++ struct imsm_dev *dev = get_imsm_dev(super, i); ++ if (!dev) ++ return; ++ for (n = 0; n < 2; ++n) { ++ struct imsm_map *map = get_imsm_map(dev, n); ++ if (!map) ++ continue; ++ map->pba_of_lba0_hi = 0; ++ map->blocks_per_member_hi = 0; ++ map->num_data_stripes_hi = 0; ++ } ++ } ++} ++ + static int + load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd) + { +@@ -3602,7 +3628,7 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd + if (err) + return err; + err = parse_raid_devices(super); +- ++ clear_hi(super); + return err; + } + +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch b/mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch new file mode 100644 index 0000000..b67b501 --- /dev/null +++ b/mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch @@ -0,0 +1,34 @@ +From 8453f8d0df0111cfd25e984afb7a64153b04bc27 Mon Sep 17 00:00:00 2001 +From: Lukasz Dorau +Date: Thu, 12 Jan 2012 10:40:00 +1100 +Subject: [PATCH] fix: Monitor sometimes crashes + +The "char cnt [40]" buffer is sometimes too small to hold all message +- in such case monitor crashes. +The buffer must be larger to be able to hold all message. + +Signed-off-by: Lukasz Dorau +Signed-off-by: NeilBrown +--- + Monitor.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 8bc8824..77f22aa 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -563,8 +563,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, + struct mdinfo *sra = + sysfs_read(-1, st->devnum, GET_MISMATCH); + if (sra && sra->mismatch_cnt > 0) { +- char cnt[40]; +- sprintf(cnt, " mismatches found: %d (on raid level %d)", ++ char cnt[80]; ++ snprintf(cnt, sizeof(cnt), ++ " mismatches found: %d (on raid level %d)", + sra->mismatch_cnt, array.level); + alert("RebuildFinished", dev, cnt, ainfo); + } else +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-fix-container-creation-with-incremental-used.patch b/mdadm-3.2.3-fix-container-creation-with-incremental-used.patch new file mode 100644 index 0000000..6a00d99 --- /dev/null +++ b/mdadm-3.2.3-fix-container-creation-with-incremental-used.patch @@ -0,0 +1,34 @@ +From 0c4304ca8b3328132537922fed8ee9e3bbb8a0fa Mon Sep 17 00:00:00 2001 +From: Lukasz Dorau +Date: Thu, 12 Jan 2012 10:57:20 +1100 +Subject: [PATCH] fix: container creation with --incremental used. + +If there is no name provided for a container by the metadata it is +always appropriate to use the metadata version name. create_mddev +will still add a uniquifying digit to the end so there is little risk +of confusion. +This makes the --incremental code behave the same as the --assemble code. + +Signed-off-by: Lukasz Dorau +Signed-off-by: NeilBrown +--- + Incremental.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index 78c9712..60175af 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -259,8 +259,7 @@ int Incremental(char *devname, int verbose, int runstop, + + name_to_use = info.name; + if (name_to_use[0] == 0 && +- info.array.level == LEVEL_CONTAINER && +- trustworthy == LOCAL) { ++ info.array.level == LEVEL_CONTAINER) { + name_to_use = info.text_version; + trustworthy = METADATA; + } +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch b/mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch new file mode 100644 index 0000000..8a469df --- /dev/null +++ b/mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch @@ -0,0 +1,31 @@ +From b51702b82767b726e34d205c9e00a4f61d3044a7 Mon Sep 17 00:00:00 2001 +From: Lukasz Dorau +Date: Fri, 20 Apr 2012 11:00:25 +0200 +Subject: [PATCH 3/3] fix: correct extending size of raid0 array + +Setting "sync_action" to "idle" while extending size of raid0 array +is racy and sometimes fails. +"sync_action" should be set to "frozen" instead. + +Signed-off-by: Lukasz Dorau +Signed-off-by: NeilBrown +--- + Grow.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 389992e..b4b9ff2 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1749,7 +1749,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + /* do not recync non-existing parity, + * we will drop it anyway + */ +- sysfs_set_str(sra, NULL, "sync_action", "idle"); ++ sysfs_set_str(sra, NULL, "sync_action", "frozen"); + /* go back to raid0, drop parity disk + */ + sysfs_set_str(sra, NULL, "level", "raid0"); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch b/mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch new file mode 100644 index 0000000..7658ae7 --- /dev/null +++ b/mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch @@ -0,0 +1,63 @@ +From 13bcac9059b6aef7bf9e828fbdea285cf6adcbd2 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:04 +0200 +Subject: [PATCH 10/14] imsm: Add function imsm_get_free_size() + +Add function imsm_imsm_get_free_size() using part of code from function +reserve_space(). + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 25 ++++++++++++++++++++++++- + 1 files changed, 24 insertions(+), 1 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 49e383f..7cc0ed5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6108,7 +6108,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, + return 1; + } + +-static int reserve_space(struct supertype *st, int raiddisks, ++static int imsm_get_free_size(struct supertype *st, int raiddisks, + unsigned long long size, int chunk, + unsigned long long *freesize) + { +@@ -6186,9 +6186,32 @@ static int reserve_space(struct supertype *st, int raiddisks, + + *freesize = size; + ++ dprintf("imsm: imsm_get_free_size() returns : %llu\n", size); ++ + return 1; + } + ++static int reserve_space(struct supertype *st, int raiddisks, ++ unsigned long long size, int chunk, ++ unsigned long long *freesize) ++{ ++ struct intel_super *super = st->sb; ++ struct dl *dl; ++ int cnt; ++ int rv = 0; ++ ++ rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize); ++ if (rv) { ++ cnt = 0; ++ for (dl = super->disks; dl; dl = dl->next) ++ if (dl->e) ++ dl->raiddisk = cnt++; ++ rv = 1; ++ } ++ ++ return rv; ++} ++ + static int validate_geometry_imsm(struct supertype *st, int level, int layout, + int raiddisks, int *chunk, unsigned long long size, + char *dev, unsigned long long *freesize, +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch b/mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch new file mode 100644 index 0000000..f7b0b08 --- /dev/null +++ b/mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch @@ -0,0 +1,238 @@ +From f3871fdc6841a0505d3a987f4ea1cfb16f6cc201 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:51:57 +0200 +Subject: [PATCH 03/14] imsm: Add new metadata update for volume size + expansion + +Add new meatdata update type imsm_update_size_change, and update metadata +for volume size expansion operation. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 files changed, 124 insertions(+), 8 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 2e6a899..ac8922f 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -419,6 +419,7 @@ enum imsm_update_type { + update_reshape_migration, + update_takeover, + update_general_migration_checkpoint, ++ update_size_change, + }; + + struct imsm_update_activate_spare { +@@ -471,6 +472,12 @@ struct imsm_update_reshape_migration { + int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */ + }; + ++struct imsm_update_size_change { ++ enum imsm_update_type type; ++ int subdev; ++ long long new_size; ++}; ++ + struct imsm_update_general_migration_checkpoint { + enum imsm_update_type type; + __u32 curr_migr_unit; +@@ -6974,7 +6981,8 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev) + super->updates_pending++; + } + +-static unsigned long long imsm_set_array_size(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; +@@ -6993,8 +7001,17 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev) + + /* set array size in metadata + */ +- map = get_imsm_map(dev, MAP_0); +- array_blocks = blocks_per_member(map) * used_disks; ++ 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 { ++ /* Online Volume Size Change ++ * Using available free space ++ */ ++ array_blocks = new_size; ++ } + + /* round array size down to closest MB + */ +@@ -7051,7 +7068,7 @@ static void imsm_progress_container_reshape(struct intel_super *super) + memcpy(map2, map, copy_map_size); + map2->num_members = prev_num_members; + +- imsm_set_array_size(dev); ++ imsm_set_array_size(dev, -1); + super->clean_migration_record_by_mdmon = 1; + super->updates_pending++; + } +@@ -7941,7 +7958,7 @@ skip_disk_add: + *tofree = *space_list; + /* calculate new size + */ +- imsm_set_array_size(new_dev); ++ imsm_set_array_size(new_dev, -1); + + ret_val = 1; + } +@@ -7956,6 +7973,44 @@ error_disk_add: + return ret_val; + } + ++static int apply_size_change_update(struct imsm_update_size_change *u, ++ struct intel_super *super) ++{ ++ struct intel_dev *id; ++ int ret_val = 0; ++ ++ dprintf("apply_size_change_update()\n"); ++ if ((u->subdev < 0) || ++ (u->subdev > 1)) { ++ dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev); ++ return ret_val; ++ } ++ ++ for (id = super->devlist ; id; id = id->next) { ++ 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); ++ unsigned long long blocks_per_member; ++ ++ /* calculate new size ++ */ ++ blocks_per_member = u->new_size / used_disks; ++ dprintf("imsm: apply_size_change_update(size: %llu, " ++ "blocks per member: %llu)\n", ++ u->new_size, blocks_per_member); ++ set_blocks_per_member(map, blocks_per_member); ++ imsm_set_array_size(dev, u->new_size); ++ ++ ret_val = 1; ++ break; ++ } ++ } ++ ++ return ret_val; ++} ++ ++ + static int apply_update_activate_spare(struct imsm_update_activate_spare *u, + struct intel_super *super, + struct active_array *active_array) +@@ -8155,7 +8210,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u, + newmap = get_imsm_map(newdev, MAP_1); + memcpy(newmap, oldmap, sizeof_imsm_map(oldmap)); + +- imsm_set_array_size(newdev); ++ imsm_set_array_size(newdev, -1); + } + + sp = (void **)id->dev; +@@ -8363,6 +8418,12 @@ static void imsm_process_update(struct supertype *st, + super->updates_pending++; + break; + } ++ case update_size_change: { ++ struct imsm_update_size_change *u = (void *)update->buf; ++ if (apply_size_change_update(u, super)) ++ super->updates_pending++; ++ break; ++ } + case update_activate_spare: { + struct imsm_update_activate_spare *u = (void *) update->buf; + if (apply_update_activate_spare(u, super, st->arrays)) +@@ -8757,6 +8818,9 @@ static void imsm_prepare_update(struct supertype *st, + dprintf("New anchor length is %llu\n", (unsigned long long)len); + break; + } ++ case update_size_change: { ++ break; ++ } + case update_create_array: { + struct imsm_update_create_array *u = (void *) update->buf; + struct intel_dev *dv; +@@ -9614,6 +9678,43 @@ abort: + return 0; + } + ++ ++/****************************************************************************** ++ * function: imsm_create_metadata_update_for_size_change() ++ * Creates update for IMSM array for array size change. ++ * ++ ******************************************************************************/ ++static int imsm_create_metadata_update_for_size_change( ++ struct supertype *st, ++ struct geo_params *geo, ++ struct imsm_update_size_change **updatep) ++{ ++ struct intel_super *super = st->sb; ++ int update_memory_size = 0; ++ struct imsm_update_size_change *u = NULL; ++ ++ dprintf("imsm_create_metadata_update_for_size_change(enter)" ++ " New size = %llu\n", geo->size); ++ ++ /* size of all update data without anchor */ ++ update_memory_size = sizeof(struct imsm_update_size_change); ++ ++ u = calloc(1, update_memory_size); ++ if (u == NULL) { ++ dprintf("error: cannot get memory for " ++ "imsm_create_metadata_update_for_size_change\n"); ++ return 0; ++ } ++ u->type = update_size_change; ++ u->subdev = super->current_vol; ++ u->new_size = geo->size; ++ ++ dprintf("imsm: reshape update preparation : OK\n"); ++ *updatep = u; ++ ++ return update_memory_size; ++} ++ + /****************************************************************************** + * function: imsm_create_metadata_update_for_migration() + * Creates update for IMSM array. +@@ -10023,8 +10124,23 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, + } + break; + case CH_ARRAY_SIZE: { +- /* ToDo: Prepare metadata update here +- */ ++ struct imsm_update_size_change *u = NULL; ++ int len = ++ imsm_create_metadata_update_for_size_change( ++ st, &geo, &u); ++ if (len < 1) { ++ dprintf("imsm: " ++ "Cannot prepare update\n"); ++ break; ++ } ++ ret_val = 0; ++ /* update metadata locally */ ++ imsm_update_metadata_locally(st, u, len); ++ /* and possibly remotely */ ++ if (st->update_tail) ++ append_metadata_update(st, u, len); ++ else ++ free(u); + } + break; + default: +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch b/mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch new file mode 100644 index 0000000..ee91683 --- /dev/null +++ b/mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch @@ -0,0 +1,129 @@ +From 54397ed97af065b1e3a12d6beab09bc05a07a9d0 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:51:58 +0200 +Subject: [PATCH 04/14] imsm: Execute size change for external metatdata + +For external metatdata ioctl doesn't set new size. Set new size using sysfs. +Put code for size change in to function to re-use the same code as during +On-line Capacity Expansion + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + Grow.c | 78 ++++++++++++++++++++++++++++++++++++++------------------------- + 1 files changed, 47 insertions(+), 31 deletions(-) + +diff --git a/Grow.c b/Grow.c +index e3ef8d4..5fd44aa 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1386,6 +1386,44 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) + return NULL; + } + ++static int set_array_size(struct supertype *st, struct mdinfo *sra, ++ char *text_version) ++{ ++ struct mdinfo *info; ++ char *subarray; ++ int ret_val = -1; ++ ++ if ((st == NULL) || (sra == NULL)) ++ return ret_val; ++ ++ if (text_version == NULL) ++ text_version = sra->text_version; ++ subarray = strchr(text_version+1, '/')+1; ++ info = st->ss->container_content(st, subarray); ++ if (info) { ++ unsigned long long current_size = 0; ++ unsigned long long new_size = ++ info->custom_array_size/2; ++ ++ if (sysfs_get_ll(sra, NULL, "array_size", ¤t_size) == 0 && ++ new_size > current_size) { ++ if (sysfs_set_num(sra, NULL, "array_size", new_size) ++ < 0) ++ dprintf("Error: Cannot set array size"); ++ else { ++ ret_val = 0; ++ dprintf("Array size changed"); ++ } ++ dprintf(" from %llu to %llu.\n", ++ current_size, new_size); ++ } ++ sysfs_free(info); ++ } else ++ dprintf("Error: set_array_size(): info pointer in NULL\n"); ++ ++ return ret_val; ++} ++ + static int reshape_array(char *container, int fd, char *devname, + struct supertype *st, struct mdinfo *info, + int force, struct mddev_dev *devlist, +@@ -1636,7 +1674,6 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + "2TB per device\n"); + size = min_csize; + } +- + array.size = size; + if (array.size != size) { + /* got truncated to 32bit, write to +@@ -1647,8 +1684,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, + "component_size", size); + else + rv = -1; +- } else ++ } else { + rv = ioctl(fd, SET_ARRAY_INFO, &array); ++ /* manage array size when it is managed externally ++ */ ++ if ((rv == 0) && st->ss->external) ++ rv = set_array_size(st, sra, sra->text_version); ++ } ++ + if (rv != 0) { + int err = errno; + +@@ -2507,35 +2550,8 @@ started: + */ + if (reshape.before.data_disks != + reshape.after.data_disks && +- info->custom_array_size) { +- struct mdinfo *info2; +- char *subarray = strchr(info->text_version+1, '/')+1; +- +- info2 = st->ss->container_content(st, subarray); +- if (info2) { +- unsigned long long current_size = 0; +- unsigned long long new_size = +- info2->custom_array_size/2; +- +- if (sysfs_get_ll(sra, +- NULL, +- "array_size", +- ¤t_size) == 0 && +- new_size > current_size) { +- if (sysfs_set_num(sra, NULL, +- "array_size", new_size) +- < 0) +- dprintf("Error: Cannot" +- " set array size"); +- else +- dprintf("Array size " +- "changed"); +- dprintf(" from %llu to %llu.\n", +- current_size, new_size); +- } +- sysfs_free(info2); +- } +- } ++ info->custom_array_size) ++ set_array_size(st, info, info->text_version); + + if (info->new_level != reshape.level) { + +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch b/mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch new file mode 100644 index 0000000..df20e39 --- /dev/null +++ b/mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch @@ -0,0 +1,103 @@ +From 7abc98717c32d08a2aab366e79c12a91573fb538 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:51:56 +0200 +Subject: [PATCH 02/14] imsm: FIX: Add volume size expand support to + imsm_analyze_change() + +Patch adds ability to function imsm_analyze_change() for: +1. Detect size change request for volume operation. +2. Check and correct size for change. +3. Set new change kind to CH_ARRAY_SIZE + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 51 insertions(+), 0 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 5f86539..2e6a899 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -405,6 +405,7 @@ struct extent { + enum imsm_reshape_type { + CH_TAKEOVER, + CH_MIGRATION, ++ CH_ARRAY_SIZE, + }; + + /* definition of messages passed to imsm_process_update */ +@@ -9726,6 +9727,10 @@ 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 intel_super *super; ++ long long current_size; + + getinfo_super_imsm_volume(st, &info, NULL); + if ((geo->level != info.array.level) && +@@ -9807,6 +9812,47 @@ 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); ++ data_disks = imsm_num_data_members(dev , MAP_0); ++ /* compute current size in K per disk member ++ */ ++ current_size = info.custom_array_size / 2 / data_disks; ++ ++ if ((current_size != geo->size) && (geo->size > 0)) { ++ if (change != -1) { ++ fprintf(stderr, ++ Name " 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) { ++ fprintf(stderr, ++ Name " Error. The last volume in container " ++ "can be expanded only (%i/%i).\n", ++ super->current_vol, st->devnum); ++ goto analyse_change_exit; ++ } ++ geo->size *= 2; ++ /* 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) { ++ fprintf(stderr, ++ Name " Error. Size expanssion is supported only" ++ " (current size is %llu, requested size " ++ "/rounded/ is %llu).\n", ++ current_size, geo->size); ++ goto analyse_change_exit; ++ } ++ geo->size *= data_disks; ++ geo->raid_disks = dev->vol.map->num_members; ++ change = CH_ARRAY_SIZE; ++ } + if (!validate_geometry_imsm(st, + geo->level, + imsm_layout, +@@ -9976,6 +10022,11 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, + free(u); + } + break; ++ case CH_ARRAY_SIZE: { ++ /* ToDo: Prepare metadata update here ++ */ ++ } ++ break; + default: + ret_val = 1; + } +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch b/mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch new file mode 100644 index 0000000..b6ed8ce --- /dev/null +++ b/mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch @@ -0,0 +1,126 @@ +From c41e00b2e68aed0ab9d41f70a3e119d86a92cf29 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:06 +0200 +Subject: [PATCH 12/14] imsm: FIX: Component size alignment check + +Put currently existing code for alignment correction in to function +imsm_component_size_aligment_check() and use it for align component size +to chunk size during volume size expansion operation. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 68 ++++++++++++++++++++++++++++++++++++++++---------------- + 1 files changed, 48 insertions(+), 20 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 1f47234..9685726 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2454,6 +2454,32 @@ int imsm_reshape_blocks_arrays_changes(struct intel_super *super) + } + return rv; + } ++static unsigned long long imsm_component_size_aligment_check(int level, ++ int chunk_size, ++ unsigned long long component_size) ++{ ++ unsigned int component_size_alligment; ++ ++ /* check component size aligment ++ */ ++ component_size_alligment = component_size % (chunk_size/512); ++ ++ dprintf("imsm_component_size_aligment_check(Level: %i, " ++ "chunk_size = %i, component_size = %llu), " ++ "component_size_alligment = %u\n", ++ level, chunk_size, component_size, ++ component_size_alligment); ++ ++ if (component_size_alligment && (level != 1) && (level != UnSet)) { ++ dprintf("imsm: reported component size alligned from %llu ", ++ component_size); ++ component_size -= component_size_alligment; ++ dprintf("to %llu (%i).\n", ++ component_size, component_size_alligment); ++ } ++ ++ return component_size; ++} + + static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap) + { +@@ -2465,7 +2491,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + struct imsm_map *map_to_analyse = map; + struct dl *dl; + char *devname; +- unsigned int component_size_alligment; + int map_disks = info->array.raid_disks; + + memset(info, 0, sizeof(*info)); +@@ -2548,19 +2573,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + info->data_offset = pba_of_lba0(map_to_analyse); + info->component_size = blocks_per_member(map_to_analyse); + +- /* check component size aligment +- */ +- component_size_alligment = +- info->component_size % (info->array.chunk_size/512); +- +- if (component_size_alligment && +- (info->array.level != 1) && (info->array.level != UnSet)) { +- dprintf("imsm: reported component size alligned from %llu ", +- info->component_size); +- info->component_size -= component_size_alligment; +- dprintf("to %llu (%i).\n", +- info->component_size, component_size_alligment); +- } ++ info->component_size = imsm_component_size_aligment_check( ++ info->array.level, ++ info->array.chunk_size, ++ info->component_size); + + memset(info->uuid, 0, sizeof(info->uuid)); + info->recovery_start = MaxSector; +@@ -9949,9 +9965,18 @@ 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); +- /* compute current size in K per disk member ++ /* compute current size per disk member + */ +- current_size = info.custom_array_size / 2 / data_disks; ++ current_size = info.custom_array_size / data_disks; ++ ++ if (geo->size > 0) { ++ /* align component size ++ */ ++ geo->size = imsm_component_size_aligment_check( ++ get_imsm_raid_level(dev->vol.map), ++ chunk * 1024, ++ geo->size * 2); ++ } + + if ((current_size != geo->size) && (geo->size >= 0)) { + if (change != -1) { +@@ -9984,10 +10009,13 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + } + geo->size = freesize + current_size; + +- /* round to chunk size */ +- geo->size &= ~(chunk-1); +- } else +- geo->size *= 2; ++ /* align component size ++ */ ++ geo->size = imsm_component_size_aligment_check( ++ get_imsm_raid_level(dev->vol.map), ++ chunk * 1024, ++ geo->size); ++ } + + if ((direction == ROLLBACK_METADATA_CHANGES)) { + /* accept size for rollback only +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch b/mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch new file mode 100644 index 0000000..412105d --- /dev/null +++ b/mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch @@ -0,0 +1,130 @@ +From fbf3d20214537e5e4bf6fb04f191418a58e88463 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:00 +0200 +Subject: [PATCH 06/14] imsm: FIX: Support metadata changes rollback + +Add metadata rollback specific code for imsm. +Let reshape_super() ability to differentiate metadata apply and rollback +actions. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 56 ++++++++++++++++++++++++++++++++++++++------------------ + 1 files changed, 38 insertions(+), 18 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 32a53d1..49e383f 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -9470,7 +9470,8 @@ static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor + + static int imsm_reshape_is_allowed_on_container(struct supertype *st, + struct geo_params *geo, +- int *old_raid_disks) ++ int *old_raid_disks, ++ int direction) + { + /* currently we only support increasing the number of devices + * for a container. This increases the number of device for each +@@ -9494,6 +9495,12 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, + return ret_val; + } + ++ if (direction == ROLLBACK_METADATA_CHANGES) { ++ dprintf("imsm: Metadata changes rollback is not supported for " ++ "container operation.\n"); ++ return ret_val; ++ } ++ + info = container_content_imsm(st, NULL); + for (member = info; member; member = member->next) { + int result; +@@ -9814,11 +9821,13 @@ static void imsm_update_metadata_locally(struct supertype *st, + * Function: imsm_analyze_change + * Description: Function analyze change for single volume + * and validate if transition is supported +-* Parameters: Geometry parameters, supertype structure ++* Parameters: Geometry parameters, supertype structure, ++* metadata change direction (apply/rollback) + * Returns: Operation type code on success, -1 if fail + ****************************************************************************/ + enum imsm_reshape_type imsm_analyze_change(struct supertype *st, +- struct geo_params *geo) ++ struct geo_params *geo, ++ int direction) + { + struct mdinfo info; + int change = -1; +@@ -9937,18 +9946,24 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + goto analyse_change_exit; + } + geo->size *= 2; +- /* 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) { +- fprintf(stderr, +- Name " Error. Size expanssion is supported only" +- " (current size is %llu, requested size " +- "/rounded/ is %llu).\n", +- current_size, geo->size); +- goto analyse_change_exit; ++ 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) { ++ fprintf(stderr, ++ Name " Error. Size expanssion is " ++ "supported only (current size is %llu, " ++ "requested size /rounded/ is %llu).\n", ++ current_size, geo->size); ++ goto analyse_change_exit; ++ } + } + geo->size *= data_disks; + geo->raid_disks = dev->vol.map->num_members; +@@ -9978,7 +9993,12 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + } + + analyse_change_exit: +- ++ if ((direction == ROLLBACK_METADATA_CHANGES) && ++ ((change == CH_MIGRATION) || (change == CH_TAKEOVER))) { ++ dprintf("imsm: Metadata changes rollback is not supported for " ++ "migration and takeover operations.\n"); ++ change = -1; ++ } + return change; + } + +@@ -10049,7 +10069,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, + int old_raid_disks = 0; + + if (imsm_reshape_is_allowed_on_container( +- st, &geo, &old_raid_disks)) { ++ st, &geo, &old_raid_disks, direction)) { + struct imsm_update_reshape *u = NULL; + int len; + +@@ -10098,7 +10118,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, + goto exit_imsm_reshape_super; + } + super->current_vol = dev->index; +- change = imsm_analyze_change(st, &geo); ++ change = imsm_analyze_change(st, &geo, direction); + switch (change) { + case CH_TAKEOVER: + ret_val = imsm_takeover(st, &geo); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch b/mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch new file mode 100644 index 0000000..9269851 --- /dev/null +++ b/mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch @@ -0,0 +1,36 @@ +From 36fd8ccc0e755042e3983a2bd02523461b5f8307 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:51:55 +0200 +Subject: [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for + Raid1/10 + +Function imsm_num_data_members() returns wrong value for raid 1 and 10. +It returns all data member but it should return number of unique data +members (excluding mirror devices) + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 088e6bc..5f86539 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2032,9 +2032,11 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map) + + switch (get_imsm_raid_level(map)) { + case 0: ++ return map->num_members; ++ break; + case 1: + case 10: +- return map->num_members; ++ return map->num_members/2; + case 5: + return map->num_members - 1; + default: +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch b/mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch new file mode 100644 index 0000000..53f8cc9 --- /dev/null +++ b/mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch @@ -0,0 +1,60 @@ +From b130333f39734eed08d38d6c36025fa4d618bc52 Mon Sep 17 00:00:00 2001 +From: Adam Kwolek +Date: Fri, 13 Apr 2012 16:52:05 +0200 +Subject: [PATCH 11/14] imsm: Support setting max size for size change + operation + +Add support for setting max size for size change operation using +imsm_get_free_size() function for computing maximum available space. + +Signed-off-by: Adam Kwolek +Signed-off-by: NeilBrown +--- + super-intel.c | 24 ++++++++++++++++++++++-- + 1 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 7cc0ed5..1f47234 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -9953,7 +9953,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + */ + current_size = info.custom_array_size / 2 / data_disks; + +- if ((current_size != geo->size) && (geo->size > 0)) { ++ if ((current_size != geo->size) && (geo->size >= 0)) { + if (change != -1) { + fprintf(stderr, + Name " Error. Size change should be the only " +@@ -9968,7 +9968,27 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + super->current_vol, st->devnum); + goto analyse_change_exit; + } +- geo->size *= 2; ++ if (geo->size == 0) { ++ /* requested size change to the maximum available size ++ */ ++ unsigned long long freesize; ++ int rv; ++ ++ rv = imsm_get_free_size(st, dev->vol.map->num_members, ++ 0, chunk, &freesize); ++ if (rv == 0) { ++ fprintf(stderr, Name " Error. Cannot find " ++ "maximum available space.\n"); ++ change = -1; ++ goto analyse_change_exit; ++ } ++ geo->size = freesize + current_size; ++ ++ /* round to chunk size */ ++ geo->size &= ~(chunk-1); ++ } else ++ geo->size *= 2; ++ + if ((direction == ROLLBACK_METADATA_CHANGES)) { + /* accept size for rollback only + */ +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch b/mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch new file mode 100644 index 0000000..7908028 --- /dev/null +++ b/mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch @@ -0,0 +1,484 @@ +From 5551b113dc18a6275fb04c7e7e3b76c656926e0a Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:15:03 +1000 +Subject: [PATCH 1/7] imsm: avoid overflows for disks over 1TB + +Calculating array_blocks using info->size causes error on activation of +volume using disks over 1 TB. unsigned long long size parameter +is used instead. + +total_blocks, pba_of_lba0, blocks_per_member and num_data_stripes overflow +when using disks over 2TB. + +Part of fillers in metadata is used to contain hi bits of the numbers +that are likely to go over 32 bit limit. +Functions are added to get and set such fields as the hi bits are not +adjacent with low bits in the structures. + +Acked-by: Dan Williams +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 198 +++++++++++++++++++++++++++++++++++++------------------- + 1 files changed, 131 insertions(+), 67 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index a351b60..c65d39b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -95,15 +95,16 @@ + #define IMSM_MAX_DEVICES 255 + struct imsm_disk { + __u8 serial[MAX_RAID_SERIAL_LEN];/* 0xD8 - 0xE7 ascii serial number */ +- __u32 total_blocks; /* 0xE8 - 0xEB total blocks */ ++ __u32 total_blocks_lo; /* 0xE8 - 0xEB total blocks lo */ + __u32 scsi_id; /* 0xEC - 0xEF scsi ID */ + #define SPARE_DISK __cpu_to_le32(0x01) /* Spare */ + #define CONFIGURED_DISK __cpu_to_le32(0x02) /* Member of some RaidDev */ + #define FAILED_DISK __cpu_to_le32(0x04) /* Permanent failure */ + __u32 status; /* 0xF0 - 0xF3 */ + __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ +-#define IMSM_DISK_FILLERS 4 +- __u32 filler[IMSM_DISK_FILLERS]; /* 0xF4 - 0x107 MPB_DISK_FILLERS for future expansion */ ++ __u32 total_blocks_hi; /* 0xF4 - 0xF5 total blocks hi */ ++#define IMSM_DISK_FILLERS 3 ++ __u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */ + }; + + /* map selector for map managment +@@ -114,9 +115,9 @@ struct imsm_disk { + + /* RAID map configuration infos. */ + struct imsm_map { +- __u32 pba_of_lba0; /* start address of partition */ +- __u32 blocks_per_member;/* blocks per member */ +- __u32 num_data_stripes; /* number of data stripes */ ++ __u32 pba_of_lba0_lo; /* start address of partition */ ++ __u32 blocks_per_member_lo;/* blocks per member */ ++ __u32 num_data_stripes_lo; /* number of data stripes */ + __u16 blocks_per_strip; + __u8 map_state; /* Normal, Uninitialized, Degraded, Failed */ + #define IMSM_T_STATE_NORMAL 0 +@@ -131,7 +132,10 @@ struct imsm_map { + __u8 num_domains; /* number of parity domains */ + __u8 failed_disk_num; /* valid only when state is degraded */ + __u8 ddf; +- __u32 filler[7]; /* expansion area */ ++ __u32 pba_of_lba0_hi; ++ __u32 blocks_per_member_hi; ++ __u32 num_data_stripes_hi; ++ __u32 filler[4]; /* expansion area */ + #define IMSM_ORD_REBUILD (1 << 24) + __u32 disk_ord_tbl[1]; /* disk_ord_tbl[num_members], + * top byte contains some flags +@@ -361,7 +365,7 @@ struct intel_super { + size_t next_len; + int updates_pending; /* count of pending updates for mdmon */ + int current_vol; /* index of raid device undergoing creation */ +- __u32 create_offset; /* common start for 'current_vol' */ ++ unsigned long long create_offset; /* common start for 'current_vol' */ + __u32 random; /* random data for seeding new family numbers */ + struct intel_dev *devlist; + struct dl { +@@ -870,6 +874,69 @@ static int count_memberships(struct dl *dl, struct intel_super *super) + + static __u32 imsm_min_reserved_sectors(struct intel_super *super); + ++static int split_ull(unsigned long long n, __u32 *lo, __u32 *hi) ++{ ++ if (lo == 0 || hi == 0) ++ return 1; ++ *lo = __le32_to_cpu((unsigned)n); ++ *hi = __le32_to_cpu((unsigned)(n >> 32)); ++ return 0; ++} ++ ++static unsigned long long join_u32(__u32 lo, __u32 hi) ++{ ++ return (unsigned long long)__le32_to_cpu(lo) | ++ (((unsigned long long)__le32_to_cpu(hi)) << 32); ++} ++ ++static unsigned long long total_blocks(struct imsm_disk *disk) ++{ ++ if (disk == NULL) ++ return 0; ++ return join_u32(disk->total_blocks_lo, disk->total_blocks_hi); ++} ++ ++static unsigned long long pba_of_lba0(struct imsm_map *map) ++{ ++ if (map == NULL) ++ return 0; ++ return join_u32(map->pba_of_lba0_lo, map->pba_of_lba0_hi); ++} ++ ++static unsigned long long blocks_per_member(struct imsm_map *map) ++{ ++ if (map == NULL) ++ return 0; ++ return join_u32(map->blocks_per_member_lo, map->blocks_per_member_hi); ++} ++ ++static unsigned long long num_data_stripes(struct imsm_map *map) ++{ ++ if (map == NULL) ++ return 0; ++ return join_u32(map->num_data_stripes_lo, map->num_data_stripes_hi); ++} ++ ++static void set_total_blocks(struct imsm_disk *disk, unsigned long long n) ++{ ++ split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi); ++} ++ ++static void set_pba_of_lba0(struct imsm_map *map, unsigned long long n) ++{ ++ split_ull(n, &map->pba_of_lba0_lo, &map->pba_of_lba0_hi); ++} ++ ++static void set_blocks_per_member(struct imsm_map *map, unsigned long long n) ++{ ++ split_ull(n, &map->blocks_per_member_lo, &map->blocks_per_member_hi); ++} ++ ++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 struct extent *get_extents(struct intel_super *super, struct dl *dl) + { + /* find a list of used extents on the given physical device */ +@@ -897,8 +964,8 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl) + struct imsm_map *map = get_imsm_map(dev, MAP_0); + + if (get_imsm_disk_slot(map, dl->index) >= 0) { +- e->start = __le32_to_cpu(map->pba_of_lba0); +- e->size = __le32_to_cpu(map->blocks_per_member); ++ e->start = pba_of_lba0(map); ++ e->size = blocks_per_member(map); + e++; + } + } +@@ -911,10 +978,9 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl) + */ + if (memberships) { + struct extent *last = &rv[memberships - 1]; +- __u32 remainder; ++ unsigned long long remainder; + +- remainder = __le32_to_cpu(dl->disk.total_blocks) - +- (last->start + last->size); ++ remainder = total_blocks(&dl->disk) - (last->start + last->size); + /* round down to 1k block to satisfy precision of the kernel + * 'size' interface + */ +@@ -925,7 +991,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl) + if (reservation > remainder) + reservation = remainder; + } +- e->start = __le32_to_cpu(dl->disk.total_blocks) - reservation; ++ e->start = total_blocks(&dl->disk) - reservation; + e->size = 0; + return rv; + } +@@ -954,7 +1020,7 @@ static __u32 imsm_reserved_sectors(struct intel_super *super, struct dl *dl) + for (i = 0; e[i].size; i++) + continue; + +- rv = __le32_to_cpu(dl->disk.total_blocks) - e[i].start; ++ rv = total_blocks(&dl->disk) - e[i].start; + + free(e); + +@@ -984,7 +1050,8 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super) + { + struct extent *e; + int i; +- __u32 min_active, remainder; ++ unsigned long long min_active; ++ __u32 remainder; + __u32 rv = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS; + struct dl *dl, *dl_min = NULL; + +@@ -995,9 +1062,10 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super) + for (dl = super->disks; dl; dl = dl->next) { + if (dl->index < 0) + continue; +- if (dl->disk.total_blocks < min_active || min_active == 0) { ++ unsigned long long blocks = total_blocks(&dl->disk); ++ if (blocks < min_active || min_active == 0) { + dl_min = dl; +- min_active = dl->disk.total_blocks; ++ min_active = blocks; + } + } + if (!dl_min) +@@ -1115,13 +1183,13 @@ static void print_imsm_dev(struct intel_super *super, + sz += __le32_to_cpu(dev->size_low); + printf(" Array Size : %llu%s\n", (unsigned long long)sz, + human_size(sz * 512)); +- sz = __le32_to_cpu(map->blocks_per_member); ++ sz = blocks_per_member(map); + printf(" Per Dev Size : %llu%s\n", (unsigned long long)sz, + human_size(sz * 512)); +- printf(" Sector Offset : %u\n", +- __le32_to_cpu(map->pba_of_lba0)); +- printf(" Num Stripes : %u\n", +- __le32_to_cpu(map->num_data_stripes)); ++ printf(" Sector Offset : %llu\n", ++ pba_of_lba0(map)); ++ printf(" Num Stripes : %llu\n", ++ num_data_stripes(map)); + printf(" Chunk Size : %u KiB", + __le16_to_cpu(map->blocks_per_strip) / 2); + if (map2) +@@ -1182,7 +1250,7 @@ static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved) + is_configured(disk) ? " active" : "", + is_failed(disk) ? " failed" : ""); + printf(" Id : %08x\n", __le32_to_cpu(disk->scsi_id)); +- sz = __le32_to_cpu(disk->total_blocks) - reserved; ++ sz = total_blocks(disk) - reserved; + printf(" Usable Size : %llu%s\n", (unsigned long long)sz, + human_size(sz * 512)); + } +@@ -2462,9 +2530,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + dl->index); + } + +- info->data_offset = __le32_to_cpu(map_to_analyse->pba_of_lba0); +- info->component_size = +- __le32_to_cpu(map_to_analyse->blocks_per_member); ++ info->data_offset = pba_of_lba0(map_to_analyse); ++ info->component_size = blocks_per_member(map_to_analyse); + + /* check component size aligment + */ +@@ -2525,7 +2592,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + + used_disks = imsm_num_data_members(dev, MAP_1); + if (used_disks > 0) { +- array_blocks = map->blocks_per_member * ++ array_blocks = blocks_per_member(map) * + used_disks; + /* round array size down to closest MB + */ +@@ -2709,7 +2776,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * + __u32 reserved = imsm_reserved_sectors(super, super->disks); + + disk = &super->disks->disk; +- info->data_offset = __le32_to_cpu(disk->total_blocks) - reserved; ++ info->data_offset = total_blocks(&super->disks->disk) - reserved; + info->component_size = reserved; + info->disk.state = is_configured(disk) ? (1 << MD_DISK_ACTIVE) : 0; + /* we don't change info->disk.raid_disk here because +@@ -3377,7 +3444,7 @@ int check_mpb_migr_compatibility(struct intel_super *super) + /* This device is migrating */ + map0 = get_imsm_map(dev_iter, MAP_0); + map1 = get_imsm_map(dev_iter, MAP_1); +- if (map0->pba_of_lba0 != map1->pba_of_lba0) ++ if (pba_of_lba0(map0) != pba_of_lba0(map1)) + /* migration optimization area was used */ + return -1; + if (migr_rec->ascending_migr == 0 +@@ -3626,7 +3693,7 @@ static struct intel_super *alloc_super(void) + if (super) { + memset(super, 0, sizeof(*super)); + super->current_vol = -1; +- super->create_offset = ~((__u32 ) 0); ++ super->create_offset = ~((unsigned long long) 0); + } + return super; + } +@@ -4346,22 +4413,13 @@ static __u16 info_to_blocks_per_strip(mdu_array_info_t *info) + return info->chunk_size >> 9; + } + +-static __u32 info_to_num_data_stripes(mdu_array_info_t *info, int num_domains) +-{ +- __u32 num_stripes; +- +- num_stripes = (info->size * 2) / info_to_blocks_per_strip(info); +- num_stripes /= num_domains; +- +- return num_stripes; +-} +- +-static __u32 info_to_blocks_per_member(mdu_array_info_t *info) ++static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info, ++ unsigned long long size) + { + if (info->level == 1) +- return info->size * 2; ++ return size * 2; + else +- return (info->size * 2) & ~(info_to_blocks_per_strip(info) - 1); ++ return (size * 2) & ~(info_to_blocks_per_strip(info) - 1); + } + + static void imsm_update_version_info(struct intel_super *super) +@@ -4452,7 +4510,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + int i; + unsigned long long array_blocks; + size_t size_old, size_new; +- __u32 num_data_stripes; ++ unsigned long long num_data_stripes; + + if (super->orom && mpb->num_raid_devs >= super->orom->vpa) { + fprintf(stderr, Name": This imsm-container already has the " +@@ -4540,11 +4598,11 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + + strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN); + if (info->level == 1) +- array_blocks = info_to_blocks_per_member(info); ++ array_blocks = info_to_blocks_per_member(info, size); + else + array_blocks = calc_array_size(info->level, info->raid_disks, + info->layout, info->chunk_size, +- info->size*2); ++ size * 2); + /* round array size down to closest MB */ + array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT; + +@@ -4557,8 +4615,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + vol->dirty = !info->state; + vol->curr_migr_unit = 0; + map = get_imsm_map(dev, MAP_0); +- map->pba_of_lba0 = __cpu_to_le32(super->create_offset); +- map->blocks_per_member = __cpu_to_le32(info_to_blocks_per_member(info)); ++ set_pba_of_lba0(map, super->create_offset); ++ set_blocks_per_member(map, info_to_blocks_per_member(info, size)); + map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); + map->failed_disk_num = ~0; + if (info->level > 0) +@@ -4585,8 +4643,10 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + else + map->num_domains = 1; + +- num_data_stripes = info_to_num_data_stripes(info, map->num_domains); +- map->num_data_stripes = __cpu_to_le32(num_data_stripes); ++ /* info->size is only int so use the 'size' parameter instead */ ++ num_data_stripes = (size * 2) / info_to_blocks_per_strip(info); ++ num_data_stripes /= map->num_domains; ++ set_num_data_stripes(map, num_data_stripes); + + map->num_members = info->raid_disks; + for (i = 0; i < map->num_members; i++) { +@@ -4729,8 +4789,8 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + */ + if (super->current_vol == 0) { + for (df = super->missing; df; df = df->next) { +- if (dl->disk.total_blocks > df->disk.total_blocks) +- df->disk.total_blocks = dl->disk.total_blocks; ++ if (total_blocks(&dl->disk) > total_blocks(&df->disk)) ++ set_total_blocks(&df->disk, total_blocks(&dl->disk)); + _disk = __get_imsm_disk(mpb, df->index); + *_disk = df->disk; + } +@@ -4869,7 +4929,11 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + get_dev_size(fd, NULL, &size); + size /= 512; + serialcpy(dd->disk.serial, dd->serial); +- dd->disk.total_blocks = __cpu_to_le32(size); ++ set_total_blocks(&dd->disk, size); ++ if (__le32_to_cpu(dd->disk.total_blocks_hi) > 0) { ++ struct imsm_super *mpb = super->anchor; ++ mpb->attributes |= MPB_ATTRIB_2TB_DISK; ++ } + mark_spare(dd); + if (sysfs_disk_to_scsi_id(fd, &id) == 0) + dd->disk.scsi_id = __cpu_to_le32(id); +@@ -5356,7 +5420,7 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten + if (maxsize < reserve) + return 0; + +- super->create_offset = ~((__u32) 0); ++ super->create_offset = ~((unsigned long long) 0); + if (start + reserve > super->create_offset) + return 0; /* start overflows create_offset */ + super->create_offset = start + reserve; +@@ -6597,8 +6661,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + this->array.working_disks++; + + info_d->events = __le32_to_cpu(mpb->generation_num); +- info_d->data_offset = __le32_to_cpu(map->pba_of_lba0); +- info_d->component_size = __le32_to_cpu(map->blocks_per_member); ++ info_d->data_offset = pba_of_lba0(map); ++ info_d->component_size = blocks_per_member(map); + } + /* now that the disk list is up-to-date fixup recovery_start */ + update_recovery_start(super, dev, this); +@@ -6882,7 +6946,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev) + /* set array size in metadata + */ + map = get_imsm_map(dev, MAP_0); +- array_blocks = map->blocks_per_member * used_disks; ++ array_blocks = blocks_per_member(map) * used_disks; + + /* round array size down to closest MB + */ +@@ -6997,7 +7061,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent) + used_disks = imsm_num_data_members(dev, MAP_0); + if (used_disks > 0) { + array_blocks = +- map->blocks_per_member * ++ blocks_per_member(map) * + used_disks; + /* round array size down to closest MB + */ +@@ -7364,9 +7428,9 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot, + found = 0; + j = 0; + pos = 0; +- array_start = __le32_to_cpu(map->pba_of_lba0); ++ array_start = pba_of_lba0(map); + array_end = array_start + +- __le32_to_cpu(map->blocks_per_member) - 1; ++ blocks_per_member(map) - 1; + + do { + /* check that we can start at pba_of_lba0 with +@@ -7566,7 +7630,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, + di->disk.minor = dl->minor; + di->disk.state = 0; + di->recovery_start = 0; +- di->data_offset = __le32_to_cpu(map->pba_of_lba0); ++ di->data_offset = pba_of_lba0(map); + di->component_size = a->info.component_size; + di->container_member = inst; + super->random = random32(); +@@ -8292,8 +8356,8 @@ static void imsm_process_update(struct supertype *st, + } + + new_map = get_imsm_map(&u->dev, MAP_0); +- new_start = __le32_to_cpu(new_map->pba_of_lba0); +- new_end = new_start + __le32_to_cpu(new_map->blocks_per_member); ++ new_start = pba_of_lba0(new_map); ++ new_end = new_start + blocks_per_member(new_map); + inf = get_disk_info(u); + + /* handle activate_spare versus create race: +@@ -8303,8 +8367,8 @@ static void imsm_process_update(struct supertype *st, + for (i = 0; i < mpb->num_raid_devs; i++) { + dev = get_imsm_dev(super, i); + map = get_imsm_map(dev, MAP_0); +- start = __le32_to_cpu(map->pba_of_lba0); +- end = start + __le32_to_cpu(map->blocks_per_member); ++ start = pba_of_lba0(map); ++ end = start + blocks_per_member(map); + if ((new_start >= start && new_start <= end) || + (start >= new_start && start <= new_end)) + /* overlap */; +@@ -9165,7 +9229,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info) + + write_offset = ((unsigned long long) + __le32_to_cpu(migr_rec->dest_1st_member_lba) + +- __le32_to_cpu(map_dest->pba_of_lba0)) * 512; ++ pba_of_lba0(map_dest)) * 512; + + unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512; + if (posix_memalign((void **)&buf, 512, unit_len) != 0) +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch b/mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch new file mode 100644 index 0000000..1ca37ab --- /dev/null +++ b/mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch @@ -0,0 +1,29 @@ +From 4ff46bbc34aca294afe2127536b620672486598e Mon Sep 17 00:00:00 2001 +From: Marcin Labun +Date: Wed, 14 Dec 2011 15:02:49 +0100 +Subject: [PATCH 1/6] imsm: display maximum volumes per controller in --detail-platform command + +Signed-off-by: Marcin Labun +--- + super-intel.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index b64aa7a..1c22aff 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1663,8 +1663,9 @@ static void print_imsm_capability(const struct imsm_orom *orom) + imsm_orom_has_chunk(orom, 1024*16) ? " 16M" : "", + imsm_orom_has_chunk(orom, 1024*32) ? " 32M" : "", + imsm_orom_has_chunk(orom, 1024*64) ? " 64M" : ""); +- printf(" Max Disks : %d\n", orom->tds); +- printf(" Max Volumes : %d\n", orom->vpa); ++ printf(" Max Disks : %d\n", orom->tds); ++ printf(" Max Volumes per array : %d\n", orom->vpa); ++ printf(" Max Volumes per controller: %d\n", orom->vphba); + return; + } + +-- +1.7.1 + diff --git a/mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch b/mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch new file mode 100644 index 0000000..962f78b --- /dev/null +++ b/mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch @@ -0,0 +1,62 @@ +From 7ce05701813496571e1f7f79c726aa6e4868bd5f Mon Sep 17 00:00:00 2001 +From: Lukasz Dorau +Date: Fri, 20 Apr 2012 13:45:02 +0200 +Subject: [PATCH 2/3] imsm: fix: rebuild does not continue after reboot + +If system is rebooted during rebuild, md driver changes sync_action +from 'recover' to 'idle' (during stopping all md devices). +If mdmon is still running then, it detects the change of sync_action state, +finishes rebuild and writes metadata to disks. After computer's restart +the RAID volume is in Normal state in OROM and rebuild seems to be finished. +After system's start-up RAID volume is in auto-read-only state +and metadata is in Dirty state. Rebuild seems to be finished but it is not. +Data is inconsistent (out-of-sync). + +When mdmon detects the change of sync_action from 'recover' to 'idle', +it has to check if rebuild is really finished. Appropriate test was added. +Now mdmon examines each volume's member if it is being rebuilt. + +Signed-off-by: Lukasz Dorau +Signed-off-by: NeilBrown +--- + super-intel.c | 17 +++++++++++++++++ + 1 files changed, 17 insertions(+), 0 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index e405d97..1ad5e47 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7273,6 +7273,8 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + struct imsm_dev *dev = get_imsm_dev(super, inst); + struct imsm_map *map = get_imsm_map(dev, MAP_0); + struct imsm_disk *disk; ++ struct mdinfo *mdi; ++ int recovery_not_finished = 0; + int failed; + __u32 ord; + __u8 map_state; +@@ -7313,6 +7315,21 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + dprintf("normal: "); + if (is_rebuilding(dev)) { + dprintf("while rebuilding"); ++ /* check if recovery is really finished */ ++ for (mdi = a->info.devs; mdi ; mdi = mdi->next) ++ if (mdi->recovery_start != MaxSector) { ++ recovery_not_finished = 1; ++ break; ++ } ++ if (recovery_not_finished) { ++ dprintf("\nimsm: Rebuild has not finished yet, " ++ "state not changed"); ++ if (a->last_checkpoint < mdi->recovery_start) { ++ a->last_checkpoint = mdi->recovery_start; ++ super->updates_pending++; ++ } ++ break; ++ } + end_migration(dev, super, map_state); + map = get_imsm_map(dev, MAP_0); + map->failed_disk_num = ~0; +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch b/mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch new file mode 100644 index 0000000..db17a01 --- /dev/null +++ b/mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch @@ -0,0 +1,40 @@ +From f878b24226953f06912ebceb2c811edf36818d2f Mon Sep 17 00:00:00 2001 +From: "Labun, Marcin" +Date: Fri, 27 Jan 2012 15:28:36 +0000 +Subject: [PATCH] imsm: fix, the second array need to have the whole available + space on devices + +Fix the case with creating an array with given container in command line +instead of real devices: +mdadm -CR /dev/md/raid0 -l 0 -n 2 -z5G /dev/md/imsm + +Signed-off-by: Marcin Labun +Signed-off-by: NeilBrown +--- + super-intel.c | 9 ++++++++- + 1 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 8d67a14..eba11d6 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6029,8 +6029,15 @@ static int reserve_space(struct supertype *st, int raiddisks, + size /= 2 * chunk; + size *= 2 * chunk; + } ++ maxsize = size; ++ } ++ if (!check_env("IMSM_NO_PLATFORM") && ++ mpb->num_raid_devs > 0 && size && size != maxsize) { ++ fprintf(stderr, Name ": attempting to create a second " ++ "volume with size less then remaining space. " ++ "Aborting...\n"); ++ return 0; + } +- + cnt = 0; + for (dl = super->disks; dl; dl = dl->next) + if (dl->e) +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch b/mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch new file mode 100644 index 0000000..eb5d951 --- /dev/null +++ b/mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch @@ -0,0 +1,33 @@ +From 86130b7a213485f1aeb078c6f32c901648e2f679 Mon Sep 17 00:00:00 2001 +From: Anna Czarnowska +Date: Mon, 2 Apr 2012 22:42:51 +0200 +Subject: [PATCH] imsm: fix: thunderdome may drop 2tb attribute + +Spare superblock doesn't depend on other spares in container. +When loading container metadata thunderdome +may pick a small disk for the champion. This will result in incorrect +interpretation of sizes of other disks in container when joint superblock +is returned. If any disk in container has the 2TB attribute set, the result +must have it set too. + +Signed-off-by: Anna Czarnowska +--- + super-intel.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index ed13542..869a39c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4079,6 +4079,8 @@ imsm_thunderdome(struct intel_super **super_list, int len) + if (s == champion) + continue; + ++ mpb->attributes |= s->anchor->attributes & MPB_ATTRIB_2TB_DISK; ++ + for (i = 0; i < mpb->num_disks; i++) { + struct imsm_disk *disk; + +-- +1.6.4.2 + diff --git a/mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch b/mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch new file mode 100644 index 0000000..65090e0 --- /dev/null +++ b/mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch @@ -0,0 +1,157 @@ +From ec50f7b6bb3a5218b51e1a953d530ef6b446bcd4 Mon Sep 17 00:00:00 2001 +From: "Labun, Marcin" +Date: Mon, 30 Jan 2012 11:57:23 +1100 +Subject: [PATCH 2/3] imsm: load_imsm_super_all supports loading metadata from + the device list + +This option is going to be used to load and analyse the metadata from +devices. This is needed to count the number of volumes on devcies attached +to particular Intel controller (SATA or SAS). It shall be done without +activation of container and volumes on the devices. + +Signed-off-by: Marcin Labun +Signed-off-by: NeilBrown +--- + super-intel.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 files changed, 73 insertions(+), 6 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 733d089..1cf8716 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -277,6 +277,22 @@ struct migr_record { + * (for recovered migrations) */ + } __attribute__ ((__packed__)); + ++struct md_list { ++ /* usage marker: ++ * 1: load metadata ++ * 2: metadata does not match ++ * 4: already checked ++ */ ++ int used; ++ char *devname; ++ int found; ++ int container; ++ dev_t st_rdev; ++ struct md_list *next; ++}; ++ ++#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg)) ++ + static __u8 migr_type(struct imsm_dev *dev) + { + if (dev->vol.migr_type == MIGR_VERIFY && +@@ -4012,12 +4028,16 @@ imsm_thunderdome(struct intel_super **super_list, int len) + + static int + get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd); +- + static int get_super_block(struct intel_super **super_list, int devnum, char *devname, + int major, int minor, int keep_fd); ++static int ++get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list, ++ int *max, int keep_fd); ++ + + static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, +- char *devname, int keep_fd) ++ char *devname, struct md_list *devlist, ++ int keep_fd) + { + struct intel_super *super_list = NULL; + struct intel_super *super = NULL; +@@ -4028,7 +4048,8 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, + /* 'fd' is an opened container */ + err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd); + else +- return 1; ++ /* get super block from devlist devices */ ++ err = get_devlist_super_block(devlist, &super_list, &i, keep_fd); + if (err) + goto error; + /* all mpbs enter, maybe one leaves */ +@@ -4094,7 +4115,54 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, + } + + ++static int ++get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list, ++ int *max, int keep_fd) ++{ ++ struct md_list *tmpdev; ++ int err = 0; ++ int i = 0; ++ int lmax = 0; + ++ for (i = 0, tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { ++ if (tmpdev->used != 1) ++ continue; ++ if (tmpdev->container == 1) { ++ int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL); ++ if (fd < 0) { ++ fprintf(stderr, Name ": cannot open device %s: %s\n", ++ tmpdev->devname, strerror(errno)); ++ err = 8; ++ goto error; ++ } ++ err = get_sra_super_block(fd, super_list, ++ tmpdev->devname, &lmax, ++ keep_fd); ++ i += lmax; ++ close(fd); ++ if (err) { ++ err = 7; ++ goto error; ++ } ++ } else { ++ int major = major(tmpdev->st_rdev); ++ int minor = minor(tmpdev->st_rdev); ++ err = get_super_block(super_list, ++ -1, ++ tmpdev->devname, ++ major, minor, ++ keep_fd); ++ i++; ++ if (err) { ++ err = 6; ++ goto error; ++ } ++ } ++ } ++ error: ++ *max = i; ++ return err; ++} + + static int get_super_block(struct intel_super **super_list, int devnum, char *devname, + int major, int minor, int keep_fd) +@@ -4187,7 +4255,7 @@ get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int + + static int load_container_imsm(struct supertype *st, int fd, char *devname) + { +- return load_super_imsm_all(st, fd, &st->sb, devname, 1); ++ return load_super_imsm_all(st, fd, &st->sb, devname, NULL, 1); + } + #endif + +@@ -5305,7 +5373,6 @@ static int imsm_default_chunk(const struct imsm_orom *orom) + return min(512, (1 << fs)); + } + +-#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg)) + static int + validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, + int raiddisks, int *chunk, int verbose) +@@ -5678,7 +5745,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + */ + struct intel_super *super; + +- if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) { ++ if (load_super_imsm_all(st, cfd, (void **) &super, NULL, NULL, 1) == 0) { + st->sb = super; + st->container_dev = fd2devnum(cfd); + close(cfd); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch b/mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch new file mode 100644 index 0000000..0b93193 --- /dev/null +++ b/mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch @@ -0,0 +1,261 @@ +From 9587c3739b6d6edc7abfa4a655b9ab46926abdbf Mon Sep 17 00:00:00 2001 +From: "Labun, Marcin" +Date: Mon, 30 Jan 2012 11:56:58 +1100 +Subject: [PATCH 1/3] imsm: load_super_imsm_all function refactoring + +Prepare function for subsequent changes related to +loading metadata from devices list. + +Signed-off-by: Marcin Labun +Signed-off-by: NeilBrown +--- + super-intel.c | 176 +++++++++++++++++++++++++++++++++++++------------------- + 1 files changed, 116 insertions(+), 60 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 0e9269f..733d089 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2985,7 +2985,7 @@ static void fd2devname(int fd, char *name) + rv = readlink(path, dname, sizeof(dname)-1); + if (rv <= 0) + return; +- ++ + dname[rv] = '\0'; + nm = strrchr(dname, '/'); + if (nm) { +@@ -4009,67 +4009,28 @@ imsm_thunderdome(struct intel_super **super_list, int len) + return champion; + } + ++ ++static int ++get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd); ++ ++static int get_super_block(struct intel_super **super_list, int devnum, char *devname, ++ int major, int minor, int keep_fd); ++ + static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, +- char *devname) ++ char *devname, int keep_fd) + { +- struct mdinfo *sra; + struct intel_super *super_list = NULL; + struct intel_super *super = NULL; +- int devnum = fd2devnum(fd); +- struct mdinfo *sd; +- int retry; + int err = 0; +- int i; ++ int i = 0; + +- /* check if 'fd' an opened container */ +- sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); +- if (!sra) ++ if (fd >= 0) ++ /* 'fd' is an opened container */ ++ err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd); ++ else + return 1; +- +- if (sra->array.major_version != -1 || +- sra->array.minor_version != -2 || +- strcmp(sra->text_version, "imsm") != 0) { +- err = 1; ++ if (err) + goto error; +- } +- /* load all mpbs */ +- for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) { +- struct intel_super *s = alloc_super(); +- char nm[32]; +- int dfd; +- int rv; +- +- err = 1; +- if (!s) +- goto error; +- s->next = super_list; +- super_list = s; +- +- err = 2; +- sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); +- dfd = dev_open(nm, O_RDWR); +- if (dfd < 0) +- goto error; +- +- rv = find_intel_hba_capability(dfd, s, devname); +- /* no orom/efi or non-intel hba of the disk */ +- if (rv != 0) +- goto error; +- +- err = load_and_parse_mpb(dfd, s, NULL, 1); +- +- /* retry the load if we might have raced against mdmon */ +- if (err == 3 && mdmon_running(devnum)) +- for (retry = 0; retry < 3; retry++) { +- usleep(3000); +- err = load_and_parse_mpb(dfd, s, NULL, 1); +- if (err != 3) +- break; +- } +- if (err) +- goto error; +- } +- + /* all mpbs enter, maybe one leaves */ + super = imsm_thunderdome(&super_list, i); + if (!super) { +@@ -4114,13 +4075,16 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, + super_list = super_list->next; + free_imsm(s); + } +- sysfs_free(sra); ++ + + if (err) + return err; + + *sbp = super; +- st->container_dev = devnum; ++ if (fd >= 0) ++ st->container_dev = fd2devnum(fd); ++ else ++ st->container_dev = NoMdDev; + if (err == 0 && st->ss == NULL) { + st->ss = &super_imsm; + st->minor_version = 0; +@@ -4129,9 +4093,101 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, + return 0; + } + ++ ++ ++ ++static int get_super_block(struct intel_super **super_list, int devnum, char *devname, ++ int major, int minor, int keep_fd) ++{ ++ struct intel_super*s = NULL; ++ char nm[32]; ++ int dfd = -1; ++ int rv; ++ int err = 0; ++ int retry; ++ ++ s = alloc_super(); ++ if (!s) { ++ err = 1; ++ goto error; ++ } ++ ++ sprintf(nm, "%d:%d", major, minor); ++ dfd = dev_open(nm, O_RDWR); ++ if (dfd < 0) { ++ err = 2; ++ goto error; ++ } ++ ++ rv = find_intel_hba_capability(dfd, s, devname); ++ /* no orom/efi or non-intel hba of the disk */ ++ if (rv != 0) { ++ err = 4; ++ goto error; ++ } ++ ++ err = load_and_parse_mpb(dfd, s, NULL, keep_fd); ++ ++ /* retry the load if we might have raced against mdmon */ ++ if (err == 3 && (devnum != -1) && mdmon_running(devnum)) ++ for (retry = 0; retry < 3; retry++) { ++ usleep(3000); ++ err = load_and_parse_mpb(dfd, s, NULL, keep_fd); ++ if (err != 3) ++ break; ++ } ++ error: ++ if (!err) { ++ s->next = *super_list; ++ *super_list = s; ++ } else { ++ if (s) ++ free(s); ++ if (dfd) ++ close(dfd); ++ } ++ if ((dfd >= 0) && (!keep_fd)) ++ close(dfd); ++ return err; ++ ++} ++ ++static int ++get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd) ++{ ++ struct mdinfo *sra; ++ int devnum; ++ struct mdinfo *sd; ++ int err = 0; ++ int i = 0; ++ sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); ++ if (!sra) ++ return 1; ++ ++ if (sra->array.major_version != -1 || ++ sra->array.minor_version != -2 || ++ strcmp(sra->text_version, "imsm") != 0) { ++ err = 1; ++ goto error; ++ } ++ /* load all mpbs */ ++ devnum = fd2devnum(fd); ++ for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) { ++ if (get_super_block(super_list, devnum, devname, ++ sd->disk.major, sd->disk.minor, keep_fd) != 0) { ++ err = 7; ++ goto error; ++ } ++ } ++ error: ++ sysfs_free(sra); ++ *max = i; ++ return err; ++} ++ + static int load_container_imsm(struct supertype *st, int fd, char *devname) + { +- return load_super_imsm_all(st, fd, &st->sb, devname); ++ return load_super_imsm_all(st, fd, &st->sb, devname, 1); + } + #endif + +@@ -5558,7 +5614,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + dev, freesize, + verbose); + } +- ++ + if (!dev) { + if (st->sb) { + if (!validate_geometry_imsm_orom(st->sb, level, layout, +@@ -5622,7 +5678,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + */ + struct intel_super *super; + +- if (load_super_imsm_all(st, cfd, (void **) &super, NULL) == 0) { ++ if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) { + st->sb = super; + st->container_dev = fd2devnum(cfd); + close(cfd); +@@ -6198,7 +6254,7 @@ static int imsm_open_new(struct supertype *c, struct active_array *a, + { + struct intel_super *super = c->sb; + struct imsm_super *mpb = super->anchor; +- ++ + if (atoi(inst) >= mpb->num_raid_devs) { + fprintf(stderr, "%s: subarry index %d, out of range\n", + __func__, atoi(inst)); +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch b/mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch new file mode 100644 index 0000000..1fc8ca1 --- /dev/null +++ b/mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch @@ -0,0 +1,30 @@ +From 027c374fd946824704291da933300da78c32a189 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:19:04 +1000 +Subject: [PATCH 7/7] imsm: set 2tb disk attribute for spare + +This patch ensures metadata attribute is set correctly also for spares. + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 1bc9e9c..dad4c4d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5048,6 +5048,9 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose) + continue; + + spare->disk[0] = d->disk; ++ if (__le32_to_cpu(d->disk.total_blocks_hi) > 0) ++ spare->attributes |= MPB_ATTRIB_2TB_DISK; ++ + sum = __gen_imsm_checksum(spare); + spare->family_num = __cpu_to_le32(sum); + spare->orig_family_num = 0; +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch b/mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch new file mode 100644 index 0000000..9ba351f --- /dev/null +++ b/mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch @@ -0,0 +1,497 @@ +From ca9de185a3b96720adcc5120f6a34c5f9bb98b3f Mon Sep 17 00:00:00 2001 +From: "Labun, Marcin" +Date: Mon, 30 Jan 2012 12:00:10 +1100 +Subject: [PATCH 3/3] imsm: validate the number of imsm volumes per controller + +IMSM OROM limits number of volumes per controller. Volumes +above the limit are blocked in OROM. mdadm should follow OROM limitations +in this area. Therefore we need to count number of volumes on the devices +attached to SATA (ahci driver) or SAS (isci) controller. Adding a new volume +must be blocked if the number of volumes on devices attached to the given +controller is exceeded. + +Signed-off-by: Marcin Labun +Signed-off-by: NeilBrown +--- + super-intel.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 399 insertions(+), 5 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 1cf8716..7db5177 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -3285,7 +3285,7 @@ static int parse_raid_devices(struct intel_super *super) + len_migr = sizeof_imsm_dev(dev_iter, 1); + if (len_migr > len) + space_needed += len_migr - len; +- ++ + dv = malloc(sizeof(*dv)); + if (!dv) + return 1; +@@ -3321,7 +3321,7 @@ static int parse_raid_devices(struct intel_super *super) + super->buf = buf; + super->len = len; + } +- ++ + return 0; + } + +@@ -4122,12 +4122,12 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list + struct md_list *tmpdev; + int err = 0; + int i = 0; +- int lmax = 0; + + for (i = 0, tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { + if (tmpdev->used != 1) + continue; + if (tmpdev->container == 1) { ++ int lmax = 0; + int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL); + if (fd < 0) { + fprintf(stderr, Name ": cannot open device %s: %s\n", +@@ -5363,6 +5363,377 @@ static int is_raid_level_supported(const struct imsm_orom *orom, int level, int + return 0; + } + ++ ++static int ++active_arrays_by_format(char *name, char* hba, struct md_list **devlist, ++ int dpa, int verbose) ++{ ++ struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ struct mdstat_ent *memb = NULL; ++ int count = 0; ++ int num = 0; ++ struct md_list *dv = NULL; ++ int found; ++ ++ for (memb = mdstat ; memb ; memb = memb->next) { ++ if (memb->metadata_version && ++ (strncmp(memb->metadata_version, "external:", 9) == 0) && ++ (strcmp(&memb->metadata_version[9], name) == 0) && ++ !is_subarray(memb->metadata_version+9) && ++ memb->members) { ++ struct dev_member *dev = memb->members; ++ int fd = -1; ++ while(dev && (fd < 0)) { ++ char *path = malloc(strlen(dev->name) + strlen("/dev/") + 1); ++ if (path) { ++ num = sprintf(path, "%s%s", "/dev/", dev->name); ++ if (num > 0) ++ fd = open(path, O_RDONLY, 0); ++ if ((num <= 0) || (fd < 0)) { ++ pr_vrb(": Cannot open %s: %s\n", ++ dev->name, strerror(errno)); ++ } ++ free(path); ++ } ++ dev = dev->next; ++ } ++ found = 0; ++ if ((fd >= 0) && disk_attached_to_hba(fd, hba)) { ++ struct mdstat_ent *vol; ++ for (vol = mdstat ; vol ; vol = vol->next) { ++ if ((vol->active > 0) && ++ vol->metadata_version && ++ is_container_member(vol, memb->dev)) { ++ found++; ++ count++; ++ } ++ } ++ if (*devlist && (found < dpa)) { ++ dv = calloc(1, sizeof(*dv)); ++ if (dv == NULL) ++ fprintf(stderr, Name ": calloc failed\n"); ++ else { ++ dv->devname = malloc(strlen(memb->dev) + strlen("/dev/") + 1); ++ if (dv->devname != NULL) { ++ sprintf(dv->devname, "%s%s", "/dev/", memb->dev); ++ dv->found = found; ++ dv->used = 0; ++ dv->next = *devlist; ++ *devlist = dv; ++ } else ++ free(dv); ++ } ++ } ++ } ++ if (fd >= 0) ++ close(fd); ++ } ++ } ++ free_mdstat(mdstat); ++ return count; ++} ++ ++#ifdef DEBUG_LOOP ++static struct md_list* ++get_loop_devices(void) ++{ ++ int i; ++ struct md_list *devlist = NULL; ++ struct md_list *dv = NULL; ++ ++ for(i = 0; i < 12; i++) { ++ dv = calloc(1, sizeof(*dv)); ++ if (dv == NULL) { ++ fprintf(stderr, Name ": calloc failed\n"); ++ break; ++ } ++ dv->devname = malloc(40); ++ if (dv->devname == NULL) { ++ fprintf(stderr, Name ": malloc failed\n"); ++ free(dv); ++ break; ++ } ++ sprintf(dv->devname, "/dev/loop%d", i); ++ dv->next = devlist; ++ devlist = dv; ++ } ++ return devlist; ++} ++#endif ++ ++static struct md_list* ++get_devices(const char *hba_path) ++{ ++ struct md_list *devlist = NULL; ++ struct md_list *dv = NULL; ++ struct dirent *ent; ++ DIR *dir; ++ int err = 0; ++ ++#if DEBUG_LOOP ++ devlist = get_loop_devices(); ++ return devlist; ++#endif ++ /* scroll through /sys/dev/block looking for devices attached to ++ * this hba ++ */ ++ dir = opendir("/sys/dev/block"); ++ for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) { ++ int fd; ++ char buf[1024]; ++ int major, minor; ++ char *path = NULL; ++ if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2) ++ continue; ++ path = devt_to_devpath(makedev(major, minor)); ++ if (!path) ++ continue; ++ if (!path_attached_to_hba(path, hba_path)) { ++ free(path); ++ path = NULL; ++ continue; ++ } ++ free(path); ++ path = NULL; ++ fd = dev_open(ent->d_name, O_RDONLY); ++ if (fd >= 0) { ++ fd2devname(fd, buf); ++ close(fd); ++ } else { ++ fprintf(stderr, Name ": cannot open device: %s\n", ++ ent->d_name); ++ continue; ++ } ++ ++ ++ dv = calloc(1, sizeof(*dv)); ++ if (dv == NULL) { ++ fprintf(stderr, Name ": malloc failed\n"); ++ err = 1; ++ break; ++ } ++ dv->devname = strdup(buf); ++ if (dv->devname == NULL) { ++ fprintf(stderr, Name ": malloc failed\n"); ++ err = 1; ++ free(dv); ++ break; ++ } ++ dv->next = devlist; ++ devlist = dv; ++ } ++ if (err) { ++ while(devlist) { ++ dv = devlist; ++ devlist = devlist->next; ++ free(dv->devname); ++ free(dv); ++ } ++ } ++ return devlist; ++} ++ ++static int ++count_volumes_list(struct md_list *devlist, char *homehost, ++ int verbose, int *found) ++{ ++ struct md_list *tmpdev; ++ int count = 0; ++ struct supertype *st = NULL; ++ ++ /* first walk the list of devices to find a consistent set ++ * that match the criterea, if that is possible. ++ * We flag the ones we like with 'used'. ++ */ ++ *found = 0; ++ st = match_metadata_desc_imsm("imsm"); ++ if (st == NULL) { ++ pr_vrb(": cannot allocate memory for imsm supertype\n"); ++ return 0; ++ } ++ ++ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { ++ char *devname = tmpdev->devname; ++ struct stat stb; ++ struct supertype *tst; ++ int dfd; ++ if (tmpdev->used > 1) ++ continue; ++ tst = dup_super(st); ++ if (tst == NULL) { ++ pr_vrb(": cannot allocate memory for imsm supertype\n"); ++ goto err_1; ++ } ++ tmpdev->container = 0; ++ dfd = dev_open(devname, O_RDONLY|O_EXCL); ++ if (dfd < 0) { ++ dprintf(": cannot open device %s: %s\n", ++ devname, strerror(errno)); ++ tmpdev->used = 2; ++ } else if (fstat(dfd, &stb)< 0) { ++ /* Impossible! */ ++ dprintf(": fstat failed for %s: %s\n", ++ devname, strerror(errno)); ++ tmpdev->used = 2; ++ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { ++ dprintf(": %s is not a block device.\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (must_be_container(dfd)) { ++ struct supertype *cst; ++ cst = super_by_fd(dfd, NULL); ++ if (cst == NULL) { ++ dprintf(": cannot recognize container type %s\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (tst->ss != st->ss) { ++ dprintf(": non-imsm container - ignore it: %s\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (!tst->ss->load_container || ++ tst->ss->load_container(tst, dfd, NULL)) ++ tmpdev->used = 2; ++ else { ++ tmpdev->container = 1; ++ } ++ if (cst) ++ cst->ss->free_super(cst); ++ } else { ++ tmpdev->st_rdev = stb.st_rdev; ++ if (tst->ss->load_super(tst,dfd, NULL)) { ++ dprintf(": no RAID superblock on %s\n", ++ devname); ++ tmpdev->used = 2; ++ } else if (tst->ss->compare_super == NULL) { ++ dprintf(": Cannot assemble %s metadata on %s\n", ++ tst->ss->name, devname); ++ tmpdev->used = 2; ++ } ++ } ++ if (dfd >= 0) ++ close(dfd); ++ if (tmpdev->used == 2 || tmpdev->used == 4) { ++ /* Ignore unrecognised devices during auto-assembly */ ++ goto loop; ++ } ++ else { ++ struct mdinfo info; ++ tst->ss->getinfo_super(tst, &info, NULL); ++ ++ if (st->minor_version == -1) ++ st->minor_version = tst->minor_version; ++ ++ if (memcmp(info.uuid, uuid_zero, ++ sizeof(int[4])) == 0) { ++ /* this is a floating spare. It cannot define ++ * an array unless there are no more arrays of ++ * this type to be found. It can be included ++ * in an array of this type though. ++ */ ++ tmpdev->used = 3; ++ goto loop; ++ } ++ ++ if (st->ss != tst->ss || ++ st->minor_version != tst->minor_version || ++ st->ss->compare_super(st, tst) != 0) { ++ /* Some mismatch. If exactly one array matches this host, ++ * we can resolve on that one. ++ * Or, if we are auto assembling, we just ignore the second ++ * for now. ++ */ ++ dprintf(": superblock on %s doesn't match others - assembly aborted\n", ++ devname); ++ goto loop; ++ } ++ tmpdev->used = 1; ++ *found = 1; ++ dprintf("found: devname: %s\n", devname); ++ } ++ loop: ++ if (tst) ++ tst->ss->free_super(tst); ++ } ++ if (*found != 0) { ++ int err; ++ if ((err = load_super_imsm_all(st, -1, &st->sb, NULL, devlist, 0)) == 0) { ++ struct mdinfo *iter, *head = st->ss->container_content(st, NULL); ++ for (iter = head; iter; iter = iter->next) { ++ dprintf("content->text_version: %s vol\n", ++ iter->text_version); ++ if (iter->array.state & (1<text_version); ++ } else ++ count++; ++ } ++ sysfs_free(head); ++ ++ } else { ++ dprintf(" no valid super block on device list: err: %d %p\n", ++ err, st->sb); ++ } ++ } else { ++ dprintf(" no more devices to examin\n"); ++ } ++ ++ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { ++ if ((tmpdev->used == 1) && (tmpdev->found)) { ++ if (count) { ++ if (count < tmpdev->found) ++ count = 0; ++ else ++ count -= tmpdev->found; ++ } ++ } ++ if (tmpdev->used == 1) ++ tmpdev->used = 4; ++ } ++ err_1: ++ if (st) ++ st->ss->free_super(st); ++ return count; ++} ++ ++ ++static int ++count_volumes(char *hba, int dpa, int verbose) ++{ ++ struct md_list *devlist = NULL; ++ int count = 0; ++ int found = 0;; ++ ++ devlist = get_devices(hba); ++ /* if no intel devices return zero volumes */ ++ if (devlist == NULL) ++ return 0; ++ ++ count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose); ++ dprintf(" path: %s active arrays: %d\n", hba, count); ++ if (devlist == NULL) ++ return 0; ++ do { ++ found = 0; ++ count += count_volumes_list(devlist, ++ NULL, ++ verbose, ++ &found); ++ dprintf("found %d count: %d\n", found, count); ++ } while (found); ++ ++ dprintf("path: %s total number of volumes: %d\n", hba, count); ++ ++ while(devlist) { ++ struct md_list *dv = devlist; ++ devlist = devlist->next; ++ free(dv->devname); ++ free(dv); ++ } ++ return count; ++} ++ + static int imsm_default_chunk(const struct imsm_orom *orom) + { + /* up to 512 if the plaform supports it, otherwise the platform max. +@@ -5583,6 +5954,15 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, + + *freesize = maxsize; + ++ if (super->orom) { ++ int count = count_volumes(super->hba->path, ++ super->orom->dpa, verbose); ++ if (super->orom->vphba <= count) { ++ pr_vrb(": platform does not support more then %d raid volumes.\n", ++ super->orom->vphba); ++ return 0; ++ } ++ } + return 1; + } + +@@ -5684,6 +6064,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + + if (!dev) { + if (st->sb) { ++ struct intel_super *super = st->sb; + if (!validate_geometry_imsm_orom(st->sb, level, layout, + raiddisks, chunk, + verbose)) +@@ -5696,6 +6077,19 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + * created. add_to_super and getinfo_super + * detect when autolayout is in progress. + */ ++ /* assuming that freesize is always given when array is ++ created */ ++ if (super->orom && freesize) { ++ int count; ++ count = count_volumes(super->hba->path, ++ super->orom->dpa, verbose); ++ if (super->orom->vphba <= count) { ++ pr_vrb(": platform does not support more" ++ "then %d raid volumes.\n", ++ super->orom->vphba); ++ return 0; ++ } ++ } + if (freesize) + return reserve_space(st, raiddisks, size, + chunk?*chunk:0, freesize); +@@ -7176,7 +7570,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, + } + return NULL; + } +- ++ + mu->space = NULL; + mu->space_list = NULL; + mu->len = sizeof(struct imsm_update_activate_spare) * num_spares; +@@ -7420,7 +7814,7 @@ error_disk_add: + } + + static int apply_update_activate_spare(struct imsm_update_activate_spare *u, +- struct intel_super *super, ++ struct intel_super *super, + struct active_array *active_array) + { + struct imsm_super *mpb = super->anchor; +-- +1.7.7.6 + diff --git a/mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch b/mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch new file mode 100644 index 0000000..71deeee --- /dev/null +++ b/mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch @@ -0,0 +1,39 @@ +From 29cd0821bfe5acdeac0b8bb54b1de9e07a453323 Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:17:25 +1000 +Subject: [PATCH 4/7] show 2TB volumes/disks support in --detail-platform + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + platform-intel.h | 1 + + super-intel.c | 4 ++++ + 2 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/platform-intel.h b/platform-intel.h +index c997f1b..94f2e81 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -76,6 +76,7 @@ struct imsm_orom { + #define IMSM_OROM_ATTR_RAID1E IMSM_OROM_RLC_RAID1E + #define IMSM_OROM_ATTR_RAID5 IMSM_OROM_RLC_RAID5 + #define IMSM_OROM_ATTR_RAID_CNG IMSM_OROM_RLC_RAID_CNG ++ #define IMSM_OROM_ATTR_2TB_DISK (1 << 26) + #define IMSM_OROM_ATTR_2TB (1 << 29) + #define IMSM_OROM_ATTR_PM (1 << 30) + #define IMSM_OROM_ATTR_ChecksumVerify (1 << 31) +diff --git a/super-intel.c b/super-intel.c +index 642ca26..0c38b45 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1786,6 +1786,10 @@ + printf(" Max Disks : %d\n", orom->tds); + printf(" Max Volumes per array : %d\n", orom->vpa); + printf(" Max Volumes per controller: %d\n", orom->vphba); ++ printf(" 2TB Volumes:%s supported\n", ++ (orom->attr & IMSM_OROM_ATTR_2TB) ? "" : " not"); ++ printf(" 2TB Disks:%s supported\n", ++ (orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "" : " not"); + return; + } + diff --git a/mdadm-3.2.3-simplify-calculating-array_blocks.patch b/mdadm-3.2.3-simplify-calculating-array_blocks.patch new file mode 100644 index 0000000..d28def9 --- /dev/null +++ b/mdadm-3.2.3-simplify-calculating-array_blocks.patch @@ -0,0 +1,47 @@ +From e03640bda562df11b60ceaaa40a56425f358090e Mon Sep 17 00:00:00 2001 +From: "Czarnowska, Anna" +Date: Mon, 2 Apr 2012 10:16:04 +1000 +Subject: [PATCH 3/7] simplify calculating array_blocks + +no point calling info_to_blocks_per_member when it just returns size*2 for level==1 +calc_array_size can be used for all levels + +Signed-off-by: Anna Czarnowska +Signed-off-by: NeilBrown +--- + super-intel.c | 5 +---- + util.c | 2 ++ + 2 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 480b379..642ca26 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4623,10 +4623,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + } + + strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN); +- if (info->level == 1) +- array_blocks = info_to_blocks_per_member(info, size); +- else +- array_blocks = calc_array_size(info->level, info->raid_disks, ++ array_blocks = calc_array_size(info->level, info->raid_disks, + info->layout, info->chunk_size, + size * 2); + /* round array size down to closest MB */ +diff --git a/util.c b/util.c +index 7abbff7..d32e650 100644 +--- a/util.c ++++ b/util.c +@@ -711,6 +711,8 @@ void print_r10_layout(int layout) + unsigned long long calc_array_size(int level, int raid_disks, int layout, + int chunksize, unsigned long long devsize) + { ++ if (level == 1) ++ return devsize; + devsize &= ~(unsigned long long)((chunksize>>9)-1); + return get_data_disks(level, layout, raid_disks) * devsize; + } +-- +1.7.7.6 + diff --git a/mdadm.spec b/mdadm.spec index 82ea4fe..a5a4792 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,7 +1,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm Version: 3.2.3 -Release: 8%{?dist} +Release: 9%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.bz2 Source1: mdmonitor.init Source2: raid-check @@ -38,6 +38,49 @@ Patch24: mdadm-3.2.3-imsm-FIX-Clear-migration-record-when-migration-switc.pa Patch25: mdadm-3.2.3-FIX-restart-reshape-when-reshape-process-is-stopped-.patch Patch26: mdadm-3.2.3-FIX-Do-not-try-to-continue-reshape-using-inactive-ar.patch Patch27: mdadm-3.2.3-FIX-Changes-in-0-case-for-reshape-position-verificat.patch +Patch28: mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch +Patch29: mdadm-3.2.3-fix-container-creation-with-incremental-used.patch +Patch30: mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch +Patch31: mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch +Patch32: mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch +Patch33: mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch +Patch34: mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch +Patch35: mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch +Patch36: mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch +Patch37: mdadm-3.2.3-simplify-calculating-array_blocks.patch +Patch38: mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch +Patch39: mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch +Patch40: mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch +Patch41: mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch +Patch42: mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch +Patch43: mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch +Patch44: mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch +Patch45: mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch +Patch46: mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch +Patch47: mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch +Patch48: mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch +Patch49: mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch +Patch50: mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch +Patch51: mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch +Patch52: mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch +Patch53: mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch +Patch54: mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch +Patch55: mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch +Patch56: mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch +Patch57: mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch +Patch58: mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch +Patch59: mdadm-3.2.3-Manage-allow-re-add-to-failed-array.patch +Patch60: mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch +Patch61: mdadm-3.2.3-Manage-freeze-recovery-while-adding-multiple-devices.patch +Patch62: mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch +Patch63: mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch +Patch64: mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch +Patch65: mdadm-3.2.3-Reset-bad-flag-on-map-update.patch +Patch66: mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch +Patch67: mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch +Patch68: mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch + +# Fedora customization patches Patch98: mdadm-3.2.3-udev.patch Patch99: mdadm-2.5.2-static.patch URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -99,6 +142,47 @@ is not used as the system init process. %patch25 -p1 -b .restart %patch26 -p1 -b .nocontinue %patch27 -p1 -b .0case +%patch28 -p1 -b .monitor3 +%patch29 -p1 -b .container +%patch30 -p1 -b .available +%patch31 -p1 -b .validate-1 +%patch32 -p1 -b .validate-2 +%patch33 -p1 -b .validate-3 +%patch34 -p1 -b .validate-4 +%patch35 -p1 -b .2tb-1 +%patch36 -p1 -b .2tb-2 +%patch37 -p1 -b .2tb-3 +%patch38 -p1 -b .2tb-4 +%patch39 -p1 -b .2tb-5 +%patch40 -p1 -b .2tb-6 +%patch41 -p1 -b .2tb-7 +%patch42 -p1 -b .2tb-8 +%patch43 -p1 -b .expand-01 +%patch44 -p1 -b .expand-02 +%patch45 -p1 -b .expand-03 +%patch46 -p1 -b .expand-04 +%patch47 -p1 -b .expand-05 +%patch48 -p1 -b .expand-06 +%patch49 -p1 -b .expand-07 +%patch50 -p1 -b .expand-08 +%patch51 -p1 -b .expand-09 +%patch52 -p1 -b .expand-10 +%patch53 -p1 -b .expand-11 +%patch54 -p1 -b .expand-12 +%patch55 -p1 -b .expand-13 +%patch56 -p1 -b .expand-14 +%patch57 -p1 -b .expand-15 +%patch58 -p1 -b .rebuild-continue +%patch59 -p1 -b .allow-re-add +%patch60 -p1 -b .replace-return-1 +%patch61 -p1 -b .freeze-recovery +%patch62 -p1 -b .make-add-work +%patch63 -p1 -b .max-devices +%patch64 -p1 -b .enough +%patch65 -p1 -b .bad-flag +%patch66 -p1 -b .bitmap-offset +%patch67 -p1 -b .bitmap-offset2 +%patch68 -p1 -b .bitmap-offset3 # Fedora customization patches %patch98 -p1 -b .udev @@ -175,6 +259,27 @@ fi %{_initrddir}/* %changelog +* Mon Apr 30 2012 Jes Sorensen - 3.2.3-9 +- Fix Monitor mode sometimes crashes when a resync completes +- Fix missing symlink for mdadm container device when incremental creates + the array +- Make sure when creating a second array in a container that the second + array uses all available space since leaving space for a third array + is invalid +- Validate the number of imsm volumes per controller +- Fix issues with imsm arrays and disks larger than 2TB +- Add support for expanding imsm arrays/containers +- The support for expanding imsm arrays/containers was accepted upstream, + update to the official patches from there +- Fix for the issue of --add not being very smart +- Fix an issue causing rebuilds to fail to restart on reboot (data + corrupter level problem) +- Reset the bad flag on map file updates +- Correctly fix failure when trying to add internal bitmap to 1.0 arrays +- Resolves: bz817023 (f17) bz817024 (f17) bz817026 (f17) bz817028 (f17) +- Resolves: bz817029 (f17) bz817032 (f17) bz817038 (f17) bz808774 (f17) +- Resolves: bz817039 (f17) bz817042 (f17) + * Mon Apr 30 2012 Jes Sorensen - 3.2.3-8 - Fix bug where IMSM arrays stay inactive in case a reboot is - performed during the reshape process.