diff --git a/SOURCES/mdadm-3.3.2-fix-problem-with-grow-continue.patch b/SOURCES/mdadm-3.3.2-fix-problem-with-grow-continue.patch new file mode 100644 index 0000000..4ad9428 --- /dev/null +++ b/SOURCES/mdadm-3.3.2-fix-problem-with-grow-continue.patch @@ -0,0 +1,52 @@ +commit 8e7ddc5f50af00e569ef115e25c635e2d74e90f0 +Author: NeilBrown +Date: Thu May 28 16:43:15 2015 +1000 + + Grow: fix problem with --grow --continue + + If an array is being reshaped using backup space on a 'spare' device, + then + mdadm --grow --continue + won't find it as by the time it runs, nothing looks like a spare are + more. The spare has been added to the array, but has no data yet. + + So allow reshape_prepare_fdlist to find a newly-incorporated spare and + report this so it can be used. + + Reported-by: Xiao Ni + Signed-off-by: NeilBrown + +diff --git a/Grow.c b/Grow.c +index a20ff3e..85de1d2 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -850,7 +850,8 @@ int reshape_prepare_fdlist(char *devname, + for (sd = sra->devs; sd; sd = sd->next) { + if (sd->disk.state & (1<disk.state & (1<disk.state & (1<disk.raid_disk < raid_disks) { + char *dn = map_dev(sd->disk.major, + sd->disk.minor, 1); + fdlist[sd->disk.raid_disk] +@@ -3184,7 +3185,7 @@ started: + d = reshape_prepare_fdlist(devname, sra, odisks, + nrdisks, blocks, backup_file, + fdlist, offsets); +- if (d < 0) { ++ if (d < odisks) { + goto release; + } + if ((st->ss->manage_reshape == NULL) || +@@ -3196,7 +3197,7 @@ started: + devname); + pr_err(" Please provide one with \"--backup=...\"\n"); + goto release; +- } else if (sra->array.spare_disks == 0) { ++ } else if (d == odisks) { + pr_err("%s: Cannot grow - " + "need a spare or backup-file to backup " + "critical section\n", devname); + goto release; + } diff --git a/SOURCES/mdadm-3.3.2-fix-resize-of-array-component-size-to-32bits.patch b/SOURCES/mdadm-3.3.2-fix-resize-of-array-component-size-to-32bits.patch new file mode 100644 index 0000000..5084809 --- /dev/null +++ b/SOURCES/mdadm-3.3.2-fix-resize-of-array-component-size-to-32bits.patch @@ -0,0 +1,30 @@ +commit 0448027b765ec7ede580a1630c23fe7cf4bd0b05 +Author: Justin Maggard +Date: Fri Oct 24 17:55:02 2014 -0700 + + Grow: fix resize of array component size to > 32bits + + If the request --size to --grow an array to is larger + than 32bits, then mdadm may make the wrong choice and + use ioctl instead of setting component_size via sysfs + and the change is ignored. + + Instead of using casts to check for a 32-bit overflow, + just check for set bits outside of INT32_MAX. + + Fixes: 4e9a3dd16d656b269f5602624ac4f7109a571368 + Signed-off-by: NeilBrown + +diff --git a/Grow.c b/Grow.c +index 76bb35a..a0f7526 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1818,7 +1818,7 @@ int Grow_reshape(char *devname, int fd, + if (s->size == MAX_SIZE) + s->size = 0; + array.size = s->size; +- if (array.size != (signed)s->size) { ++ if (s->size & ~INT32_MAX) { + /* got truncated to 32bit, write to + * component_size instead + */ diff --git a/SOURCES/mdadm-3.3.2-imsm-add-support-for-NVMe-devices.patch b/SOURCES/mdadm-3.3.2-imsm-add-support-for-NVMe-devices.patch new file mode 100644 index 0000000..a10ecbc --- /dev/null +++ b/SOURCES/mdadm-3.3.2-imsm-add-support-for-NVMe-devices.patch @@ -0,0 +1,202 @@ +From 614902f64e856b4cffc26687fac74412c4a6d91c Mon Sep 17 00:00:00 2001 +From: Pawel Baldysiak +Date: Wed, 19 Nov 2014 13:53:28 +0100 +Subject: [PATCH] imsm: add support for NVMe devices + +Recognize Intel(R) NVMe devices as IMSM-capable. + +Signed-off-by: Pawel Baldysiak +Signed-off-by: Artur Paszkiewicz +Signed-off-by: NeilBrown +--- + platform-intel.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- + platform-intel.h | 5 +++++ + super-intel.c | 11 +++++++---- + 3 files changed, 56 insertions(+), 6 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index c5a0aa4..ae72827 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -65,6 +65,8 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + type = SYS_DEV_SAS; + else if (strcmp(driver, "ahci") == 0) + type = SYS_DEV_SATA; ++ else if (strcmp(driver, "nvme") == 0) ++ type = SYS_DEV_NVME; + else + type = SYS_DEV_UNKNOWN; + +@@ -174,7 +176,7 @@ static __u16 devpath_to_vendor(const char *dev_path) + + struct sys_dev *find_intel_devices(void) + { +- struct sys_dev *ahci, *isci; ++ struct sys_dev *ahci, *isci, *nvme; + + if (valid_time > time(0) - 10) + return intel_devices; +@@ -184,14 +186,24 @@ struct sys_dev *find_intel_devices(void) + + isci = find_driver_devices("pci", "isci"); + ahci = find_driver_devices("pci", "ahci"); ++ nvme = find_driver_devices("pci", "nvme"); + +- if (!ahci) { ++ if (!isci && !ahci) { ++ ahci = nvme; ++ } else if (!ahci) { + ahci = isci; ++ struct sys_dev *elem = ahci; ++ while (elem->next) ++ elem = elem->next; ++ elem->next = nvme; + } else { + struct sys_dev *elem = ahci; + while (elem->next) + elem = elem->next; + elem->next = isci; ++ while (elem->next) ++ elem = elem->next; ++ elem->next = nvme; + } + intel_devices = ahci; + valid_time = time(0); +@@ -497,6 +509,33 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + return ret; + } + ++const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba) ++{ ++ static const struct imsm_orom *nvme_orom; ++ ++ if (hba->type != SYS_DEV_NVME) ++ return NULL; ++ ++ if (!nvme_orom) { ++ struct imsm_orom nvme_orom_compat = { ++ .signature = IMSM_NVME_OROM_COMPAT_SIGNATURE, ++ .rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | ++ IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5, ++ .sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB | ++ IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB | ++ IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB, ++ .dpa = IMSM_OROM_DISKS_PER_ARRAY_NVME, ++ .tds = IMSM_OROM_TOTAL_DISKS_NVME, ++ .vpa = IMSM_OROM_VOLUMES_PER_ARRAY, ++ .vphba = IMSM_OROM_TOTAL_DISKS_NVME / 2 * IMSM_OROM_VOLUMES_PER_ARRAY, ++ .attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK, ++ }; ++ nvme_orom = add_orom(&nvme_orom_compat); ++ } ++ add_orom_device_id(nvme_orom, hba->dev_id); ++ return nvme_orom; ++} ++ + const struct imsm_orom *find_imsm_capability(struct sys_dev *hba) + { + const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id); +@@ -504,10 +543,13 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba) + if (cap) + return cap; + ++ if (hba->type == SYS_DEV_NVME) ++ return find_imsm_nvme(hba); + if ((cap = find_imsm_efi(hba)) != NULL) + return cap; + if ((cap = find_imsm_hba_orom(hba)) != NULL) + return cap; ++ + return NULL; + } + +diff --git a/platform-intel.h b/platform-intel.h +index e41f386..6b4ebd8 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -23,6 +23,7 @@ + struct imsm_orom { + __u8 signature[4]; + #define IMSM_OROM_SIGNATURE "$VER" ++ #define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM" + __u8 table_ver_major; /* Currently 2 (can change with future revs) */ + __u8 table_ver_minor; /* Currently 2 (can change with future revs) */ + __u16 major_ver; /* Example: 8 as in 8.6.0.1020 */ +@@ -60,12 +61,15 @@ struct imsm_orom { + #define IMSM_OROM_SSS_64MB (1 << 15) + __u16 dpa; /* Disks Per Array supported */ + #define IMSM_OROM_DISKS_PER_ARRAY 6 ++ #define IMSM_OROM_DISKS_PER_ARRAY_NVME 12 + __u16 tds; /* Total Disks Supported */ + #define IMSM_OROM_TOTAL_DISKS 6 ++ #define IMSM_OROM_TOTAL_DISKS_NVME 12 + __u8 vpa; /* # Volumes Per Array supported */ + #define IMSM_OROM_VOLUMES_PER_ARRAY 2 + __u8 vphba; /* # Volumes Per Host Bus Adapter supported */ + #define IMSM_OROM_VOLUMES_PER_HBA 4 ++ #define IMSM_OROM_VOLUMES_PER_HBA_NVME 4 + /* Attributes supported. This should map to the + * attributes in the MPB. Also, lower 16 bits + * should match/duplicate RLC bits above. +@@ -173,6 +177,7 @@ enum sys_dev_type { + SYS_DEV_UNKNOWN = 0, + SYS_DEV_SAS, + SYS_DEV_SATA, ++ SYS_DEV_NVME, + SYS_DEV_MAX + }; + +diff --git a/super-intel.c b/super-intel.c +index dabf011..d2ee1c6 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -509,7 +509,8 @@ struct imsm_update_add_remove_disk { + static const char *_sys_dev_type[] = { + [SYS_DEV_UNKNOWN] = "Unknown", + [SYS_DEV_SAS] = "SAS", +- [SYS_DEV_SATA] = "SATA" ++ [SYS_DEV_SATA] = "SATA", ++ [SYS_DEV_NVME] = "NVMe" + }; + + const char *get_sys_dev_type(enum sys_dev_type type) +@@ -559,7 +560,7 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device + + hba = super->hba; + /* Intel metadata allows for all disks attached to the same type HBA. +- * Do not sypport odf HBA types mixing ++ * Do not support HBA types mixing + */ + if (device->type != hba->type) + return 2; +@@ -3841,9 +3842,9 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de + " but the container is assigned to Intel(R) " + "%s RAID controller (", + devname, +- hba_name->path, ++ get_sys_dev_type(hba_name->type), + hba_name->pci_id ? : "Err!", +- get_sys_dev_type(hba_name->type)); ++ get_sys_dev_type(super->hba->type)); + + while (hba) { + fprintf(stderr, "%s", hba->pci_id ? : "Err!"); +@@ -3860,6 +3861,7 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de + super->orom = find_imsm_capability(hba_name); + if (!super->orom) + return 3; ++ + return 0; + } + +@@ -5916,6 +5918,7 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, + pr_vrb(": platform does not support a volume size over 2TB\n"); + return 0; + } ++ + return 1; + } + +-- +2.4.3 + diff --git a/SOURCES/mdadm-3.3.2-imsm-detail-platform-improvements.patch b/SOURCES/mdadm-3.3.2-imsm-detail-platform-improvements.patch new file mode 100644 index 0000000..bfbd610 --- /dev/null +++ b/SOURCES/mdadm-3.3.2-imsm-detail-platform-improvements.patch @@ -0,0 +1,299 @@ +From 0858eccf86e9b3611d711717ec65a042f5c7ff9f Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Wed, 19 Nov 2014 13:53:29 +0100 +Subject: [PATCH] imsm: detail-platform improvements + +Print platform details per OROM, not per controller, differentiate +RST(e) platforms from legacy IMSM, print NVMe device paths, adjust port +printing to newer sysfs path. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: Pawel Baldysiak +Signed-off-by: NeilBrown +--- + platform-intel.c | 26 ++++++++++------ + platform-intel.h | 23 ++++++++++++++ + super-intel.c | 93 ++++++++++++++++++++++++++++++++++++++------------------ + 3 files changed, 103 insertions(+), 39 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index ae72827..54ef37f 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -134,6 +134,16 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + static struct sys_dev *intel_devices=NULL; + static time_t valid_time = 0; + ++struct sys_dev *device_by_id(__u16 device_id) ++{ ++ struct sys_dev *iter; ++ ++ for (iter = intel_devices; iter != NULL; iter = iter->next) ++ if (iter->dev_id == device_id) ++ return iter; ++ return NULL; ++} ++ + static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val) + { + char path[strlen(dev_path) + strlen(entry) + 2]; +@@ -219,18 +229,13 @@ struct pciExpDataStructFormat { + __u16 devListOffset; + } __attribute__ ((packed)); + +-struct devid_list { +- __u16 devid; +- struct devid_list *next; +-}; +- +-struct orom_entry { +- struct imsm_orom orom; +- struct devid_list *devid_list; +-}; +- + static struct orom_entry oroms[SYS_DEV_MAX]; + ++const struct orom_entry *get_oroms(void) ++{ ++ return (const struct orom_entry *)&oroms; ++} ++ + const struct imsm_orom *get_orom_by_device_id(__u16 dev_id) + { + int i; +@@ -529,6 +534,7 @@ const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba) + .vpa = IMSM_OROM_VOLUMES_PER_ARRAY, + .vphba = IMSM_OROM_TOTAL_DISKS_NVME / 2 * IMSM_OROM_VOLUMES_PER_ARRAY, + .attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK, ++ .driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem + }; + nvme_orom = add_orom(&nvme_orom_compat); + } +diff --git a/platform-intel.h b/platform-intel.h +index 6b4ebd8..3e85d44 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -173,6 +173,17 @@ static inline int fls(int x) + return r; + } + ++static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom) ++{ ++ return !!(orom->driver_features & IMSM_OROM_CAPABILITIES_EnterpriseSystem); ++} ++ ++static inline int imsm_orom_is_nvme(const struct imsm_orom *orom) ++{ ++ return memcmp(orom->signature, IMSM_NVME_OROM_COMPAT_SIGNATURE, ++ sizeof(orom->signature)) == 0; ++} ++ + enum sys_dev_type { + SYS_DEV_UNKNOWN = 0, + SYS_DEV_SAS, +@@ -194,6 +205,16 @@ struct efi_guid { + __u8 b[16]; + }; + ++struct devid_list { ++ __u16 devid; ++ struct devid_list *next; ++}; ++ ++struct orom_entry { ++ struct imsm_orom orom; ++ struct devid_list *devid_list; ++}; ++ + static inline char *guid_str(char *buf, struct efi_guid guid) + { + sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" +@@ -215,4 +236,6 @@ int devt_attached_to_hba(dev_t dev, const char *hba_path); + char *devt_to_devpath(dev_t dev); + int path_attached_to_hba(const char *disk_path, const char *hba_path); + const char *get_sys_dev_type(enum sys_dev_type); ++const struct orom_entry * get_oroms(void); + const struct imsm_orom *get_orom_by_device_id(__u16 device_id); ++struct sys_dev *device_by_id(__u16 device_id); +diff --git a/super-intel.c b/super-intel.c +index d2ee1c6..4c53019 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1709,7 +1709,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + break; + } + *c = '\0'; +- if (sscanf(&path[hba_len], "host%d", &port) == 1) ++ if ((sscanf(&path[hba_len], "ata%d", &port) == 1) || ++ ((sscanf(&path[hba_len], "host%d", &port) == 1))) + port -= host_base; + else { + if (verbose > 0) { +@@ -1768,6 +1769,8 @@ static void print_found_intel_controllers(struct sys_dev *elem) + fprintf(stderr, "SATA "); + else if (elem->type == SYS_DEV_SAS) + fprintf(stderr, "SAS "); ++ else if (elem->type == SYS_DEV_NVME) ++ fprintf(stderr, "NVMe "); + fprintf(stderr, "RAID controller"); + if (elem->pci_id) + fprintf(stderr, " at %s", elem->pci_id); +@@ -1789,7 +1792,8 @@ static int ahci_get_port_count(const char *hba_path, int *port_count) + for (ent = readdir(dir); ent; ent = readdir(dir)) { + int host; + +- if (sscanf(ent->d_name, "host%d", &host) != 1) ++ if ((sscanf(ent->d_name, "ata%d", &host) != 1) && ++ ((sscanf(ent->d_name, "host%d", &host) != 1))) + continue; + if (*port_count == 0) + host_base = host; +@@ -1805,9 +1809,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count) + + static void print_imsm_capability(const struct imsm_orom *orom) + { +- printf(" Platform : Intel(R) Matrix Storage Manager\n"); +- printf(" Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, +- orom->hotfix_ver, orom->build); ++ printf(" Platform : Intel(R) "); ++ if (orom->capabilities == 0 && orom->driver_features == 0) ++ printf("Matrix Storage Manager\n"); ++ else ++ printf("Rapid Storage Technology%s\n", ++ imsm_orom_is_enterprise(orom) ? " enterprise" : ""); ++ if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) ++ printf(" Version : %d.%d.%d.%d\n", orom->major_ver, ++ orom->minor_ver, orom->hotfix_ver, orom->build); + printf(" RAID Levels :%s%s%s%s%s\n", + imsm_orom_has_raid0(orom) ? " raid0" : "", + imsm_orom_has_raid1(orom) ? " raid1" : "", +@@ -1836,16 +1846,18 @@ static void print_imsm_capability(const struct imsm_orom *orom) + printf(" 2TB disks :%s supported\n", + (orom->attr & IMSM_OROM_ATTR_2TB_DISK)?"":" not"); + printf(" Max Disks : %d\n", orom->tds); +- printf(" Max Volumes : %d per array, %d per controller\n", +- orom->vpa, orom->vphba); ++ printf(" Max Volumes : %d per array, %d per %s\n", ++ orom->vpa, orom->vphba, ++ imsm_orom_is_nvme(orom) ? "platform" : "controller"); + return; + } + + static void print_imsm_capability_export(const struct imsm_orom *orom) + { + printf("MD_FIRMWARE_TYPE=imsm\n"); +- printf("IMSM_VERSION=%d.%d.%d.%d\n",orom->major_ver, orom->minor_ver, +- orom->hotfix_ver, orom->build); ++ if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) ++ printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, ++ orom->hotfix_ver, orom->build); + printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n", + imsm_orom_has_raid0(orom) ? "raid0 " : "", + imsm_orom_has_raid1(orom) ? "raid1 " : "", +@@ -1889,7 +1901,6 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + * platform capabilities. If raid support is disabled in the BIOS the + * option-rom capability structure will not be available. + */ +- const struct imsm_orom *orom; + struct sys_dev *list, *hba; + int host_base = 0; + int port_count = 0; +@@ -1922,15 +1933,42 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + print_found_intel_controllers(list); + + for (hba = list; hba; hba = hba->next) { +- if (controller_path && (compare_paths(hba->path,controller_path) != 0)) ++ if (controller_path && (compare_paths(hba->path, controller_path) != 0)) + continue; +- orom = find_imsm_capability(hba); +- if (!orom) ++ if (!find_imsm_capability(hba)) { + pr_err("imsm capabilities not found for controller: %s (type %s)\n", + hba->path, get_sys_dev_type(hba->type)); +- else { +- result = 0; +- print_imsm_capability(orom); ++ continue; ++ } ++ result = 0; ++ } ++ ++ if (controller_path && result == 1) { ++ pr_err("no active Intel(R) RAID controller found under %s\n", ++ controller_path); ++ return result; ++ } ++ ++ const struct orom_entry *oroms = get_oroms(); ++ int i; ++ ++ for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++) { ++ print_imsm_capability(&oroms[i].orom); ++ ++ if (imsm_orom_is_nvme(&oroms[i].orom)) { ++ for (hba = list; hba; hba = hba->next) { ++ if (hba->type == SYS_DEV_NVME) ++ printf(" NVMe Device : %s\n", hba->path); ++ } ++ continue; ++ } ++ ++ struct devid_list *devid; ++ for (devid = oroms[i].devid_list; devid; devid = devid->next) { ++ hba = device_by_id(devid->devid); ++ if (!hba) ++ continue; ++ + printf(" I/O Controller : %s (%s)\n", + hba->path, get_sys_dev_type(hba->type)); + if (hba->type == SYS_DEV_SATA) { +@@ -1943,18 +1981,14 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + } + } + } ++ printf("\n"); + } + +- if (controller_path && result == 1) +- pr_err("no active Intel(R) RAID " +- "controller found under %s\n",controller_path); +- + return result; + } + + static int export_detail_platform_imsm(int verbose, char *controller_path) + { +- const struct imsm_orom *orom; + struct sys_dev *list, *hba; + int result=1; + +@@ -1969,17 +2003,18 @@ static int export_detail_platform_imsm(int verbose, char *controller_path) + for (hba = list; hba; hba = hba->next) { + if (controller_path && (compare_paths(hba->path,controller_path) != 0)) + continue; +- orom = find_imsm_capability(hba); +- if (!orom) { +- if (verbose > 0) +- pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path); +- } +- else { +- print_imsm_capability_export(orom); ++ if (!find_imsm_capability(hba) && verbose > 0) ++ pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path); ++ else + result = 0; +- } + } + ++ const struct orom_entry *oroms = get_oroms(); ++ int i; ++ ++ for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++) ++ print_imsm_capability_export(&oroms[i].orom); ++ + return result; + } + +-- +2.4.3 + diff --git a/SOURCES/mdadm-3.3.2-imsm-support-for-OROMs-shared-by-multiple-HBAs.patch b/SOURCES/mdadm-3.3.2-imsm-support-for-OROMs-shared-by-multiple-HBAs.patch new file mode 100644 index 0000000..10d58ae --- /dev/null +++ b/SOURCES/mdadm-3.3.2-imsm-support-for-OROMs-shared-by-multiple-HBAs.patch @@ -0,0 +1,644 @@ +From 6b781d331bf52b01b9bafa6409ffb400f8c62895 Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Wed, 19 Nov 2014 13:53:26 +0100 +Subject: [PATCH] imsm: support for OROMs shared by multiple HBAs + +The IMSM platform code was based on an assumption that the OROM or UEFI +capability structure (represented by struct imsm_orom) always belongs to +only one HBA. This assumption is no longer valid, because of newer +platforms with dual AHCI HBAs. Each HBA can have a separate OROM, but +some versions have a combined OROM for both HBAs. + +This patch implements this HBA-OROM relationship in struct orom_entry, +which matches an OROM with a list of HBA PCI ids. All the detected +orom_entries are stored and retrieved using a global array and the +functions add_orom(), add_orom_device_id() and get_orom_by_device_id(). +This replaces the arrays: imsm_orom, populated_orom, imsm_efi, +populated_efi. + +The scan() function is extended to find all HBAs for an OROM. The list +of their device ids is retrieved from the PCI Expansion ROM Data +Structure, hence the additional field devListOffset in struct +pciExpDataStructFormat. + +In UEFI mode we can't read the PCI Expansion ROM Data Structure and the +imsm_orom structures are stored in UEFI variables. They do not provide a +similar device id list, so we also check the HBA PCI class to make sure +that the HBA has RAID mode enabled. + +In super-intel.c there are changes which allow spanning of IMSM +containers over HBAs of the same type, but only if the HBAs share the +same OROM. This is done by comparing imsm_orom pointers, which (outside +of platform-intel.c) always point to the global array containing all the +detected oroms. Additional warnings are added to +validate_container_imsm() to warn about potentially dangerous operations +in all the possible cases, e.g. when an array is assembled using disks +attached to HBAs with separate OROMs. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: NeilBrown +--- + platform-intel.c | 248 ++++++++++++++++++++++++++++++++----------------------- + platform-intel.h | 5 +- + super-intel.c | 134 +++++++++++++++++++++--------- + 3 files changed, 243 insertions(+), 144 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index f347382..f779d02 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -59,6 +59,7 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + struct sys_dev *list = NULL; + enum sys_dev_type type; + unsigned long long dev_id; ++ unsigned long long class; + + if (strcmp(driver, "isci") == 0) + type = SYS_DEV_SAS; +@@ -99,6 +100,9 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + if (devpath_to_ll(path, "device", &dev_id) != 0) + continue; + ++ if (devpath_to_ll(path, "class", &class) != 0) ++ continue; ++ + /* start / add list entry */ + if (!head) { + head = xmalloc(sizeof(*head)); +@@ -114,6 +118,7 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + } + + list->dev_id = (__u16) dev_id; ++ list->class = (__u32) class; + list->type = type; + list->path = realpath(path, NULL); + list->next = NULL; +@@ -127,16 +132,6 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + static struct sys_dev *intel_devices=NULL; + static time_t valid_time = 0; + +-static enum sys_dev_type device_type_by_id(__u16 device_id) +-{ +- struct sys_dev *iter; +- +- for(iter = intel_devices; iter != NULL; iter = iter->next) +- if (iter->dev_id == device_id) +- return iter->type; +- return SYS_DEV_UNKNOWN; +-} +- + static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val) + { + char path[strlen(dev_path) + strlen(entry) + 2]; +@@ -209,16 +204,79 @@ struct pciExpDataStructFormat { + __u8 ver[4]; + __u16 vendorID; + __u16 deviceID; ++ __u16 devListOffset; + } __attribute__ ((packed)); + +-static struct imsm_orom imsm_orom[SYS_DEV_MAX]; +-static int populated_orom[SYS_DEV_MAX]; ++struct devid_list { ++ __u16 devid; ++ struct devid_list *next; ++}; ++ ++struct orom_entry { ++ struct imsm_orom orom; ++ struct devid_list *devid_list; ++}; ++ ++static struct orom_entry oroms[SYS_DEV_MAX]; ++ ++const struct imsm_orom *get_orom_by_device_id(__u16 dev_id) ++{ ++ int i; ++ struct devid_list *list; ++ ++ for (i = 0; i < SYS_DEV_MAX; i++) { ++ for (list = oroms[i].devid_list; list; list = list->next) { ++ if (list->devid == dev_id) ++ return &oroms[i].orom; ++ } ++ } ++ return NULL; ++} ++ ++static const struct imsm_orom *add_orom(const struct imsm_orom *orom) ++{ ++ int i; ++ ++ for (i = 0; i < SYS_DEV_MAX; i++) { ++ if (&oroms[i].orom == orom) ++ return orom; ++ if (oroms[i].orom.signature[0] == 0) { ++ oroms[i].orom = *orom; ++ return &oroms[i].orom; ++ } ++ } ++ return NULL; ++} ++ ++static void add_orom_device_id(const struct imsm_orom *orom, __u16 dev_id) ++{ ++ int i; ++ struct devid_list *list; ++ struct devid_list *prev = NULL; ++ ++ for (i = 0; i < SYS_DEV_MAX; i++) { ++ if (&oroms[i].orom == orom) { ++ for (list = oroms[i].devid_list; list; prev = list, list = list->next) { ++ if (list->devid == dev_id) ++ return; ++ } ++ list = xmalloc(sizeof(struct devid_list)); ++ list->devid = dev_id; ++ list->next = NULL; ++ ++ if (prev == NULL) ++ oroms[i].devid_list = list; ++ else ++ prev->next = list; ++ return; ++ } ++ } ++} + + static int scan(const void *start, const void *end, const void *data) + { + int offset; +- const struct imsm_orom *imsm_mem; +- int dev; ++ const struct imsm_orom *imsm_mem = NULL; + int len = (end - start); + struct pciExpDataStructFormat *ptr= (struct pciExpDataStructFormat *)data; + +@@ -231,81 +289,83 @@ static int scan(const void *start, const void *end, const void *data) + (ulong) __le16_to_cpu(ptr->vendorID), + (ulong) __le16_to_cpu(ptr->deviceID)); + +- if (__le16_to_cpu(ptr->vendorID) == 0x8086) { +- /* serach attached intel devices by device id from OROM */ +- dev = device_type_by_id(__le16_to_cpu(ptr->deviceID)); +- if (dev == SYS_DEV_UNKNOWN) +- return 0; +- } +- else ++ if (__le16_to_cpu(ptr->vendorID) != 0x8086) + return 0; + + for (offset = 0; offset < len; offset += 4) { +- imsm_mem = start + offset; +- if ((memcmp(imsm_mem->signature, "$VER", 4) == 0)) { +- imsm_orom[dev] = *imsm_mem; +- populated_orom[dev] = 1; +- return populated_orom[SYS_DEV_SATA] && populated_orom[SYS_DEV_SAS]; ++ const void *mem = start + offset; ++ ++ if ((memcmp(mem, IMSM_OROM_SIGNATURE, 4) == 0)) { ++ imsm_mem = mem; ++ break; + } + } ++ ++ if (!imsm_mem) ++ return 0; ++ ++ const struct imsm_orom *orom = add_orom(imsm_mem); ++ ++ if (ptr->devListOffset) { ++ const __u16 *dev_list = (void *)ptr + ptr->devListOffset; ++ int i; ++ ++ for (i = 0; dev_list[i] != 0; i++) ++ add_orom_device_id(orom, dev_list[i]); ++ } else { ++ add_orom_device_id(orom, __le16_to_cpu(ptr->deviceID)); ++ } ++ + return 0; + } + +-const struct imsm_orom *imsm_platform_test(enum sys_dev_type hba_id, int *populated, +- struct imsm_orom *imsm_orom) ++const struct imsm_orom *imsm_platform_test(struct sys_dev *hba) + { +- memset(imsm_orom, 0, sizeof(*imsm_orom)); +- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | +- IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5; +- imsm_orom->sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB | +- IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB | +- IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB | +- IMSM_OROM_SSS_256kB | IMSM_OROM_SSS_512kB | +- IMSM_OROM_SSS_1MB | IMSM_OROM_SSS_2MB; +- imsm_orom->dpa = IMSM_OROM_DISKS_PER_ARRAY; +- imsm_orom->tds = IMSM_OROM_TOTAL_DISKS; +- imsm_orom->vpa = IMSM_OROM_VOLUMES_PER_ARRAY; +- imsm_orom->vphba = IMSM_OROM_VOLUMES_PER_HBA; +- imsm_orom->attr = imsm_orom->rlc | IMSM_OROM_ATTR_ChecksumVerify; +- *populated = 1; ++ struct imsm_orom orom = { ++ .signature = IMSM_OROM_SIGNATURE, ++ .rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | ++ IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5, ++ .sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB | ++ IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB | ++ IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB | ++ IMSM_OROM_SSS_256kB | IMSM_OROM_SSS_512kB | ++ IMSM_OROM_SSS_1MB | IMSM_OROM_SSS_2MB, ++ .dpa = IMSM_OROM_DISKS_PER_ARRAY, ++ .tds = IMSM_OROM_TOTAL_DISKS, ++ .vpa = IMSM_OROM_VOLUMES_PER_ARRAY, ++ .vphba = IMSM_OROM_VOLUMES_PER_HBA ++ }; ++ orom.attr = orom.rlc | IMSM_OROM_ATTR_ChecksumVerify; + + if (check_env("IMSM_TEST_OROM_NORAID5")) { +- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | ++ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | + IMSM_OROM_RLC_RAID10; + } +- if (check_env("IMSM_TEST_AHCI_EFI_NORAID5") && (hba_id == SYS_DEV_SAS)) { +- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | ++ if (check_env("IMSM_TEST_AHCI_EFI_NORAID5") && (hba->type == SYS_DEV_SAS)) { ++ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | + IMSM_OROM_RLC_RAID10; + } +- if (check_env("IMSM_TEST_SCU_EFI_NORAID5") && (hba_id == SYS_DEV_SATA)) { +- imsm_orom->rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | ++ if (check_env("IMSM_TEST_SCU_EFI_NORAID5") && (hba->type == SYS_DEV_SATA)) { ++ orom.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 | + IMSM_OROM_RLC_RAID10; + } + +- return imsm_orom; ++ const struct imsm_orom *ret = add_orom(&orom); ++ ++ add_orom_device_id(ret, hba->dev_id); ++ ++ return ret; + } + +-static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id) ++static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + { + unsigned long align; + +- if (hba_id >= SYS_DEV_MAX) +- return NULL; ++ if (check_env("IMSM_TEST_OROM")) ++ return imsm_platform_test(hba); + +- /* it's static data so we only need to read it once */ +- if (populated_orom[hba_id]) { +- dprintf("OROM CAP: %p, pid: %d pop: %d\n", +- &imsm_orom[hba_id], (int) getpid(), populated_orom[hba_id]); +- return &imsm_orom[hba_id]; +- } +- if (check_env("IMSM_TEST_OROM")) { +- dprintf("OROM CAP: %p, pid: %d pop: %d\n", +- &imsm_orom[hba_id], (int) getpid(), populated_orom[hba_id]); +- return imsm_platform_test(hba_id, &populated_orom[hba_id], &imsm_orom[hba_id]); +- } + /* return empty OROM capabilities in EFI test mode */ +- if (check_env("IMSM_TEST_AHCI_EFI") || +- check_env("IMSM_TEST_SCU_EFI")) ++ if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI")) + return NULL; + + find_intel_devices(); +@@ -325,9 +385,7 @@ static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id) + scan_adapter_roms(scan); + probe_roms_exit(); + +- if (populated_orom[hba_id]) +- return &imsm_orom[hba_id]; +- return NULL; ++ return get_orom_by_device_id(hba->dev_id); + } + + #define GUID_STR_MAX 37 /* according to GUID format: +@@ -347,9 +405,7 @@ static const struct imsm_orom *find_imsm_hba_orom(enum sys_dev_type hba_id) + #define VENDOR_GUID \ + EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6) + +-int populated_efi[SYS_DEV_MAX] = { 0, 0 }; +- +-static struct imsm_orom imsm_efi[SYS_DEV_MAX]; ++#define PCI_CLASS_RAID_CNTRL 0x010400 + + int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struct efi_guid guid) + { +@@ -395,54 +451,40 @@ int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struc + return 0; + } + +-const struct imsm_orom *find_imsm_efi(enum sys_dev_type hba_id) ++const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + { +- if (hba_id >= SYS_DEV_MAX) +- return NULL; ++ struct imsm_orom orom; ++ const struct imsm_orom *ret; + +- dprintf("EFI CAP: %p, pid: %d pop: %d\n", +- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]); ++ if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI")) ++ return imsm_platform_test(hba); + +- /* it's static data so we only need to read it once */ +- if (populated_efi[hba_id]) { +- dprintf("EFI CAP: %p, pid: %d pop: %d\n", +- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]); +- return &imsm_efi[hba_id]; +- } +- if (check_env("IMSM_TEST_AHCI_EFI") || +- check_env("IMSM_TEST_SCU_EFI")) { +- dprintf("OROM CAP: %p, pid: %d pop: %d\n", +- &imsm_efi[hba_id], (int) getpid(), populated_efi[hba_id]); +- return imsm_platform_test(hba_id, &populated_efi[hba_id], &imsm_efi[hba_id]); +- } + /* OROM test is set, return that there is no EFI capabilities */ + if (check_env("IMSM_TEST_OROM")) + return NULL; + +- if (read_efi_variable(&imsm_efi[hba_id], sizeof(imsm_efi[0]), hba_id == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID)) { +- populated_efi[hba_id] = 0; ++ if (hba->type == SYS_DEV_SATA && hba->class != PCI_CLASS_RAID_CNTRL) + return NULL; +- } + +- populated_efi[hba_id] = 1; +- return &imsm_efi[hba_id]; +-} ++ if (read_efi_variable(&orom, sizeof(orom), hba->type == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID)) ++ return NULL; + +-/* +- * backward interface compatibility +- */ +-const struct imsm_orom *find_imsm_orom(void) +-{ +- return find_imsm_hba_orom(SYS_DEV_SATA); ++ ret = add_orom(&orom); ++ add_orom_device_id(ret, hba->dev_id); ++ ++ return ret; + } + +-const struct imsm_orom *find_imsm_capability(enum sys_dev_type hba_id) ++const struct imsm_orom *find_imsm_capability(struct sys_dev *hba) + { +- const struct imsm_orom *cap=NULL; ++ const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id); ++ ++ if (cap) ++ return cap; + +- if ((cap = find_imsm_efi(hba_id)) != NULL) ++ if ((cap = find_imsm_efi(hba)) != NULL) + return cap; +- if ((cap = find_imsm_hba_orom(hba_id)) != NULL) ++ if ((cap = find_imsm_hba_orom(hba)) != NULL) + return cap; + return NULL; + } +diff --git a/platform-intel.h b/platform-intel.h +index 8226be3..e41f386 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -22,6 +22,7 @@ + /* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */ + struct imsm_orom { + __u8 signature[4]; ++ #define IMSM_OROM_SIGNATURE "$VER" + __u8 table_ver_major; /* Currently 2 (can change with future revs) */ + __u8 table_ver_minor; /* Currently 2 (can change with future revs) */ + __u16 major_ver; /* Example: 8 as in 8.6.0.1020 */ +@@ -180,6 +181,7 @@ struct sys_dev { + char *path; + char *pci_id; + __u16 dev_id; ++ __u32 class; + struct sys_dev *next; + }; + +@@ -201,10 +203,11 @@ static inline char *guid_str(char *buf, struct efi_guid guid) + char *diskfd_to_devpath(int fd); + struct sys_dev *find_driver_devices(const char *bus, const char *driver); + struct sys_dev *find_intel_devices(void); +-const struct imsm_orom *find_imsm_capability(enum sys_dev_type hba_id); ++const struct imsm_orom *find_imsm_capability(struct sys_dev *hba); + const struct imsm_orom *find_imsm_orom(void); + int disk_attached_to_hba(int fd, const char *hba_path); + int devt_attached_to_hba(dev_t dev, const char *hba_path); + char *devt_to_devpath(dev_t dev); + int path_attached_to_hba(const char *disk_path, const char *hba_path); + const char *get_sys_dev_type(enum sys_dev_type); ++const struct imsm_orom *get_orom_by_device_id(__u16 device_id); +diff --git a/super-intel.c b/super-intel.c +index e28ac7d..dabf011 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -555,11 +555,26 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device + if (super->hba == NULL) { + super->hba = alloc_intel_hba(device); + return 1; +- } else +- /* IMSM metadata disallows to attach disks to multiple +- * controllers. +- */ ++ } ++ ++ hba = super->hba; ++ /* Intel metadata allows for all disks attached to the same type HBA. ++ * Do not sypport odf HBA types mixing ++ */ ++ if (device->type != hba->type) ++ return 2; ++ ++ /* Multiple same type HBAs can be used if they share the same OROM */ ++ const struct imsm_orom *device_orom = get_orom_by_device_id(device->dev_id); ++ ++ if (device_orom != super->orom) + return 2; ++ ++ while (hba->next) ++ hba = hba->next; ++ ++ hba->next = alloc_intel_hba(device); ++ return 1; + } + + static struct sys_dev* find_disk_attached_hba(int fd, const char *devname) +@@ -1886,13 +1901,12 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + if (!list) + return 2; + for (hba = list; hba; hba = hba->next) { +- orom = find_imsm_capability(hba->type); +- if (!orom) { +- result = 2; ++ if (find_imsm_capability(hba)) { ++ result = 0; + break; + } + else +- result = 0; ++ result = 2; + } + return result; + } +@@ -1909,7 +1923,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + for (hba = list; hba; hba = hba->next) { + if (controller_path && (compare_paths(hba->path,controller_path) != 0)) + continue; +- orom = find_imsm_capability(hba->type); ++ orom = find_imsm_capability(hba); + if (!orom) + pr_err("imsm capabilities not found for controller: %s (type %s)\n", + hba->path, get_sys_dev_type(hba->type)); +@@ -1954,7 +1968,7 @@ static int export_detail_platform_imsm(int verbose, char *controller_path) + for (hba = list; hba; hba = hba->next) { + if (controller_path && (compare_paths(hba->path,controller_path) != 0)) + continue; +- orom = find_imsm_capability(hba->type); ++ orom = find_imsm_capability(hba); + if (!orom) { + if (verbose > 0) + pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path); +@@ -3087,13 +3101,18 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst) + * use the same Intel hba + * If not on Intel hba at all, allow anything. + */ +- if (!check_env("IMSM_NO_PLATFORM")) { +- if (first->hba && sec->hba && +- strcmp(first->hba->path, sec->hba->path) != 0) { ++ if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) { ++ if (first->hba->type != sec->hba->type) { ++ fprintf(stderr, ++ "HBAs of devices do not match %s != %s\n", ++ get_sys_dev_type(first->hba->type), ++ get_sys_dev_type(sec->hba->type)); ++ return 3; ++ } ++ if (first->orom != sec->orom) { + fprintf(stderr, +- "HBAs of devices does not match %s != %s\n", +- first->hba ? first->hba->path : NULL, +- sec->hba ? sec->hba->path : NULL); ++ "HBAs of devices do not match %s != %s\n", ++ first->hba->pci_id, sec->hba->pci_id); + return 3; + } + } +@@ -3832,14 +3851,13 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de + fprintf(stderr, ", "); + hba = hba->next; + } +- +- fprintf(stderr, ").\n"); +- cont_err("Mixing devices attached to multiple controllers " +- "is not allowed.\n"); ++ fprintf(stderr, ").\n" ++ " Mixing devices attached to different controllers " ++ "is not allowed.\n"); + } + return 2; + } +- super->orom = find_imsm_capability(hba_name->type); ++ super->orom = find_imsm_capability(hba_name); + if (!super->orom) + return 3; + return 0; +@@ -9061,32 +9079,68 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds, + ******************************************************************************/ + int validate_container_imsm(struct mdinfo *info) + { +- if (!check_env("IMSM_NO_PLATFORM")) { +- struct sys_dev *idev; +- struct mdinfo *dev; +- char *hba_path = NULL; +- char *dev_path = devt_to_devpath(makedev(info->disk.major, +- info->disk.minor)); ++ if (check_env("IMSM_NO_PLATFORM")) ++ return 0; + +- for (idev = find_intel_devices(); idev; idev = idev->next) { +- if (strstr(dev_path, idev->path)) { +- hba_path = idev->path; +- break; +- } ++ struct sys_dev *idev; ++ struct sys_dev *hba = NULL; ++ struct sys_dev *intel_devices = find_intel_devices(); ++ char *dev_path = devt_to_devpath(makedev(info->disk.major, ++ info->disk.minor)); ++ ++ for (idev = intel_devices; idev; idev = idev->next) { ++ if (dev_path && strstr(dev_path, idev->path)) { ++ hba = idev; ++ break; + } ++ } ++ if (dev_path) + free(dev_path); + +- if (hba_path) { +- for (dev = info->next; dev; dev = dev->next) { +- if (!devt_attached_to_hba(makedev(dev->disk.major, +- dev->disk.minor), hba_path)) { +- pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n" +- " This operation is not supported and can lead to data loss.\n"); +- return 1; +- } ++ if (!hba) { ++ pr_err("WARNING - Cannot detect HBA for device %s!\n", ++ devid2kname(makedev(info->disk.major, info->disk.minor))); ++ return 1; ++ } ++ ++ const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id); ++ struct mdinfo *dev; ++ ++ for (dev = info->next; dev; dev = dev->next) { ++ dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor)); ++ ++ struct sys_dev *hba2 = NULL; ++ for (idev = intel_devices; idev; idev = idev->next) { ++ if (dev_path && strstr(dev_path, idev->path)) { ++ hba2 = idev; ++ break; + } + } ++ if (dev_path) ++ free(dev_path); ++ ++ const struct imsm_orom *orom2 = hba2 == NULL ? NULL : ++ get_orom_by_device_id(hba2->dev_id); ++ ++ if (hba2 && hba->type != hba2->type) { ++ pr_err("WARNING - HBAs of devices do not match %s != %s\n", ++ get_sys_dev_type(hba->type), get_sys_dev_type(hba2->type)); ++ return 1; ++ } ++ ++ if (orom != orom2) { ++ pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n" ++ " This operation is not supported and can lead to data loss.\n"); ++ return 1; ++ } ++ ++ if (!orom) { ++ pr_err("WARNING - IMSM container assembled with disks under HBAs without IMSM platform support!\n" ++ " This operation is not supported and can lead to data loss.\n"); ++ return 1; ++ } + } ++ + return 0; + } + #ifndef MDASSEMBLE +-- +2.4.3 + diff --git a/SOURCES/mdadm-3.3.2-imsm-support-for-second-and-combined-AHCI-controller.patch b/SOURCES/mdadm-3.3.2-imsm-support-for-second-and-combined-AHCI-controller.patch new file mode 100644 index 0000000..ffa21f8 --- /dev/null +++ b/SOURCES/mdadm-3.3.2-imsm-support-for-second-and-combined-AHCI-controller.patch @@ -0,0 +1,69 @@ +From 81188ef870ead9121d66287eb2ced28a25a1e8d4 Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Wed, 19 Nov 2014 13:53:27 +0100 +Subject: [PATCH] imsm: support for second and combined AHCI controllers in + UEFI mode + +Grantly platform introduces a second AHCI controller (sSATA) and two new +UEFI variables for the RSTe firmware. This patch adds support for those +variables in order to correctly determine IMSM platform capabilities in +UEFI mode. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: NeilBrown +--- + platform-intel.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/platform-intel.c b/platform-intel.c +index f779d02..c5a0aa4 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -401,6 +401,8 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + #define SYS_EFI_VAR_PATH "/sys/firmware/efi/vars" + #define SCU_PROP "RstScuV" + #define AHCI_PROP "RstSataV" ++#define AHCI_SSATA_PROP "RstsSatV" ++#define AHCI_CSATA_PROP "RstCSatV" + + #define VENDOR_GUID \ + EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6) +@@ -455,6 +457,7 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + { + struct imsm_orom orom; + const struct imsm_orom *ret; ++ int err; + + if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI")) + return imsm_platform_test(hba); +@@ -466,7 +469,26 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + if (hba->type == SYS_DEV_SATA && hba->class != PCI_CLASS_RAID_CNTRL) + return NULL; + +- if (read_efi_variable(&orom, sizeof(orom), hba->type == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID)) ++ err = read_efi_variable(&orom, sizeof(orom), hba->type == SYS_DEV_SAS ? SCU_PROP : AHCI_PROP, VENDOR_GUID); ++ ++ /* try to read variable for second AHCI controller */ ++ if (err && hba->type == SYS_DEV_SATA) ++ err = read_efi_variable(&orom, sizeof(orom), AHCI_SSATA_PROP, VENDOR_GUID); ++ ++ /* try to read variable for combined AHCI controllers */ ++ if (err && hba->type == SYS_DEV_SATA) { ++ static const struct imsm_orom *csata; ++ ++ err = read_efi_variable(&orom, sizeof(orom), AHCI_CSATA_PROP, VENDOR_GUID); ++ if (!err) { ++ if (!csata) ++ csata = add_orom(&orom); ++ add_orom_device_id(csata, hba->dev_id); ++ return csata; ++ } ++ } ++ ++ if (err) + return NULL; + + ret = add_orom(&orom); +-- +2.4.3 + diff --git a/SOURCES/mdadm-3.3.2-imsm-use-efivarfs-interface-for-reading-UEFI-variabl.patch b/SOURCES/mdadm-3.3.2-imsm-use-efivarfs-interface-for-reading-UEFI-variabl.patch new file mode 100644 index 0000000..db5a896 --- /dev/null +++ b/SOURCES/mdadm-3.3.2-imsm-use-efivarfs-interface-for-reading-UEFI-variabl.patch @@ -0,0 +1,78 @@ +From 88605db99c00f48bd56ad86718657d54e254be57 Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Thu, 20 Nov 2014 18:56:13 +0100 +Subject: [PATCH] imsm: use efivarfs interface for reading UEFI variables + +Read UEFI variables using the new efivarfs interface, fallback to +sysfs-efivars if that fails. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: NeilBrown +--- + platform-intel.c | 37 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 54ef37f..37274da 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -416,6 +416,7 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + + #define SYS_EFI_VAR_PATH "/sys/firmware/efi/vars" ++#define SYS_EFIVARS_PATH "/sys/firmware/efi/efivars" + #define SCU_PROP "RstScuV" + #define AHCI_PROP "RstSataV" + #define AHCI_SSATA_PROP "RstsSatV" +@@ -426,13 +427,47 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + + #define PCI_CLASS_RAID_CNTRL 0x010400 + +-int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struct efi_guid guid) ++static int read_efi_var(void *buffer, ssize_t buf_size, char *variable_name, struct efi_guid guid) ++{ ++ char path[PATH_MAX]; ++ char buf[GUID_STR_MAX]; ++ int fd; ++ ssize_t n; ++ ++ snprintf(path, PATH_MAX, "%s/%s-%s", SYS_EFIVARS_PATH, variable_name, guid_str(buf, guid)); ++ ++ fd = open(path, O_RDONLY); ++ if (fd < 0) ++ return 1; ++ ++ /* read the variable attributes and ignore it */ ++ n = read(fd, buf, sizeof(__u32)); ++ if (n < 0) { ++ close(fd); ++ return 1; ++ } ++ ++ /* read the variable data */ ++ n = read(fd, buffer, buf_size); ++ close(fd); ++ if (n < buf_size) ++ return 1; ++ ++ return 0; ++} ++ ++static int read_efi_variable(void *buffer, ssize_t buf_size, char *variable_name, struct efi_guid guid) + { + char path[PATH_MAX]; + char buf[GUID_STR_MAX]; + int dfd; + ssize_t n, var_data_len; + ++ /* Try to read the variable using the new efivarfs interface first. ++ * If that fails, fall back to the old sysfs-efivars interface. */ ++ if (!read_efi_var(buffer, buf_size, variable_name, guid)) ++ return 0; ++ + snprintf(path, PATH_MAX, "%s/%s-%s/size", SYS_EFI_VAR_PATH, variable_name, guid_str(buf, guid)); + + dprintf("EFI VAR: path=%s\n", path); +-- +2.4.3 + diff --git a/SOURCES/mdadm.rules b/SOURCES/mdadm.rules index a2c1e18..cc1ed04 100644 --- a/SOURCES/mdadm.rules +++ b/SOURCES/mdadm.rules @@ -55,15 +55,4 @@ LABEL="dm_change_end" KERNEL=="md*", SUBSYSTEM=="block", ENV{ID_FS_TYPE}=="linux_raid_member", \ ACTION=="change", RUN+="/sbin/mdadm -I $env{DEVNAME}" -# In case the initramfs only started some of the arrays in our container, -# run incremental assembly on the container itself. Note: we ran mdadm -# on the container in 64-md-raid.rules, and that's how the MD_LEVEL -# environment variable is already set. If that disappears from the other -# file, we will need to add this line into the middle of the next rule: -# IMPORT{program}="/sbin/mdadm -D --export $tempnode", \ - -SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="md*", \ - ENV{MD_LEVEL}=="container", RUN+="/sbin/mdadm -I $env{DEVNAME}" - - LABEL="md_end" diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec index f9f5146..1bbb37d 100644 --- a/SPECS/mdadm.spec +++ b/SPECS/mdadm.spec @@ -1,7 +1,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm Version: 3.3.2 -Release: 2%{?dist}.1 +Release: 7%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz Source1: mdmonitor.init Source2: raid-check @@ -12,6 +12,13 @@ Source6: mdmonitor.service Source7: mdadm.conf Source8: mdadm_event.conf Patch1: mdadm-3.3.2-IMSM-Clear-migration-record-on-disks-more-often.patch +Patch2: mdadm-3.3.2-fix-resize-of-array-component-size-to-32bits.patch +Patch3: mdadm-3.3.2-imsm-support-for-OROMs-shared-by-multiple-HBAs.patch +Patch4: mdadm-3.3.2-imsm-support-for-second-and-combined-AHCI-controller.patch +Patch5: mdadm-3.3.2-imsm-add-support-for-NVMe-devices.patch +Patch6: mdadm-3.3.2-imsm-detail-platform-improvements.patch +Patch7: mdadm-3.3.2-imsm-use-efivarfs-interface-for-reading-UEFI-variabl.patch +Patch8: mdadm-3.3.2-fix-problem-with-grow-continue.patch # RHEL customization patches Patch96: mdadm-3.3.2-skip-rules.patch Patch97: mdadm-3.3-udev.patch @@ -40,6 +47,13 @@ file can be used to help with some common tasks. %setup -q %patch1 -p1 -b .migration +%patch2 -p1 -b .resize +%patch3 -p1 -b .multihba +%patch4 -p1 -b .secondahci +%patch5 -p1 -b .nvme +%patch6 -p1 -b .detail +%patch7 -p1 -b .efivars +%patch8 -p1 -b .grow # RHEL customization patches %patch96 -p1 -b .rules @@ -106,11 +120,26 @@ rm -rf %{buildroot} /etc/libreport/events.d/* %changelog -* Tue Mar 24 2015 Jes Sorensen - 3.3.2-2.1 -- Z-Stream fix +* Thu Sep 17 2015 Jes Sorensen - 3.3.2-7 +- Fix race condition when assembling IMSM volumes with mdadm -As +- Resolves bz1263205 + +* Thu Sep 17 2015 Xiao Ni - 3.3.2-6 +- Fix issue reshape is stuck +- Resolves rhbz#1246035 + +* Tue Aug 25 2015 Jes Sorensen - 3.3.2-5 +- Add support for IMSM over NVME storage +- Resolves rhbz#1173504 + +* Thu Jul 2 2015 Xiao Ni - 3.3.2-4 +- Fix issue mdadm --grow --size does not work for >2TB +- Resolves rhbz#1236538 + +* Tue Mar 24 2015 Jes Sorensen - 3.3.2-3 - Fix issue where migration record was not always cleared after successful reshape. -- Resolves rhbz#1205325 +- Resolves rhbz#1183724 * Mon Jan 19 2015 Jes Sorensen - 3.3.2-2 - Do not install 64-md-raid-assembly.rules