diff --git a/0116-imsm-nvme-multipath-support.patch b/0116-imsm-nvme-multipath-support.patch new file mode 100644 index 0000000..4ac6856 --- /dev/null +++ b/0116-imsm-nvme-multipath-support.patch @@ -0,0 +1,232 @@ +From d835518b6b5381da773e1ce1ae10614239017ecf Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Fri, 12 Mar 2021 10:30:16 +0100 +Subject: [PATCH] imsm: nvme multipath support +Patch-mainline: mdadm-4.1+ +Git-commit: d835518b6b5381da773e1ce1ae10614239017ecf +References: bsc#1175758 + +Add support for nvme devices which are represented +via nvme-subsystem. +Print warning when multi-path disk is added to RAID. + +Signed-off-by: Oleksandr Shchirskyi +Signed-off-by: Blazej Kucman +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +Signed-off-by: Coly Li +--- + platform-intel.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++- + platform-intel.h | 2 ++ + super-intel.c | 38 ++++++++++++++--------- + 3 files changed, 104 insertions(+), 15 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index f1f6d4c..0e1ec3d 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -30,6 +30,8 @@ + #include + #include + ++#define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/" ++ + static int devpath_to_ll(const char *dev_path, const char *entry, + unsigned long long *val); + +@@ -668,12 +670,63 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba) + return NULL; + } + ++/* Check whether the nvme device is represented by nvme subsytem, ++ * if yes virtual path should be changed to hardware device path, ++ * to allow IMSM capabilities detection. ++ * Returns: ++ * hardware path to device - if the device is represented via ++ * nvme virtual subsytem ++ * NULL - if the device is not represented via nvme virtual subsytem ++ */ ++char *get_nvme_multipath_dev_hw_path(const char *dev_path) ++{ ++ DIR *dir; ++ struct dirent *ent; ++ char *rp = NULL; ++ ++ if (strncmp(dev_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) != 0) ++ return NULL; ++ ++ dir = opendir(dev_path); ++ if (!dir) ++ return NULL; ++ ++ for (ent = readdir(dir); ent; ent = readdir(dir)) { ++ char buf[strlen(dev_path) + strlen(ent->d_name) + 1]; ++ ++ /* Check if dir is a controller, ignore namespaces*/ ++ if (!(strncmp(ent->d_name, "nvme", 4) == 0) || ++ (strrchr(ent->d_name, 'n') != &ent->d_name[0])) ++ continue; ++ ++ sprintf(buf, "%s/%s", dev_path, ent->d_name); ++ rp = realpath(buf, NULL); ++ break; ++ } ++ ++ closedir(dir); ++ return rp; ++} ++ + char *devt_to_devpath(dev_t dev) + { + char device[46]; ++ char *rp; ++ char *buf; + + sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev)); +- return realpath(device, NULL); ++ ++ rp = realpath(device, NULL); ++ if (!rp) ++ return NULL; ++ ++ buf = get_nvme_multipath_dev_hw_path(rp); ++ if (buf) { ++ free(rp); ++ return buf; ++ } ++ ++ return rp; + } + + char *diskfd_to_devpath(int fd) +@@ -797,3 +850,27 @@ int imsm_is_nvme_supported(int disk_fd, int verbose) + } + return 1; + } ++ ++/* Verify if multipath is supported by NVMe controller ++ * Returns: ++ * 0 - not supported ++ * 1 - supported ++ */ ++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)) ++ return 0; ++ ++ if (strncmp(ns_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) == 0) ++ return 1; ++ ++ return 0; ++} +diff --git a/platform-intel.h b/platform-intel.h +index 7371478..8396a0f 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -236,6 +236,7 @@ static inline char *guid_str(char *buf, struct efi_guid guid) + return buf; + } + ++char *get_nvme_multipath_dev_hw_path(const char *dev_path); + char *diskfd_to_devpath(int fd); + __u16 devpath_to_vendor(const char *dev_path); + struct sys_dev *find_driver_devices(const char *bus, const char *driver); +@@ -252,4 +253,5 @@ 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); + char *vmd_domain_to_controller(struct sys_dev *hba, char *buf); +diff --git a/super-intel.c b/super-intel.c +index 2bfcad1..6617dd6 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2386,9 +2386,9 @@ 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; +- char *rp; + int fd; + + dir = opendir("/sys/block/"); +@@ -2397,19 +2397,23 @@ static int print_nvme_info(struct sys_dev *hba) + + for (ent = readdir(dir); ent; ent = readdir(dir)) { + if (strstr(ent->d_name, "nvme")) { +- sprintf(buf, "/sys/block/%s", ent->d_name); +- rp = realpath(buf, NULL); +- if (!rp) ++ fd = open_dev(ent->d_name); ++ if (fd < 0) + continue; +- if (path_attached_to_hba(rp, hba->path)) { +- fd = open_dev(ent->d_name); +- if (!imsm_is_nvme_supported(fd, 0)) { +- if (fd >= 0) +- close(fd); +- free(rp); +- continue; +- } + ++ if (!imsm_is_nvme_supported(fd, 0)) { ++ if (fd >= 0) ++ close(fd); ++ continue; ++ } ++ ++ device_path = diskfd_to_devpath(fd); ++ if (!device_path) { ++ close(fd); ++ continue; ++ } ++ ++ if (path_attached_to_hba(device_path, hba->path)) { + fd2devname(fd, buf); + if (hba->type == SYS_DEV_VMD) + printf(" NVMe under VMD : %s", buf); +@@ -2420,9 +2424,9 @@ static int print_nvme_info(struct sys_dev *hba) + printf(" (%s)\n", buf); + else + printf("()\n"); +- close(fd); + } +- free(rp); ++ free(device_path); ++ close(fd); + } + } + +@@ -5938,6 +5942,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + int i; + char *devpath = diskfd_to_devpath(fd); + char controller_path[PATH_MAX]; ++ char *controller_name; + + if (!devpath) { + pr_err("failed to get devpath, aborting\n"); +@@ -5948,6 +5953,11 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + } + + 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)) { +-- +2.26.2 + diff --git a/0117-Grow-be-careful-of-corrupt-dev_roles-list.patch b/0117-Grow-be-careful-of-corrupt-dev_roles-list.patch new file mode 100644 index 0000000..4f09315 --- /dev/null +++ b/0117-Grow-be-careful-of-corrupt-dev_roles-list.patch @@ -0,0 +1,166 @@ +From 8818d4e7fe7cda900d5c00014b05cdde058bdd29 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 26 Feb 2021 12:02:36 +1100 +Subject: [PATCH] Grow: be careful of corrupt dev_roles list +Git-commit: 8818d4e7fe7cda900d5c00014b05cdde058bdd29 +Patch-mainline: mdadm-4.1+ +References: bsc#1181619 + +I've seen a case where the dev_roles list of a linear array +was corrupt. ->max_dev was > 128 and > raid_disks, and the +extra slots were '0', not 0xFFFE or 0xFFFF. + +This caused problems when a 128th device was added. + +So: + 1/ make Grow_Add_device more robust so that if numbers + look wrong, it fails-safe. + + 2/ make examine_super1() report details if the dev_roles + array is corrupt. + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Grow.c | 15 ++++++++++++--- + super1.c | 48 ++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 50 insertions(+), 13 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 5c2512f..cec8388 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -197,7 +197,12 @@ int Grow_Add_device(char *devname, int fd, char *newdev) + info.disk.minor = minor(rdev); + info.disk.raid_disk = d; + info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); +- st->ss->update_super(st, &info, "linear-grow-new", newdev, 0, 0, NULL); ++ if (st->ss->update_super(st, &info, "linear-grow-new", newdev, ++ 0, 0, NULL) != 0) { ++ pr_err("Preparing new metadata failed on %s\n", newdev); ++ close(nfd); ++ return 1; ++ } + + if (st->ss->store_super(st, nfd)) { + pr_err("Cannot store new superblock on %s\n", newdev); +@@ -250,8 +255,12 @@ int Grow_Add_device(char *devname, int fd, char *newdev) + info.array.active_disks = nd+1; + info.array.working_disks = nd+1; + +- st->ss->update_super(st, &info, "linear-grow-update", dv, +- 0, 0, NULL); ++ if (st->ss->update_super(st, &info, "linear-grow-update", dv, ++ 0, 0, NULL) != 0) { ++ pr_err("Updating metadata failed on %s\n", dv); ++ close(fd2); ++ return 1; ++ } + + if (st->ss->store_super(st, fd2)) { + pr_err("Cannot store new superblock on %s\n", dv); +diff --git a/super1.c b/super1.c +index b5b379b..7bee026 100644 +--- a/super1.c ++++ b/super1.c +@@ -330,6 +330,7 @@ static void examine_super1(struct supertype *st, char *homehost) + int layout; + unsigned long long sb_offset; + struct mdinfo info; ++ int inconsistent = 0; + + printf(" Magic : %08x\n", __le32_to_cpu(sb->magic)); + printf(" Version : 1"); +@@ -576,14 +577,16 @@ static void examine_super1(struct supertype *st, char *homehost) + if (role == d) + cnt++; + } +- if (cnt == 2) ++ if (cnt == 2 && __le32_to_cpu(sb->level) > 0) + printf("R"); + else if (cnt == 1) + printf("A"); + else if (cnt == 0) + printf("."); +- else ++ else { + printf("?"); ++ inconsistent = 1; ++ } + } + #if 0 + /* This is confusing too */ +@@ -598,6 +601,21 @@ static void examine_super1(struct supertype *st, char *homehost) + #endif + printf(" ('A' == active, '.' == missing, 'R' == replacing)"); + printf("\n"); ++ for (d = 0; d < __le32_to_cpu(sb->max_dev); d++) { ++ unsigned int r = __le16_to_cpu(sb->dev_roles[d]); ++ if (r <= MD_DISK_ROLE_MAX && ++ r > __le32_to_cpu(sb->raid_disks) + delta_extra) ++ inconsistent = 1; ++ } ++ if (inconsistent) { ++ printf("WARNING Array state is inconsistent - each number should appear only once\n"); ++ for (d = 0; d < __le32_to_cpu(sb->max_dev); d++) ++ if (__le16_to_cpu(sb->dev_roles[d]) >= MD_DISK_ROLE_FAULTY) ++ printf(" %d:-", d); ++ else ++ printf(" %d:%d", d, __le16_to_cpu(sb->dev_roles[d])); ++ printf("\n"); ++ } + } + + static void brief_examine_super1(struct supertype *st, int verbose) +@@ -1264,19 +1282,25 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + rv = 1; + } + } else if (strcmp(update, "linear-grow-new") == 0) { +- unsigned int i; ++ int i; + int fd; +- unsigned int max = __le32_to_cpu(sb->max_dev); ++ int max = __le32_to_cpu(sb->max_dev); ++ ++ if (max > MAX_DEVS) ++ return -2; + + for (i = 0; i < max; i++) + if (__le16_to_cpu(sb->dev_roles[i]) >= + MD_DISK_ROLE_FAULTY) + break; ++ if (i != info->disk.number) ++ return -2; + sb->dev_number = __cpu_to_le32(i); +- info->disk.number = i; +- if (i >= max) { ++ ++ if (i == max) + sb->max_dev = __cpu_to_le32(max+1); +- } ++ if (i > max) ++ return -2; + + random_uuid(sb->device_uuid); + +@@ -1302,10 +1326,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + } + } else if (strcmp(update, "linear-grow-update") == 0) { + int max = __le32_to_cpu(sb->max_dev); +- sb->raid_disks = __cpu_to_le32(info->array.raid_disks); +- if (info->array.raid_disks > max) { ++ int i = info->disk.number; ++ if (max > MAX_DEVS || i > MAX_DEVS) ++ return -2; ++ if (i > max) ++ return -2; ++ if (i == max) + sb->max_dev = __cpu_to_le32(max+1); +- } ++ sb->raid_disks = __cpu_to_le32(info->array.raid_disks); + sb->dev_roles[info->disk.number] = + __cpu_to_le16(info->disk.raid_disk); + } else if (strcmp(update, "resync") == 0) { +-- +2.26.2 + diff --git a/mdadm.changes b/mdadm.changes index a6afc2c..485d665 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Fri May 14 14:40:40 UTC 2021 - Coly Li + +- Grow: be careful of corrupt dev_roles list (bsc#1181619) + 0117-Grow-be-careful-of-corrupt-dev_roles-list.patch + +------------------------------------------------------------------- +Fri May 14 12:17:31 UTC 2021 - Coly Li + +- imsm: nvme multipath support (bsc#1175758) + 0116-imsm-nvme-multipath-support.patch + ------------------------------------------------------------------- Wed Mar 17 02:35:00 UTC 2021 - Heming Zhao diff --git a/mdadm.spec b/mdadm.spec index 0ecdca9..9743525 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -152,6 +152,8 @@ Patch112: 0112-Incremental-Remove-redundant-spare-movement-logic.patch Patch113: 0113-Dump-get-stat-from-a-wrong-metadata-file-when-restor.patch Patch114: 0114-super1-fix-Floating-point-exception.patch Patch115: 0115-super1.c-avoid-useless-sync-when-bitmap-switches-fro.patch +Patch116: 0116-imsm-nvme-multipath-support.patch +Patch117: 0117-Grow-be-careful-of-corrupt-dev_roles-list.patch Patch1001: 1001-display-timeout-status.patch Patch1002: 1002-OnCalendar-format-fix-of-mdcheck_start-timer.patch Patch1003: 1003-mdadm-treat-the-Dell-softraid-array-as-local-array.patch @@ -274,6 +276,8 @@ mdadm is a program that can be used to control Linux md devices. %patch113 -p1 %patch114 -p1 %patch115 -p1 +%patch116 -p1 +%patch117 -p1 %patch1001 -p1 %patch1002 -p1 %patch1003 -p1