From cdf6b7786aba2d59f4fdec6ef8e67fe698266949 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Fri, 23 Jul 2021 12:31:42 +0000 Subject: [PATCH] import mdadm-4.2-rc1_3.el8 --- ...-imsm-change-wrong-size-verification.patch | 39 +++ ...ch => 0002-Fix-some-building-errors.patch} | 2 +- ...from-using-stop-with-ambiguous-args.patch} | 2 +- ...neric-method-to-resolve-device-links.patch | 327 +++++++++++++++++ ...0005-imsm-add-devpath_to_char-method.patch | 157 +++++++++ ...imit-support-to-the-lowest-namespace.patch | 329 ++++++++++++++++++ ...date_geometry-when-adding-drive-to-e.patch | 107 ++++++ ...needs-to-specify-int32-for-bitmap_of.patch | 31 ++ ..._open-in-validate-geometry-container.patch | 48 +++ ...ffset-for-4k-disks-in-examine-output.patch | 30 ++ ...ves-line-from-details-for-external-m.patch | 35 ++ ...spares-with-other-arrays-during-RAID.patch | 173 +++++++++ SOURCES/0013-mdadm-Fix-building-errors.patch | 49 +++ ...e-memory-leaks-and-refactor-freeing-.patch | 142 ++++++++ ...ror-handling-for-chunk-size-in-RAID1.patch | 32 ++ SPECS/mdadm.spec | 37 +- 16 files changed, 1535 insertions(+), 5 deletions(-) create mode 100644 SOURCES/0001-imsm-change-wrong-size-verification.patch rename SOURCES/{0001-Fix-some-building-errors.patch => 0002-Fix-some-building-errors.patch} (97%) rename SOURCES/{0002-Prevent-user-from-using-stop-with-ambiguous-args.patch => 0003-Prevent-user-from-using-stop-with-ambiguous-args.patch} (93%) create mode 100644 SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch create mode 100644 SOURCES/0005-imsm-add-devpath_to_char-method.patch create mode 100644 SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch create mode 100644 SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch create mode 100644 SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch create mode 100644 SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch create mode 100644 SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch create mode 100644 SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch create mode 100644 SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch create mode 100644 SOURCES/0013-mdadm-Fix-building-errors.patch create mode 100644 SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch create mode 100644 SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch diff --git a/SOURCES/0001-imsm-change-wrong-size-verification.patch b/SOURCES/0001-imsm-change-wrong-size-verification.patch new file mode 100644 index 0000000..e1731cb --- /dev/null +++ b/SOURCES/0001-imsm-change-wrong-size-verification.patch @@ -0,0 +1,39 @@ +From ff904202a4a6232e0f0dfea31a7c4a34ab08f76e Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 21 Apr 2021 16:50:08 +0200 +Subject: [PATCH 01/15] imsm: change wrong size verification + +Expectation that size is always rounded is incorrect. +Just confirm that size is smaller to be certain that update is safe. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + super-intel.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 876e077..be0313d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11823,12 +11823,12 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index) + if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR) + continue; + +- /* There is a difference, verify that imsm_dev_size is +- * rounded correctly and push update. ++ /* There is a difference, confirm that imsm_dev_size is ++ * smaller and push update. + */ +- if (d_size != round_size_to_mb(d_size, disc_count)) { +- dprintf("imsm: Size of volume %d is not rounded correctly\n", +- i); ++ if (d_size > calc_size) { ++ pr_err("imsm: dev size of subarray %d is incorrect\n", ++ i); + goto exit; + } + memset(&geo, 0, sizeof(struct geo_params)); +-- +2.7.5 + diff --git a/SOURCES/0001-Fix-some-building-errors.patch b/SOURCES/0002-Fix-some-building-errors.patch similarity index 97% rename from SOURCES/0001-Fix-some-building-errors.patch rename to SOURCES/0002-Fix-some-building-errors.patch index 16cf5cf..cff64c9 100644 --- a/SOURCES/0001-Fix-some-building-errors.patch +++ b/SOURCES/0002-Fix-some-building-errors.patch @@ -1,7 +1,7 @@ From 83b3de7795d2a421eb6ae4ab97656a250bb898ea Mon Sep 17 00:00:00 2001 From: Xiao Ni Date: Fri, 23 Apr 2021 14:01:30 +0800 -Subject: [PATCH 1/2] Fix some building errors +Subject: [PATCH 02/15] Fix some building errors There are some building errors if treating warning as errors. Fix them in this patch. diff --git a/SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch b/SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch similarity index 93% rename from SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch rename to SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch index 0a052e0..02e3a9b 100644 --- a/SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch +++ b/SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch @@ -1,7 +1,7 @@ From 0530e2e0d8c9ecb5171e70bc48e1a6566f317378 Mon Sep 17 00:00:00 2001 From: Norbert Szulc Date: Wed, 5 May 2021 13:01:02 +0200 -Subject: [PATCH 2/2] Prevent user from using --stop with ambiguous args +Subject: [PATCH 03/15] Prevent user from using --stop with ambiguous args When both --scan and device name is passed to --stop action, then is executed only for given device. Scan is ignored. diff --git a/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch b/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch new file mode 100644 index 0000000..565826c --- /dev/null +++ b/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch @@ -0,0 +1,327 @@ +From 7c798f870900f6f4d4647dd3c88318524d7ccee4 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 17 May 2021 16:39:00 +0200 +Subject: [PATCH 04/15] imsm: add generic method to resolve "device" links + +Each virtual device is linked with parent by "device". This patch adds +possibility to get previous device in sysfs tree. + +Depending on device type, there is a different amount of virutal +layers. The best we can do is allow to directly specify how many +"device" links need to be resolved. This approach also allows to get +previous virtual device, which may contain some attributes. + +Simplify fd2devname, this function doesn't require new functionality and +shall use generic fd2kname. + +For nvme drives represented via nvme-subystem when path to block +device if requested, then return it without translation. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + platform-intel.c | 75 ++++++++++++++++++++++++++++++++++++++------------------ + platform-intel.h | 4 +-- + super-intel.c | 63 ++++++++++++++++++----------------------------- + 3 files changed, 77 insertions(+), 65 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 2da152f..2ed63ed 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -712,28 +712,61 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path) + return rp; + } + +-char *devt_to_devpath(dev_t dev) ++/* Description: Return part or whole realpath for the dev ++ * Parameters: ++ * dev - the device to be quered ++ * dev_level - level of "/device" entries. It allows to caller to access ++ * virtual or physical devices which are on "path" to quered ++ * one. ++ * buf - optional, must be PATH_MAX size. If set, then will be used. ++ */ ++char *devt_to_devpath(dev_t dev, int dev_level, char *buf) + { +- char device[46]; +- char *rp; +- char *buf; ++ char device[PATH_MAX]; ++ char *hw_path; ++ int i; ++ unsigned long device_free_len = sizeof(device) - 1; ++ char dev_str[] = "/device"; ++ unsigned long dev_str_len = strlen(dev_str); ++ ++ snprintf(device, sizeof(device), "/sys/dev/block/%d:%d", major(dev), ++ minor(dev)); ++ ++ /* If caller wants block device, return path to it even if it is exposed ++ * via virtual layer. ++ */ ++ if (dev_level == 0) ++ return realpath(device, buf); + +- sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev)); ++ device_free_len -= strlen(device); ++ for (i = 0; i < dev_level; i++) { ++ if (device_free_len < dev_str_len) ++ return NULL; + +- rp = realpath(device, NULL); +- if (!rp) +- return NULL; ++ strncat(device, dev_str, device_free_len); + +- buf = get_nvme_multipath_dev_hw_path(rp); +- if (buf) { +- free(rp); +- return buf; ++ /* Resolve nvme-subsystem abstraction if needed ++ */ ++ device_free_len -= dev_str_len; ++ if (i == 0) { ++ char rp[PATH_MAX]; ++ ++ if (!realpath(device, rp)) ++ return NULL; ++ hw_path = get_nvme_multipath_dev_hw_path(rp); ++ if (hw_path) { ++ strcpy(device, hw_path); ++ device_free_len = sizeof(device) - ++ strlen(device) - 1; ++ free(hw_path); ++ } ++ } + } + +- return rp; ++ return realpath(device, buf); + } + +-char *diskfd_to_devpath(int fd) ++char *diskfd_to_devpath(int fd, int dev_level, char *buf) + { + /* return the device path for a disk, return NULL on error or fd + * refers to a partition +@@ -745,7 +778,7 @@ char *diskfd_to_devpath(int fd) + if (!S_ISBLK(st.st_mode)) + return NULL; + +- return devt_to_devpath(st.st_rdev); ++ return devt_to_devpath(st.st_rdev, dev_level, buf); + } + + int path_attached_to_hba(const char *disk_path, const char *hba_path) +@@ -770,7 +803,7 @@ int path_attached_to_hba(const char *disk_path, const char *hba_path) + + int devt_attached_to_hba(dev_t dev, const char *hba_path) + { +- char *disk_path = devt_to_devpath(dev); ++ char *disk_path = devt_to_devpath(dev, 1, NULL); + int rc = path_attached_to_hba(disk_path, hba_path); + + if (disk_path) +@@ -781,7 +814,7 @@ int devt_attached_to_hba(dev_t dev, const char *hba_path) + + int disk_attached_to_hba(int fd, const char *hba_path) + { +- char *disk_path = diskfd_to_devpath(fd); ++ char *disk_path = diskfd_to_devpath(fd, 1, NULL); + int rc = path_attached_to_hba(disk_path, hba_path); + + if (disk_path) +@@ -862,15 +895,9 @@ int imsm_is_nvme_supported(int disk_fd, int verbose) + */ + int is_multipath_nvme(int disk_fd) + { +- char path_buf[PATH_MAX]; + char ns_path[PATH_MAX]; +- char *kname = fd2kname(disk_fd); +- +- if (!kname) +- return 0; +- sprintf(path_buf, "/sys/block/%s", kname); + +- if (!realpath(path_buf, ns_path)) ++ if (!diskfd_to_devpath(disk_fd, 0, ns_path)) + return 0; + + if (strncmp(ns_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) == 0) +diff --git a/platform-intel.h b/platform-intel.h +index 8396a0f..f93add5 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -237,7 +237,7 @@ static inline char *guid_str(char *buf, struct efi_guid guid) + } + + char *get_nvme_multipath_dev_hw_path(const char *dev_path); +-char *diskfd_to_devpath(int fd); ++char *diskfd_to_devpath(int fd, int dev_level, char *buf); + __u16 devpath_to_vendor(const char *dev_path); + struct sys_dev *find_driver_devices(const char *bus, const char *driver); + struct sys_dev *find_intel_devices(void); +@@ -245,7 +245,7 @@ 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); ++char *devt_to_devpath(dev_t dev, int dev_level, char *buf); + 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_orom_entry_by_device_id(__u16 dev_id); +diff --git a/super-intel.c b/super-intel.c +index 5469912..cff8550 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -694,7 +694,7 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname) + if (fd < 0) + disk_path = (char *) devname; + else +- disk_path = diskfd_to_devpath(fd); ++ disk_path = diskfd_to_devpath(fd, 1, NULL); + + if (!disk_path) + return 0; +@@ -2253,7 +2253,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + + if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2) + continue; +- path = devt_to_devpath(makedev(major, minor)); ++ path = devt_to_devpath(makedev(major, minor), 1, NULL); + if (!path) + continue; + if (!path_attached_to_hba(path, hba_path)) { +@@ -2407,7 +2407,7 @@ static int print_nvme_info(struct sys_dev *hba) + continue; + } + +- device_path = diskfd_to_devpath(fd); ++ device_path = diskfd_to_devpath(fd, 1, NULL); + if (!device_path) { + close(fd); + continue; +@@ -4015,28 +4015,13 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst, + + static void fd2devname(int fd, char *name) + { +- struct stat st; +- char path[256]; +- char dname[PATH_MAX]; + char *nm; +- int rv; +- +- name[0] = '\0'; +- if (fstat(fd, &st) != 0) +- return; +- sprintf(path, "/sys/dev/block/%d:%d", +- major(st.st_rdev), minor(st.st_rdev)); + +- rv = readlink(path, dname, sizeof(dname)-1); +- if (rv <= 0) ++ nm = fd2kname(fd); ++ if (!nm) + return; + +- dname[rv] = '\0'; +- nm = strrchr(dname, '/'); +- if (nm) { +- nm++; +- snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm); +- } ++ snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm); + } + + static int nvme_get_serial(int fd, void *buf, size_t buf_len) +@@ -5941,29 +5926,23 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + free(dd); + abort(); + } ++ + if (super->hba && ((super->hba->type == SYS_DEV_NVME) || + (super->hba->type == SYS_DEV_VMD))) { + int i; +- char *devpath = diskfd_to_devpath(fd); +- char controller_path[PATH_MAX]; +- char *controller_name; ++ char cntrl_path[PATH_MAX]; ++ char *cntrl_name; ++ char pci_dev_path[PATH_MAX]; + +- if (!devpath) { +- pr_err("failed to get devpath, aborting\n"); ++ if (!diskfd_to_devpath(fd, 2, pci_dev_path) || ++ !diskfd_to_devpath(fd, 1, cntrl_path)) { ++ pr_err("failed to get dev_path, aborting\n"); + if (dd->devname) + free(dd->devname); + free(dd); + return 1; + } + +- snprintf(controller_path, PATH_MAX-1, "%s/device", devpath); +- +- controller_name = basename(devpath); +- if (is_multipath_nvme(fd)) +- pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", controller_name); +- +- free(devpath); +- + if (!imsm_is_nvme_supported(dd->fd, 1)) { + if (dd->devname) + free(dd->devname); +@@ -5971,7 +5950,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + return 1; + } + +- if (devpath_to_vendor(controller_path) == 0x8086) { ++ cntrl_name = basename(cntrl_path); ++ if (is_multipath_nvme(fd)) ++ pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", ++ cntrl_name); ++ ++ if (devpath_to_vendor(pci_dev_path) == 0x8086) { + /* + * If Intel's NVMe drive has serial ended with + * "-A","-B","-1" or "-2" it means that this is "x8" +@@ -6985,7 +6969,7 @@ get_devices(const char *hba_path) + char *path = NULL; + if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2) + continue; +- path = devt_to_devpath(makedev(major, minor)); ++ path = devt_to_devpath(makedev(major, minor), 1, NULL); + if (!path) + continue; + if (!path_attached_to_hba(path, hba_path)) { +@@ -10648,7 +10632,7 @@ int validate_container_imsm(struct mdinfo *info) + 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)); ++ info->disk.minor), 1, NULL); + + for (idev = intel_devices; idev; idev = idev->next) { + if (dev_path && strstr(dev_path, idev->path)) { +@@ -10669,7 +10653,8 @@ int validate_container_imsm(struct mdinfo *info) + struct mdinfo *dev; + + for (dev = info->next; dev; dev = dev->next) { +- dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor)); ++ dev_path = devt_to_devpath(makedev(dev->disk.major, ++ dev->disk.minor), 1, NULL); + + struct sys_dev *hba2 = NULL; + for (idev = intel_devices; idev; idev = idev->next) { +@@ -11181,7 +11166,7 @@ static const char *imsm_get_disk_controller_domain(const char *path) + struct sys_dev* hba; + char *path; + +- path = devt_to_devpath(st.st_rdev); ++ path = devt_to_devpath(st.st_rdev, 1, NULL); + if (path == NULL) + return "unknown"; + hba = find_disk_attached_hba(-1, path); +-- +2.7.5 + diff --git a/SOURCES/0005-imsm-add-devpath_to_char-method.patch b/SOURCES/0005-imsm-add-devpath_to_char-method.patch new file mode 100644 index 0000000..53a5ecc --- /dev/null +++ b/SOURCES/0005-imsm-add-devpath_to_char-method.patch @@ -0,0 +1,157 @@ +From fcebeb77b18842876295b1a0dbc22d173a709434 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 17 May 2021 16:39:01 +0200 +Subject: [PATCH 05/15] imsm: add devpath_to_char method + +Add method for reading sysfs attributes and propagate it across IMSM code. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + platform-intel.c | 23 +++++++++++++++++++++++ + platform-intel.h | 2 ++ + super-intel.c | 33 +++++++++++++++------------------ + 3 files changed, 40 insertions(+), 18 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 2ed63ed..9401784 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -239,6 +239,29 @@ __u16 devpath_to_vendor(const char *dev_path) + return id; + } + ++/* Description: Read text value of dev_path/entry field ++ * Parameters: ++ * dev_path - sysfs path to the device ++ * entry - entry to be read ++ * buf - buffer for read value ++ * len - size of buf ++ * verbose - error logging level ++ */ ++int devpath_to_char(const char *dev_path, const char *entry, char *buf, int len, ++ int verbose) ++{ ++ char path[PATH_MAX]; ++ ++ snprintf(path, sizeof(path), "%s/%s", dev_path, entry); ++ if (load_sys(path, buf, len)) { ++ if (verbose) ++ pr_err("Cannot read %s, aborting\n", path); ++ return 1; ++ } ++ ++ return 0; ++} ++ + struct sys_dev *find_intel_devices(void) + { + struct sys_dev *ahci, *isci, *nvme; +diff --git a/platform-intel.h b/platform-intel.h +index f93add5..45d98cd 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -238,6 +238,8 @@ static inline char *guid_str(char *buf, struct efi_guid guid) + + char *get_nvme_multipath_dev_hw_path(const char *dev_path); + char *diskfd_to_devpath(int fd, int dev_level, char *buf); ++int devpath_to_char(const char *dev_path, const char *entry, char *buf, ++ int len, int verbose); + __u16 devpath_to_vendor(const char *dev_path); + struct sys_dev *find_driver_devices(const char *bus, const char *driver); + struct sys_dev *find_intel_devices(void); +diff --git a/super-intel.c b/super-intel.c +index cff8550..c352f50 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2246,7 +2246,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + char vendor[64]; + char buf[1024]; + int major, minor; +- char *device; ++ char device[PATH_MAX]; + char *c; + int port; + int type; +@@ -2262,20 +2262,15 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + continue; + } + +- /* retrieve the scsi device type */ +- if (asprintf(&device, "/sys/dev/block/%d:%d/device/xxxxxxx", major, minor) < 0) { ++ /* retrieve the scsi device */ ++ if (!devt_to_devpath(makedev(major, minor), 1, device)) { + if (verbose > 0) +- pr_err("failed to allocate 'device'\n"); ++ pr_err("failed to get device\n"); + err = 2; + break; + } +- sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor); +- if (load_sys(device, buf, sizeof(buf)) != 0) { +- if (verbose > 0) +- pr_err("failed to read device type for %s\n", +- path); ++ if (devpath_to_char(device, "type", buf, sizeof(buf), 0)) { + err = 2; +- free(device); + break; + } + type = strtoul(buf, NULL, 10); +@@ -2284,8 +2279,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + if (!(type == 0 || type == 7 || type == 14)) { + vendor[0] = '\0'; + model[0] = '\0'; +- sprintf(device, "/sys/dev/block/%d:%d/device/vendor", major, minor); +- if (load_sys(device, buf, sizeof(buf)) == 0) { ++ ++ if (devpath_to_char(device, "vendor", buf, ++ sizeof(buf), 0) == 0) { + strncpy(vendor, buf, sizeof(vendor)); + vendor[sizeof(vendor) - 1] = '\0'; + c = (char *) &vendor[sizeof(vendor) - 1]; +@@ -2293,8 +2289,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + *c-- = '\0'; + + } +- sprintf(device, "/sys/dev/block/%d:%d/device/model", major, minor); +- if (load_sys(device, buf, sizeof(buf)) == 0) { ++ ++ if (devpath_to_char(device, "model", buf, ++ sizeof(buf), 0) == 0) { + strncpy(model, buf, sizeof(model)); + model[sizeof(model) - 1] = '\0'; + c = (char *) &model[sizeof(model) - 1]; +@@ -2319,7 +2316,6 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + } + } else + buf[0] = '\0'; +- free(device); + + /* chop device path to 'host%d' and calculate the port number */ + c = strchr(&path[hba_len], '/'); +@@ -4026,7 +4022,7 @@ static void fd2devname(int fd, char *name) + + static int nvme_get_serial(int fd, void *buf, size_t buf_len) + { +- char path[60]; ++ char path[PATH_MAX]; + char *name = fd2kname(fd); + + if (!name) +@@ -4035,9 +4031,10 @@ static int nvme_get_serial(int fd, void *buf, size_t buf_len) + if (strncmp(name, "nvme", 4) != 0) + return 1; + +- snprintf(path, sizeof(path) - 1, "/sys/block/%s/device/serial", name); ++ if (!diskfd_to_devpath(fd, 1, path)) ++ return 1; + +- return load_sys(path, buf, buf_len); ++ return devpath_to_char(path, "serial", buf, buf_len, 0); + } + + extern int scsi_get_serial(int fd, void *buf, size_t buf_len); +-- +2.7.5 + diff --git a/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch b/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch new file mode 100644 index 0000000..7fecc91 --- /dev/null +++ b/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch @@ -0,0 +1,329 @@ +From 8662f92d71f1f88589061272606b8b673d31de05 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 17 May 2021 16:39:02 +0200 +Subject: [PATCH 06/15] imsm: Limit support to the lowest namespace + +First namespace existence is not quaranted by NVMe specification. +Instead first the smallest one shall be chosen. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + platform-intel.c | 81 ++++++++++++++++++++++++++---------- + platform-intel.h | 2 +- + super-intel.c | 124 +++++++++++++++++++++++++++---------------------------- + 3 files changed, 123 insertions(+), 84 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 9401784..5a8729e 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -879,36 +879,75 @@ char *vmd_domain_to_controller(struct sys_dev *hba, char *buf) + closedir(dir); + return NULL; + } +-/* Verify that NVMe drive is supported by IMSM ++ ++/* Scan over all controller's namespaces and compare nsid value to verify if ++ * current one is supported. The routine doesn't check IMSM capabilities for ++ * namespace. Only one nvme namespace is supported by IMSM. ++ * Paramteres: ++ * fd - open descriptor to the nvme namespace ++ * verbose - error logging level + * Returns: +- * 0 - not supported +- * 1 - supported ++ * 1 - if namespace is supported ++ * 0 - otherwise + */ +-int imsm_is_nvme_supported(int disk_fd, int verbose) ++int imsm_is_nvme_namespace_supported(int fd, int verbose) + { +- char nsid_path[PATH_MAX]; +- char buf[PATH_MAX]; +- struct stat stb; ++ DIR *dir = NULL; ++ struct dirent *ent; ++ char cntrl_path[PATH_MAX]; ++ char ns_path[PATH_MAX]; ++ unsigned long long lowest_nsid = ULLONG_MAX; ++ unsigned long long this_nsid; ++ int rv = 0; + +- if (disk_fd < 0) +- return 0; + +- if (fstat(disk_fd, &stb)) +- return 0; ++ if (!diskfd_to_devpath(fd, 1, cntrl_path) || ++ !diskfd_to_devpath(fd, 0, ns_path)) { ++ if (verbose) ++ pr_err("Cannot get device paths\n"); ++ goto abort; ++ } + +- snprintf(nsid_path, PATH_MAX-1, "/sys/dev/block/%d:%d/nsid", +- major(stb.st_rdev), minor(stb.st_rdev)); + +- if (load_sys(nsid_path, buf, sizeof(buf))) { +- pr_err("Cannot read %s, rejecting drive\n", nsid_path); +- return 0; +- } +- if (strtoll(buf, NULL, 10) != 1) { ++ if (devpath_to_ll(ns_path, "nsid", &this_nsid)) { + if (verbose) +- pr_err("Only first namespace is supported by IMSM, aborting\n"); +- return 0; ++ pr_err("Cannot read nsid value for %s", ++ basename(ns_path)); ++ goto abort; + } +- return 1; ++ ++ dir = opendir(cntrl_path); ++ if (!dir) ++ goto abort; ++ ++ /* The lowest nvme namespace is supported */ ++ for (ent = readdir(dir); ent; ent = readdir(dir)) { ++ unsigned long long curr_nsid; ++ char curr_ns_path[PATH_MAX + 256]; ++ ++ if (!strstr(ent->d_name, "nvme")) ++ continue; ++ ++ snprintf(curr_ns_path, sizeof(curr_ns_path), "%s/%s", ++ cntrl_path, ent->d_name); ++ ++ if (devpath_to_ll(curr_ns_path, "nsid", &curr_nsid)) ++ goto abort; ++ ++ if (lowest_nsid > curr_nsid) ++ lowest_nsid = curr_nsid; ++ } ++ ++ if (this_nsid == lowest_nsid) ++ rv = 1; ++ else if (verbose) ++ pr_err("IMSM is supported on the lowest NVMe namespace\n"); ++ ++abort: ++ if (dir) ++ closedir(dir); ++ ++ return rv; + } + + /* Verify if multipath is supported by NVMe controller +diff --git a/platform-intel.h b/platform-intel.h +index 45d98cd..6238d23 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -254,6 +254,6 @@ const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id); + const struct imsm_orom *get_orom_by_device_id(__u16 device_id); + struct sys_dev *device_by_id(__u16 device_id); + struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path); +-int imsm_is_nvme_supported(int disk_fd, int verbose); + int is_multipath_nvme(int disk_fd); ++int imsm_is_nvme_namespace_supported(int disk_fd, int verbose); + char *vmd_domain_to_controller(struct sys_dev *hba, char *buf); +diff --git a/super-intel.c b/super-intel.c +index c352f50..fdcefb6 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2381,49 +2381,51 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + + static int print_nvme_info(struct sys_dev *hba) + { +- char buf[1024]; +- char *device_path; + struct dirent *ent; + DIR *dir; +- int fd; + + dir = opendir("/sys/block/"); + if (!dir) + return 1; + + for (ent = readdir(dir); ent; ent = readdir(dir)) { +- if (strstr(ent->d_name, "nvme")) { +- fd = open_dev(ent->d_name); +- if (fd < 0) +- continue; ++ char ns_path[PATH_MAX]; ++ char cntrl_path[PATH_MAX]; ++ char buf[PATH_MAX]; ++ int fd = -1; + +- if (!imsm_is_nvme_supported(fd, 0)) { +- if (fd >= 0) +- close(fd); +- continue; +- } ++ if (!strstr(ent->d_name, "nvme")) ++ goto skip; + +- device_path = diskfd_to_devpath(fd, 1, NULL); +- if (!device_path) { +- close(fd); +- continue; +- } ++ fd = open_dev(ent->d_name); ++ if (fd < 0) ++ goto skip; + +- if (path_attached_to_hba(device_path, hba->path)) { +- fd2devname(fd, buf); +- if (hba->type == SYS_DEV_VMD) +- printf(" NVMe under VMD : %s", buf); +- else if (hba->type == SYS_DEV_NVME) +- printf(" NVMe Device : %s", buf); +- if (!imsm_read_serial(fd, NULL, (__u8 *)buf, +- sizeof(buf))) +- printf(" (%s)\n", buf); +- else +- printf("()\n"); +- } +- free(device_path); ++ if (!diskfd_to_devpath(fd, 0, ns_path) || ++ !diskfd_to_devpath(fd, 1, cntrl_path)) ++ goto skip; ++ ++ if (!path_attached_to_hba(cntrl_path, hba->path)) ++ goto skip; ++ ++ if (!imsm_is_nvme_namespace_supported(fd, 0)) ++ goto skip; ++ ++ fd2devname(fd, buf); ++ if (hba->type == SYS_DEV_VMD) ++ printf(" NVMe under VMD : %s", buf); ++ else if (hba->type == SYS_DEV_NVME) ++ printf(" NVMe Device : %s", buf); ++ ++ if (!imsm_read_serial(fd, NULL, (__u8 *)buf, ++ sizeof(buf))) ++ printf(" (%s)\n", buf); ++ else ++ printf("()\n"); ++ ++skip: ++ if (fd > -1) + close(fd); +- } + } + + closedir(dir); +@@ -5933,14 +5935,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + + if (!diskfd_to_devpath(fd, 2, pci_dev_path) || + !diskfd_to_devpath(fd, 1, cntrl_path)) { +- pr_err("failed to get dev_path, aborting\n"); +- if (dd->devname) +- free(dd->devname); +- free(dd); +- return 1; +- } ++ pr_err("failed to get dev paths, aborting\n"); + +- if (!imsm_is_nvme_supported(dd->fd, 1)) { + if (dd->devname) + free(dd->devname); + free(dd); +@@ -6665,7 +6661,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + { + int fd; + unsigned long long ldsize; +- struct intel_super *super; ++ struct intel_super *super = NULL; + int rv = 0; + + if (level != LEVEL_CONTAINER) +@@ -6680,24 +6676,18 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + dev, strerror(errno)); + return 0; + } +- if (!get_dev_size(fd, dev, &ldsize)) { +- close(fd); +- return 0; +- } ++ if (!get_dev_size(fd, dev, &ldsize)) ++ goto exit; + + /* capabilities retrieve could be possible + * note that there is no fd for the disks in array. + */ + super = alloc_super(); +- if (!super) { +- close(fd); +- return 0; +- } +- if (!get_dev_sector_size(fd, NULL, &super->sector_size)) { +- close(fd); +- free_imsm(super); +- return 0; +- } ++ if (!super) ++ goto exit; ++ ++ if (!get_dev_sector_size(fd, NULL, &super->sector_size)) ++ goto exit; + + rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL); + if (rv != 0) { +@@ -6708,32 +6698,42 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + fd, str, super->orom, rv, raiddisks); + #endif + /* no orom/efi or non-intel hba of the disk */ +- close(fd); +- free_imsm(super); +- return 0; ++ rv = 0; ++ goto exit; + } +- close(fd); + if (super->orom) { + if (raiddisks > super->orom->tds) { + if (verbose) + pr_err("%d exceeds maximum number of platform supported disks: %d\n", + raiddisks, super->orom->tds); +- free_imsm(super); +- return 0; ++ goto exit; + } + if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 && + (ldsize >> 9) >> 32 > 0) { + if (verbose) + pr_err("%s exceeds maximum platform supported size\n", dev); +- free_imsm(super); +- return 0; ++ goto exit; ++ } ++ ++ if (super->hba->type == SYS_DEV_VMD || ++ super->hba->type == SYS_DEV_NVME) { ++ if (!imsm_is_nvme_namespace_supported(fd, 1)) { ++ if (verbose) ++ pr_err("NVMe namespace %s is not supported by IMSM\n", ++ basename(dev)); ++ goto exit; ++ } + } + } + + *freesize = avail_size_imsm(st, ldsize >> 9, data_offset); +- free_imsm(super); ++ rv = 1; ++exit: ++ if (super) ++ free_imsm(super); ++ close(fd); + +- return 1; ++ return rv; + } + + static unsigned long long find_size(struct extent *e, int *idx, int num_extents) +-- +2.7.5 + diff --git a/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch b/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch new file mode 100644 index 0000000..ea25ff7 --- /dev/null +++ b/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch @@ -0,0 +1,107 @@ +From 1f5d54a06df01ca3032ca2d29159584cab7d7509 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 17 May 2021 16:39:03 +0200 +Subject: [PATCH 07/15] Manage: Call validate_geometry when adding drive to + external container + +When adding drive to container call validate_geometry to verify whether +drive is supported and can be addded to container. + +Remove unused parameters from validate_geometry_imsm_container(). +There is no need to pass them. +Don't calculate freesize if it is not mandatory. Make it configurable. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Manage.c | 7 +++++++ + super-ddf.c | 9 +++++---- + super-intel.c | 19 +++++++------------ + 3 files changed, 19 insertions(+), 16 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 0a5f09b..f789e0c 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -992,6 +992,13 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + return -1; + } + ++ /* Check if metadata handler is able to accept the drive */ ++ if (!tst->ss->validate_geometry(tst, LEVEL_CONTAINER, 0, 1, NULL, ++ 0, 0, dv->devname, NULL, 0, 1)) { ++ close(container_fd); ++ return -1; ++ } ++ + Kill(dv->devname, NULL, 0, -1, 0); + dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); + if (tst->ss->add_to_super(tst, &disc, dfd, +diff --git a/super-ddf.c b/super-ddf.c +index 2314762..80a40f8 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -3475,10 +3475,11 @@ validate_geometry_ddf_container(struct supertype *st, + return 0; + } + close(fd); +- +- *freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS); +- if (*freesize == 0) +- return 0; ++ if (freesize) { ++ *freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS); ++ if (*freesize == 0) ++ return 0; ++ } + + return 1; + } +diff --git a/super-intel.c b/super-intel.c +index fdcefb6..fe45d93 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6652,8 +6652,7 @@ static int store_super_imsm(struct supertype *st, int fd) + } + + static int validate_geometry_imsm_container(struct supertype *st, int level, +- int layout, int raiddisks, int chunk, +- unsigned long long size, ++ int raiddisks, + unsigned long long data_offset, + char *dev, + unsigned long long *freesize, +@@ -6725,8 +6724,8 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + } + } + } +- +- *freesize = avail_size_imsm(st, ldsize >> 9, data_offset); ++ if (freesize) ++ *freesize = avail_size_imsm(st, ldsize >> 9, data_offset); + rv = 1; + exit: + if (super) +@@ -7586,15 +7585,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + * if given unused devices create a container + * if given given devices in a container create a member volume + */ +- if (level == LEVEL_CONTAINER) { ++ if (level == LEVEL_CONTAINER) + /* Must be a fresh device to add to a container */ +- return validate_geometry_imsm_container(st, level, layout, +- raiddisks, +- *chunk, +- size, data_offset, +- dev, freesize, +- verbose); +- } ++ return validate_geometry_imsm_container(st, level, raiddisks, ++ data_offset, dev, ++ freesize, verbose); + + /* + * Size is given in sectors. +-- +2.7.5 + diff --git a/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch b/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch new file mode 100644 index 0000000..25080d2 --- /dev/null +++ b/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch @@ -0,0 +1,31 @@ +From f421731c7e1de6608f8fafb551d199ff5f1d6b97 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 2 Jun 2021 09:17:19 +0800 +Subject: [PATCH 08/15] mdadm/super1: It needs to specify int32 for + bitmap_offset + +For super1.0 bitmap offset is -16. So it needs to use int type for bitmap offset. + +Fixes: 1fe2e1007310 (mdadm/bitmap: locate bitmap calcuate bitmap position wrongly) +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + super1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/super1.c b/super1.c +index c05e623..a12a5bc 100644 +--- a/super1.c ++++ b/super1.c +@@ -2631,7 +2631,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num) + else + ret = -1; + +- offset = __le64_to_cpu(sb->super_offset) + __le32_to_cpu(sb->bitmap_offset); ++ offset = __le64_to_cpu(sb->super_offset) + (int32_t)__le32_to_cpu(sb->bitmap_offset); + if (node_num) { + bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE); + bm_sectors_per_node = calc_bitmap_size(bms, 4096) >> 9; +-- +2.7.5 + diff --git a/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch b/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch new file mode 100644 index 0000000..e356085 --- /dev/null +++ b/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch @@ -0,0 +1,48 @@ +From dca80fcd5d15c37ecbd82763e6fe4aee8c077bf9 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Tue, 15 Jun 2021 16:45:39 +0200 +Subject: [PATCH 09/15] Use dev_open in validate geometry container + +Fix regression caused by the patch 1f5d54a06 +("Manage: Call validate_geometry when adding drive to external container") +- mdmonitor passes to Manage() routine dev name as min:mjr. +The open() used in validate_geometry_container() +in both ddf and imsm requires path, replace open calls by dev_open, +which allows to use dev path and min:mjr. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + super-ddf.c | 2 +- + super-intel.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index 80a40f8..dc8e512 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -3463,7 +3463,7 @@ validate_geometry_ddf_container(struct supertype *st, + if (!dev) + return 1; + +- fd = open(dev, O_RDONLY|O_EXCL, 0); ++ fd = dev_open(dev, O_RDONLY|O_EXCL); + if (fd < 0) { + if (verbose) + pr_err("ddf: Cannot open %s: %s\n", +diff --git a/super-intel.c b/super-intel.c +index fe45d93..5356ca5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6668,7 +6668,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + if (!dev) + return 1; + +- fd = open(dev, O_RDONLY|O_EXCL, 0); ++ fd = dev_open(dev, O_RDONLY|O_EXCL); + if (fd < 0) { + if (verbose > 0) + pr_err("imsm: Cannot open %s: %s\n", +-- +2.7.5 + diff --git a/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch b/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch new file mode 100644 index 0000000..8972e90 --- /dev/null +++ b/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch @@ -0,0 +1,30 @@ +From 7d8935cbb0fdb2b776b736bffc00323a04e5f788 Mon Sep 17 00:00:00 2001 +From: Oleksandr Shchirskyi +Date: Fri, 18 Jun 2021 15:53:30 +0200 +Subject: [PATCH 10/15] imsm: correct offset for 4k disks in --examine output + +"Sector Offset" field in Examine output was always printed in 512 +byte sectors. Update it to support 4096 sector size. + +Signed-off-by: Oleksandr Shchirskyi +Signed-off-by: Jes Sorensen +--- + super-intel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/super-intel.c b/super-intel.c +index 5356ca5..88636e0 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1663,7 +1663,7 @@ static void print_imsm_dev(struct intel_super *super, + (unsigned long long)sz * 512 / super->sector_size, + human_size(sz * 512)); + printf(" Sector Offset : %llu\n", +- pba_of_lba0(map)); ++ pba_of_lba0(map) * 512 / super->sector_size); + printf(" Num Stripes : %llu\n", + num_data_stripes(map)); + printf(" Chunk Size : %u KiB", +-- +2.7.5 + diff --git a/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch b/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch new file mode 100644 index 0000000..695113a --- /dev/null +++ b/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch @@ -0,0 +1,35 @@ +From 8d69bf147ec77447c5d45c17bed7dc017808cc44 Mon Sep 17 00:00:00 2001 +From: Oleksandr Shchirskyi +Date: Fri, 18 Jun 2021 15:53:31 +0200 +Subject: [PATCH 11/15] Remove Spare drives line from details for external + metadata + +Arrays with external metadata do not have spare disks directly +assigned to volumes; spare disks belong to containers and are +moved to arrays when the array is degraded/reshaping. +Thus, the display of zero spare disks in volume details is +incorrect and can be confusing. + +Signed-off-by: Oleksandr Shchirskyi +Signed-off-by: Jes Sorensen +--- + Detail.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Detail.c b/Detail.c +index cd26fb0..ad56344 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -548,7 +548,8 @@ int Detail(char *dev, struct context *c) + array.working_disks); + if (array.raid_disks) { + printf(" Failed Devices : %d\n", array.failed_disks); +- printf(" Spare Devices : %d\n", array.spare_disks); ++ if (!external) ++ printf(" Spare Devices : %d\n", array.spare_disks); + } + printf("\n"); + if (array.level == 5) { +-- +2.7.5 + diff --git a/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch b/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch new file mode 100644 index 0000000..1d1c128 --- /dev/null +++ b/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch @@ -0,0 +1,173 @@ +From 601ffa784f03cea843b9b732e561ffea0b8c036f Mon Sep 17 00:00:00 2001 +From: Oleksandr Shchirskyi +Date: Fri, 18 Jun 2021 15:53:32 +0200 +Subject: [PATCH 12/15] Don't associate spares with other arrays during RAID + Examine + +Spares in imsm belong to containers, not volumes, and must go into +a separate container when assembling the RAID. +Remove association spares with other arrays and make Examine print +separate containers for spares. +Auto assemble without config file already works like this. So make +creating a config file and assembling from it consistent with auto +assemble. +With this change, mdadm -Es will add this line to output if spares +are found: +ARRAY metadata=imsm UUID=00000000:00000000:00000000:00000000 + +Signed-off-by: Oleksandr Shchirskyi +Signed-off-by: Jes Sorensen +--- + Examine.c | 2 +- + super-intel.c | 74 +++++++++++++++-------------------------------------------- + 2 files changed, 20 insertions(+), 56 deletions(-) + +diff --git a/Examine.c b/Examine.c +index 4381cd5..9574a3c 100644 +--- a/Examine.c ++++ b/Examine.c +@@ -166,7 +166,7 @@ int Examine(struct mddev_dev *devlist, + int newline = 0; + + ap->st->ss->brief_examine_super(ap->st, c->verbose > 0); +- if (ap->spares) ++ if (ap->spares && !ap->st->ss->external) + newline += printf(" spares=%d", ap->spares); + if (c->verbose > 0) { + newline += printf(" devices"); +diff --git a/super-intel.c b/super-intel.c +index 88636e0..aeea137 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2123,12 +2123,6 @@ static void brief_examine_super_imsm(struct supertype *st, int verbose) + /* We just write a generic IMSM ARRAY entry */ + struct mdinfo info; + char nbuf[64]; +- struct intel_super *super = st->sb; +- +- if (!super->anchor->num_raid_devs) { +- printf("ARRAY metadata=imsm\n"); +- return; +- } + + getinfo_super_imsm(st, &info, NULL); + fname_from_uuid(st, &info, nbuf, ':'); +@@ -3911,12 +3905,9 @@ static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src) + static int compare_super_imsm(struct supertype *st, struct supertype *tst, + int verbose) + { +- /* +- * return: ++ /* return: + * 0 same, or first was empty, and second was copied +- * 1 second had wrong number +- * 2 wrong uuid +- * 3 wrong other info ++ * 1 sb are different + */ + struct intel_super *first = st->sb; + struct intel_super *sec = tst->sb; +@@ -3926,31 +3917,30 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst, + tst->sb = NULL; + return 0; + } ++ + /* in platform dependent environment test if the disks + * use the same Intel hba +- * If not on Intel hba at all, allow anything. ++ * if not on Intel hba at all, allow anything. ++ * doesn't check HBAs if num_raid_devs is not set, as it means ++ * it is a free floating spare, and all spares regardless of HBA type ++ * will fall into separate container during the assembly + */ +- if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) { ++ if (first->hba && sec->hba && first->anchor->num_raid_devs != 0) { + if (first->hba->type != sec->hba->type) { + if (verbose) + pr_err("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; ++ return 1; + } +- + if (first->orom != sec->orom) { + if (verbose) + pr_err("HBAs of devices do not match %s != %s\n", + first->hba->pci_id, sec->hba->pci_id); +- return 3; ++ return 1; + } +- + } + +- /* if an anchor does not have num_raid_devs set then it is a free +- * floating spare +- */ + if (first->anchor->num_raid_devs > 0 && + sec->anchor->num_raid_devs > 0) { + /* Determine if these disks might ever have been +@@ -3962,7 +3952,7 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst, + + if (memcmp(first->anchor->sig, sec->anchor->sig, + MAX_SIGNATURE_LENGTH) != 0) +- return 3; ++ return 1; + + if (first_family == 0) + first_family = first->anchor->family_num; +@@ -3970,43 +3960,17 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst, + sec_family = sec->anchor->family_num; + + if (first_family != sec_family) +- return 3; ++ return 1; + + } + +- /* if 'first' is a spare promote it to a populated mpb with sec's +- * family number +- */ +- if (first->anchor->num_raid_devs == 0 && +- sec->anchor->num_raid_devs > 0) { +- int i; +- struct intel_dev *dv; +- struct imsm_dev *dev; +- +- /* we need to copy raid device info from sec if an allocation +- * fails here we don't associate the spare +- */ +- for (i = 0; i < sec->anchor->num_raid_devs; i++) { +- dv = xmalloc(sizeof(*dv)); +- dev = xmalloc(sizeof_imsm_dev(get_imsm_dev(sec, i), 1)); +- dv->dev = dev; +- dv->index = i; +- dv->next = first->devlist; +- first->devlist = dv; +- } +- if (i < sec->anchor->num_raid_devs) { +- /* allocation failure */ +- free_devlist(first); +- pr_err("imsm: failed to associate spare\n"); +- return 3; +- } +- first->anchor->num_raid_devs = sec->anchor->num_raid_devs; +- first->anchor->orig_family_num = sec->anchor->orig_family_num; +- first->anchor->family_num = sec->anchor->family_num; +- memcpy(first->anchor->sig, sec->anchor->sig, MAX_SIGNATURE_LENGTH); +- for (i = 0; i < sec->anchor->num_raid_devs; i++) +- imsm_copy_dev(get_imsm_dev(first, i), get_imsm_dev(sec, i)); +- } ++ /* if an anchor does not have num_raid_devs set then it is a free ++ * floating spare. don't assosiate spare with any array, as during assembly ++ * spares shall fall into separate container, from which they can be moved ++ * when necessary ++ */ ++ if (first->anchor->num_raid_devs ^ sec->anchor->num_raid_devs) ++ return 1; + + return 0; + } +-- +2.7.5 + diff --git a/SOURCES/0013-mdadm-Fix-building-errors.patch b/SOURCES/0013-mdadm-Fix-building-errors.patch new file mode 100644 index 0000000..b953afd --- /dev/null +++ b/SOURCES/0013-mdadm-Fix-building-errors.patch @@ -0,0 +1,49 @@ +From ccd61ebfd97fde43768497c79e3d361b484b1520 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 22 Jun 2021 23:15:55 +0800 +Subject: [PATCH 13/15] mdadm: Fix building errors + +In util.c, there is a building error: +'/md/metadata_version' directive writing 20 bytes into a +region of size between 0 and 255 [-Werror=format-overflow=] + +In mapfile.c +It declares the fouth argument as 'int *' in map_update, +but in mdadm.h it's previously declared as an array 'int[4]' + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + mapfile.c | 2 +- + util.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/mapfile.c b/mapfile.c +index 8d7acb3..6b2207d 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -215,7 +215,7 @@ void map_free(struct map_ent *map) + } + + int map_update(struct map_ent **mpp, char *devnm, char *metadata, +- int *uuid, char *path) ++ int uuid[4], char *path) + { + struct map_ent *map, *mp; + int rv; +diff --git a/util.c b/util.c +index 5879694..cdf1da2 100644 +--- a/util.c ++++ b/util.c +@@ -1543,7 +1543,7 @@ int open_container(int fd) + /* 'fd' is a block device. Find out if it is in use + * by a container, and return an open fd on that container. + */ +- char path[256]; ++ char path[288]; + char *e; + DIR *dir; + struct dirent *de; +-- +2.7.5 + diff --git a/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch b/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch new file mode 100644 index 0000000..0387a8a --- /dev/null +++ b/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch @@ -0,0 +1,142 @@ +From 3a85bf0e417d0977136efbade7c7ea269e24bc21 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Mon, 28 Jun 2021 14:15:04 +0200 +Subject: [PATCH 14/15] imsm: Fix possible memory leaks and refactor freeing + struct dl + +Free memory allocated by structs dl and intel_super. +Allow __free_imsm_disk to decide if fd has to be closed and propagate it +across code instead of direct struct dl freeing. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + super-intel.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index aeea137..da37625 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4499,9 +4499,9 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd + return err; + } + +-static void __free_imsm_disk(struct dl *d) ++static void __free_imsm_disk(struct dl *d, int close_fd) + { +- if (d->fd >= 0) ++ if (close_fd && d->fd > -1) + close(d->fd); + if (d->devname) + free(d->devname); +@@ -4518,17 +4518,17 @@ static void free_imsm_disks(struct intel_super *super) + while (super->disks) { + d = super->disks; + super->disks = d->next; +- __free_imsm_disk(d); ++ __free_imsm_disk(d, 1); + } + while (super->disk_mgmt_list) { + d = super->disk_mgmt_list; + super->disk_mgmt_list = d->next; +- __free_imsm_disk(d); ++ __free_imsm_disk(d, 1); + } + while (super->missing) { + d = super->missing; + super->missing = d->next; +- __free_imsm_disk(d); ++ __free_imsm_disk(d, 1); + } + + } +@@ -5243,10 +5243,13 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname) + free_super_imsm(st); + + super = alloc_super(); +- if (!get_dev_sector_size(fd, NULL, &super->sector_size)) +- return 1; + if (!super) + return 1; ++ ++ if (!get_dev_sector_size(fd, NULL, &super->sector_size)) { ++ free_imsm(super); ++ return 1; ++ } + /* Load hba and capabilities if they exist. + * But do not preclude loading metadata in case capabilities or hba are + * non-compliant and ignore_hw_compat is set. +@@ -5884,9 +5887,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN); + if (rv) { + pr_err("failed to retrieve scsi serial, aborting\n"); +- if (dd->devname) +- free(dd->devname); +- free(dd); ++ __free_imsm_disk(dd, 0); + abort(); + } + +@@ -5900,10 +5901,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + if (!diskfd_to_devpath(fd, 2, pci_dev_path) || + !diskfd_to_devpath(fd, 1, cntrl_path)) { + pr_err("failed to get dev paths, aborting\n"); +- +- if (dd->devname) +- free(dd->devname); +- free(dd); ++ __free_imsm_disk(dd, 0); + return 1; + } + +@@ -5939,15 +5937,16 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + !imsm_orom_has_tpv_support(super->orom)) { + pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n" + "\tPlease refer to Intel(R) RSTe/VROC user guide.\n"); +- free(dd->devname); +- free(dd); ++ __free_imsm_disk(dd, 0); + return 1; + } + } + + get_dev_size(fd, NULL, &size); +- if (!get_dev_sector_size(fd, NULL, &member_sector_size)) ++ if (!get_dev_sector_size(fd, NULL, &member_sector_size)) { ++ __free_imsm_disk(dd, 0); + return 1; ++ } + + if (super->sector_size == 0) { + /* this a first device, so sector_size is not set yet */ +@@ -9260,7 +9259,7 @@ static int remove_disk_super(struct intel_super *super, int major, int minor) + else + super->disks = dl->next; + dl->next = NULL; +- __free_imsm_disk(dl); ++ __free_imsm_disk(dl, 1); + dprintf("removed %x:%x\n", major, minor); + break; + } +@@ -9310,7 +9309,7 @@ static int add_remove_disk_update(struct intel_super *super) + } + } + /* release allocate disk structure */ +- __free_imsm_disk(disk_cfg); ++ __free_imsm_disk(disk_cfg, 1); + } + } + return check_degraded; +@@ -10511,7 +10510,7 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind + struct dl *dl = *dlp; + + *dlp = (*dlp)->next; +- __free_imsm_disk(dl); ++ __free_imsm_disk(dl, 1); + } + } + +-- +2.7.5 + diff --git a/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch b/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch new file mode 100644 index 0000000..22d9628 --- /dev/null +++ b/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch @@ -0,0 +1,32 @@ +From 5b30a34aa4b5ea7a8202314c1d737ec4a481c127 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 15 Jul 2021 12:25:23 +0200 +Subject: [PATCH 15/15] Add error handling for chunk size in RAID1 + +Print error if chunk size is set as it is not supported. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Create.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/Create.c b/Create.c +index 18b5e64..f5d57f8 100644 +--- a/Create.c ++++ b/Create.c +@@ -254,9 +254,8 @@ int Create(struct supertype *st, char *mddev, + case LEVEL_MULTIPATH: + case LEVEL_CONTAINER: + if (s->chunk) { +- s->chunk = 0; +- if (c->verbose > 0) +- pr_err("chunk size ignored for this level\n"); ++ pr_err("specifying chunk size is forbidden for this level\n"); ++ return 1; + } + break; + default: +-- +2.7.5 + diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec index 285484e..1de075b 100644 --- a/SPECS/mdadm.spec +++ b/SPECS/mdadm.spec @@ -2,7 +2,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm Version: 4.2 %define subversion rc1 -Release: rc1_2%{?dist} +Release: rc1_3%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}-%{subversion}.tar.xz Source1: mdmonitor.init Source2: raid-check @@ -15,8 +15,21 @@ Source8: mdadm_event.conf Source9: mdcheck Source10: mdadm_env.sh -Patch001: 0001-Fix-some-building-errors.patch -Patch002: 0002-Prevent-user-from-using-stop-with-ambiguous-args.patch +Patch001: 0001-imsm-change-wrong-size-verification.patch +Patch002: 0002-Fix-some-building-errors.patch +Patch003: 0003-Prevent-user-from-using-stop-with-ambiguous-args.patch +Patch004: 0004-imsm-add-generic-method-to-resolve-device-links.patch +Patch005: 0005-imsm-add-devpath_to_char-method.patch +Patch006: 0006-imsm-Limit-support-to-the-lowest-namespace.patch +Patch007: 0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch +Patch008: 0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch +Patch009: 0009-Use-dev_open-in-validate-geometry-container.patch +Patch010: 0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch +Patch011: 0011-Remove-Spare-drives-line-from-details-for-external-m.patch +Patch012: 0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch +Patch013: 0013-mdadm-Fix-building-errors.patch +Patch014: 0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch +Patch015: 0015-Add-error-handling-for-chunk-size-in-RAID1.patch # RHEL customization patches Patch200: mdadm-3.3-udev.patch @@ -49,6 +62,20 @@ file can be used to help with some common tasks. %patch001 -p1 -b .0001 %patch002 -p1 -b .0002 +%patch003 -p1 -b .0003 +%patch004 -p1 -b .0004 +%patch005 -p1 -b .0005 +%patch006 -p1 -b .0006 +%patch007 -p1 -b .0007 +%patch008 -p1 -b .0008 +%patch009 -p1 -b .0009 +%patch010 -p1 -b .0010 +%patch011 -p1 -b .0011 +%patch012 -p1 -b .0012 +%patch013 -p1 -b .0013 +%patch014 -p1 -b .0014 +%patch015 -p1 -b .0015 + # RHEL customization patches %patch200 -p1 -b .udev %patch201 -p1 -b .static @@ -119,6 +146,10 @@ rm -rf %{buildroot} /usr/lib/mdadm/mdadm_env.sh %changelog +* Tue Jul 20 2021 Xiao Ni - 4.2-rc1-3 +- Fix super1.0 offset problem and super imsm bugs +- Resolves rhbz#1966712 and rhbz#1975449 + * Thu Jun 10 2021 Xiao Ni - 4.2-rc1-2 - Fix udev rule syntax error - Resolves rhbz#1945780