diff --git a/SOURCES/0048-mdcheck-service-can-t-start-succesfully-because-of-s.patch b/SOURCES/0048-mdcheck-service-can-t-start-succesfully-because-of-s.patch new file mode 100644 index 0000000..a106dd2 --- /dev/null +++ b/SOURCES/0048-mdcheck-service-can-t-start-succesfully-because-of-s.patch @@ -0,0 +1,45 @@ +From e1512e7b7d060f0346738b237ea34eac21b29a26 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 18 Dec 2019 14:46:21 +0800 +Subject: [RHEL8.2 PATCH 1/1] mdcheck service can't start succesfully because + of syntax error + +It reports error when starting mdcheck_start and mdcheck_continue service. +Invalid environment assignment, ignoring: MDADM_CHECK_DURATION="6 hours" + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + systemd/mdcheck_continue.service | 2 +- + systemd/mdcheck_start.service | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service +index deac695..aa02dde 100644 +--- a/systemd/mdcheck_continue.service ++++ b/systemd/mdcheck_continue.service +@@ -11,7 +11,7 @@ ConditionPathExistsGlob = /var/lib/mdcheck/MD_UUID_* + + [Service] + Type=oneshot +-Environment= MDADM_CHECK_DURATION="6 hours" ++Environment= "MDADM_CHECK_DURATION=6 hours" + EnvironmentFile=-/run/sysconfig/mdadm + ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh + ExecStart=/usr/share/mdadm/mdcheck --continue --duration ${MDADM_CHECK_DURATION} +diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service +index f17f1aa..da62d5f 100644 +--- a/systemd/mdcheck_start.service ++++ b/systemd/mdcheck_start.service +@@ -11,7 +11,7 @@ Wants=mdcheck_continue.timer + + [Service] + Type=oneshot +-Environment= MDADM_CHECK_DURATION="6 hours" ++Environment= "MDADM_CHECK_DURATION=6 hours" + EnvironmentFile=-/run/sysconfig/mdadm + ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh + ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION} +-- +2.7.5 + diff --git a/SOURCES/0049-Remove-last-traces-of-HOT_ADD_DISK.patch b/SOURCES/0049-Remove-last-traces-of-HOT_ADD_DISK.patch new file mode 100644 index 0000000..e9e7674 --- /dev/null +++ b/SOURCES/0049-Remove-last-traces-of-HOT_ADD_DISK.patch @@ -0,0 +1,41 @@ +From 02af379337c73e751ad97c0fed9123121f8b4289 Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Wed, 27 Nov 2019 10:19:54 -0500 +Subject: [RHEL8.2 PATCH 49/61] Remove last traces of HOT_ADD_DISK + +This ioctl is no longer used, so remove all references to it. + +Signed-off-by: Jes Sorensen +--- + Manage.c | 2 -- + md_u.h | 1 - + 2 files changed, 3 deletions(-) + +diff --git a/Manage.c b/Manage.c +index ffe55f8..deeba2b 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1289,8 +1289,6 @@ int Manage_subdevs(char *devname, int fd, + /* Do something to each dev. + * devmode can be + * 'a' - add the device +- * try HOT_ADD_DISK +- * If that fails EINVAL, try ADD_NEW_DISK + * 'S' - add the device as a spare - don't try re-add + * 'j' - add the device as a journal device + * 'A' - re-add the device +diff --git a/md_u.h b/md_u.h +index 2d66d52..b30893c 100644 +--- a/md_u.h ++++ b/md_u.h +@@ -28,7 +28,6 @@ + #define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) + #define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) + #define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) +-#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) + #define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) + #define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) + +-- +2.7.5 + diff --git a/SOURCES/0050-Fix-up-a-few-formatting-issues.patch b/SOURCES/0050-Fix-up-a-few-formatting-issues.patch new file mode 100644 index 0000000..f74c9b7 --- /dev/null +++ b/SOURCES/0050-Fix-up-a-few-formatting-issues.patch @@ -0,0 +1,51 @@ +From 9cf361f8791d86aaced821c19af556819bc03732 Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Wed, 27 Nov 2019 11:33:15 -0500 +Subject: [RHEL8.2 PATCH 50/61] Fix up a few formatting issues + +Signed-off-by: Jes Sorensen +--- + Manage.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/Manage.c b/Manage.c +index deeba2b..b22c396 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1728,8 +1728,10 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + int fd2 = open(from_devname, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) { +- if (fd1>=0) close(fd1); +- if (fd2>=0) close(fd2); ++ if (fd1 >= 0) ++ close(fd1); ++ if (fd2 >= 0) ++ close(fd2); + return 0; + } + +@@ -1743,7 +1745,8 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + devlist.disposition = 'r'; + if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) { + devlist.disposition = 'a'; +- if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL, 0) == 0) { ++ if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, ++ NULL, 0) == 0) { + /* make sure manager is aware of changes */ + ping_manager(to_devname); + ping_manager(from_devname); +@@ -1751,7 +1754,9 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + close(fd2); + return 1; + } +- else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0); ++ else ++ Manage_subdevs(from_devname, fd2, &devlist, ++ -1, 0, NULL, 0); + } + close(fd1); + close(fd2); +-- +2.7.5 + diff --git a/SOURCES/0051-Remove-unused-code.patch b/SOURCES/0051-Remove-unused-code.patch new file mode 100644 index 0000000..cd4aa2a --- /dev/null +++ b/SOURCES/0051-Remove-unused-code.patch @@ -0,0 +1,26 @@ +From 4b31846f3f90aa24f883ceed80e91f204c0a9389 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 29 Nov 2019 17:14:47 +0800 +Subject: [RHEL8.2 PATCH 51/61] Remove unused code + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + platform-intel.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/platform-intel.h b/platform-intel.h +index 29c85f1..7cb370e 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -169,7 +169,6 @@ static inline int fls(int x) + r -= 2; + } + if (!(x & 0x80000000u)) { +- x <<= 1; + r -= 1; + } + return r; +-- +2.7.5 + diff --git a/SOURCES/0052-imsm-return-correct-uuid-for-volume-in-detail.patch b/SOURCES/0052-imsm-return-correct-uuid-for-volume-in-detail.patch new file mode 100644 index 0000000..642297f --- /dev/null +++ b/SOURCES/0052-imsm-return-correct-uuid-for-volume-in-detail.patch @@ -0,0 +1,176 @@ +From b771faef931c798a4553db0a8c1366aff90079c6 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Fri, 29 Nov 2019 15:21:08 +0100 +Subject: [RHEL8.2 PATCH 52/61] imsm: return correct uuid for volume in detail + +Fixes the side effect of the patch b6180160f ("imsm: save current_vol number") +- wrong UUID is printed in detail for each volume. +New parameter "subarray" is added to determine what info should be extracted +from metadata (subarray or container). +The parameter affects only IMSM metadata. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + Detail.c | 4 ++-- + mdadm.h | 5 +++-- + super-ddf.c | 5 +++-- + super-intel.c | 20 ++++++++++++++++++-- + super0.c | 4 ++-- + super1.c | 4 ++-- + 6 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/Detail.c b/Detail.c +index 3e61e37..24fa462 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -623,7 +623,7 @@ This is pretty boring + free_mdstat(ms); + + if (st && st->sb) +- st->ss->detail_super(st, c->homehost); ++ st->ss->detail_super(st, c->homehost, subarray); + + if (array.raid_disks == 0 && sra && + sra->array.major_version == -1 && +@@ -767,7 +767,7 @@ skip_devices_state: + if (spares && c->brief && array.raid_disks) + printf(" spares=%d", spares); + if (c->brief && st && st->sb) +- st->ss->brief_detail_super(st); ++ st->ss->brief_detail_super(st, subarray); + if (st) + st->ss->free_super(st); + +diff --git a/mdadm.h b/mdadm.h +index c88ceab..91f1338 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -847,8 +847,9 @@ extern struct superswitch { + /* Used to report details of an active array. + * ->load_super was possibly given a 'component' string. + */ +- void (*detail_super)(struct supertype *st, char *homehost); +- void (*brief_detail_super)(struct supertype *st); ++ void (*detail_super)(struct supertype *st, char *homehost, ++ char *subarray); ++ void (*brief_detail_super)(struct supertype *st, char *subarray); + void (*export_detail_super)(struct supertype *st); + + /* Optional: platform hardware / firmware details */ +diff --git a/super-ddf.c b/super-ddf.c +index c095e8a..7802063 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1730,7 +1730,8 @@ err: + return 1; + } + +-static void detail_super_ddf(struct supertype *st, char *homehost) ++static void detail_super_ddf(struct supertype *st, char *homehost, ++ char *subarray) + { + struct ddf_super *sb = st->sb; + int cnt = be16_to_cpu(sb->virt->populated_vdes); +@@ -1787,7 +1788,7 @@ static void uuid_of_ddf_subarray(const struct ddf_super *ddf, + memcpy(uuid, sha, 4*4); + } + +-static void brief_detail_super_ddf(struct supertype *st) ++static void brief_detail_super_ddf(struct supertype *st, char *subarray) + { + struct mdinfo info; + char nbuf[64]; +diff --git a/super-intel.c b/super-intel.c +index a7fbed4..86dcb69 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2183,23 +2183,39 @@ err: + return 1; + } + +-static void detail_super_imsm(struct supertype *st, char *homehost) ++static void detail_super_imsm(struct supertype *st, char *homehost, ++ char *subarray) + { + struct mdinfo info; + char nbuf[64]; ++ struct intel_super *super = st->sb; ++ int temp_vol = super->current_vol; ++ ++ if (subarray) ++ super->current_vol = strtoul(subarray, NULL, 10); + + getinfo_super_imsm(st, &info, NULL); + fname_from_uuid(st, &info, nbuf, ':'); + printf("\n UUID : %s\n", nbuf + 5); ++ ++ super->current_vol = temp_vol; + } + +-static void brief_detail_super_imsm(struct supertype *st) ++static void brief_detail_super_imsm(struct supertype *st, char *subarray) + { + struct mdinfo info; + char nbuf[64]; ++ struct intel_super *super = st->sb; ++ int temp_vol = super->current_vol; ++ ++ if (subarray) ++ super->current_vol = strtoul(subarray, NULL, 10); ++ + getinfo_super_imsm(st, &info, NULL); + fname_from_uuid(st, &info, nbuf, ':'); + printf(" UUID=%s", nbuf + 5); ++ ++ super->current_vol = temp_vol; + } + + static int imsm_read_serial(int fd, char *devname, __u8 *serial); +diff --git a/super0.c b/super0.c +index 42989b9..6b7c0e3 100644 +--- a/super0.c ++++ b/super0.c +@@ -348,7 +348,7 @@ err: + return 1; + } + +-static void detail_super0(struct supertype *st, char *homehost) ++static void detail_super0(struct supertype *st, char *homehost, char *subarray) + { + mdp_super_t *sb = st->sb; + printf(" UUID : "); +@@ -368,7 +368,7 @@ static void detail_super0(struct supertype *st, char *homehost) + printf("\n Events : %d.%d\n\n", sb->events_hi, sb->events_lo); + } + +-static void brief_detail_super0(struct supertype *st) ++static void brief_detail_super0(struct supertype *st, char *subarray) + { + mdp_super_t *sb = st->sb; + printf(" UUID="); +diff --git a/super1.c b/super1.c +index b85dc20..929466d 100644 +--- a/super1.c ++++ b/super1.c +@@ -833,7 +833,7 @@ err: + return 1; + } + +-static void detail_super1(struct supertype *st, char *homehost) ++static void detail_super1(struct supertype *st, char *homehost, char *subarray) + { + struct mdp_superblock_1 *sb = st->sb; + bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE); +@@ -857,7 +857,7 @@ static void detail_super1(struct supertype *st, char *homehost) + (unsigned long long)__le64_to_cpu(sb->events)); + } + +-static void brief_detail_super1(struct supertype *st) ++static void brief_detail_super1(struct supertype *st, char *subarray) + { + struct mdp_superblock_1 *sb = st->sb; + int i; +-- +2.7.5 + diff --git a/SOURCES/0053-imsm-Change-the-way-of-printing-nvme-drives-in-detai.patch b/SOURCES/0053-imsm-Change-the-way-of-printing-nvme-drives-in-detai.patch new file mode 100644 index 0000000..3c1c221 --- /dev/null +++ b/SOURCES/0053-imsm-Change-the-way-of-printing-nvme-drives-in-detai.patch @@ -0,0 +1,208 @@ +From 6da53c0e2aab200605722795798b1e4f2352cd64 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Mon, 2 Dec 2019 10:52:05 +0100 +Subject: [RHEL8.2 PATCH 53/61] imsm: Change the way of printing nvme drives in + detail-platform. + +Change NVMe controller path to device node path +in mdadm --detail-platform and print serial number. +The method imsm_read_serial always trimes serial to +MAX_RAID_SERIAL_LEN, added parameter 'serial_buf_len' +will be used to check the serial fit +to passed buffor, if not, will be trimed. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + super-intel.c | 97 ++++++++++++++++++++++++++++------------------------------- + 1 file changed, 46 insertions(+), 51 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 86dcb69..5c1f759 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2218,7 +2218,8 @@ static void brief_detail_super_imsm(struct supertype *st, char *subarray) + super->current_vol = temp_vol; + } + +-static int imsm_read_serial(int fd, char *devname, __u8 *serial); ++static int imsm_read_serial(int fd, char *devname, __u8 *serial, ++ size_t serial_buf_len); + static void fd2devname(int fd, char *name); + + static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_base, int verbose) +@@ -2364,8 +2365,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + else { + fd2devname(fd, buf); + printf(" Port%d : %s", port, buf); +- if (imsm_read_serial(fd, NULL, (__u8 *) buf) == 0) +- printf(" (%.*s)\n", MAX_RAID_SERIAL_LEN, buf); ++ if (imsm_read_serial(fd, NULL, (__u8 *)buf, ++ sizeof(buf)) == 0) ++ printf(" (%s)\n", buf); + else + printf(" ()\n"); + close(fd); +@@ -2388,52 +2390,45 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b + return err; + } + +-static int print_vmd_attached_devs(struct sys_dev *hba) ++static int print_nvme_info(struct sys_dev *hba) + { ++ char buf[1024]; + struct dirent *ent; + DIR *dir; +- char path[292]; +- char link[256]; +- char *c, *rp; +- +- if (hba->type != SYS_DEV_VMD) +- return 1; ++ char *rp; ++ int fd; + +- /* scroll through /sys/dev/block looking for devices attached to +- * this hba +- */ +- dir = opendir("/sys/bus/pci/drivers/nvme"); ++ dir = opendir("/sys/block/"); + if (!dir) + return 1; + + for (ent = readdir(dir); ent; ent = readdir(dir)) { +- int n; +- +- /* is 'ent' a device? check that the 'subsystem' link exists and +- * that its target matches 'bus' +- */ +- sprintf(path, "/sys/bus/pci/drivers/nvme/%s/subsystem", +- ent->d_name); +- n = readlink(path, link, sizeof(link)); +- if (n < 0 || n >= (int)sizeof(link)) +- continue; +- link[n] = '\0'; +- c = strrchr(link, '/'); +- if (!c) +- continue; +- if (strncmp("pci", c+1, strlen("pci")) != 0) +- continue; +- +- sprintf(path, "/sys/bus/pci/drivers/nvme/%s", ent->d_name); +- +- rp = realpath(path, NULL); +- if (!rp) +- continue; ++ if (strstr(ent->d_name, "nvme")) { ++ sprintf(buf, "/sys/block/%s", ent->d_name); ++ rp = realpath(buf, NULL); ++ if (!rp) ++ continue; ++ if (path_attached_to_hba(rp, hba->path)) { ++ fd = open_dev(ent->d_name); ++ if (fd < 0) { ++ free(rp); ++ continue; ++ } + +- if (path_attached_to_hba(rp, hba->path)) { +- printf(" NVMe under VMD : %s\n", rp); ++ 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"); ++ close(fd); ++ } ++ free(rp); + } +- free(rp); + } + + closedir(dir); +@@ -2648,7 +2643,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + char buf[PATH_MAX]; + printf(" I/O Controller : %s (%s)\n", + vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type)); +- if (print_vmd_attached_devs(hba)) { ++ if (print_nvme_info(hba)) { + if (verbose > 0) + pr_err("failed to get devices attached to VMD domain.\n"); + result |= 2; +@@ -2663,7 +2658,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + if (entry->type == SYS_DEV_NVME) { + for (hba = list; hba; hba = hba->next) { + if (hba->type == SYS_DEV_NVME) +- printf(" NVMe Device : %s\n", hba->path); ++ print_nvme_info(hba); + } + printf("\n"); + continue; +@@ -4028,11 +4023,11 @@ static int nvme_get_serial(int fd, void *buf, size_t buf_len) + extern int scsi_get_serial(int fd, void *buf, size_t buf_len); + + static int imsm_read_serial(int fd, char *devname, +- __u8 serial[MAX_RAID_SERIAL_LEN]) ++ __u8 *serial, size_t serial_buf_len) + { + char buf[50]; + int rv; +- int len; ++ size_t len; + char *dest; + char *src; + unsigned int i; +@@ -4075,13 +4070,13 @@ static int imsm_read_serial(int fd, char *devname, + len = dest - buf; + dest = buf; + +- /* truncate leading characters */ +- if (len > MAX_RAID_SERIAL_LEN) { +- dest += len - MAX_RAID_SERIAL_LEN; +- len = MAX_RAID_SERIAL_LEN; ++ if (len > serial_buf_len) { ++ /* truncate leading characters */ ++ dest += len - serial_buf_len; ++ len = serial_buf_len; + } + +- memset(serial, 0, MAX_RAID_SERIAL_LEN); ++ memset(serial, 0, serial_buf_len); + memcpy(serial, dest, len); + + return 0; +@@ -4136,7 +4131,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd) + char name[40]; + __u8 serial[MAX_RAID_SERIAL_LEN]; + +- rv = imsm_read_serial(fd, devname, serial); ++ rv = imsm_read_serial(fd, devname, serial, MAX_RAID_SERIAL_LEN); + + if (rv != 0) + return 2; +@@ -5844,7 +5839,7 @@ int mark_spare(struct dl *disk) + return ret_val; + + ret_val = 0; +- if (!imsm_read_serial(disk->fd, NULL, serial)) { ++ if (!imsm_read_serial(disk->fd, NULL, serial, MAX_RAID_SERIAL_LEN)) { + /* Restore disk serial number, because takeover marks disk + * as failed and adds to serial ':0' before it becomes + * a spare disk. +@@ -5895,7 +5890,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + dd->fd = fd; + dd->e = NULL; + dd->action = DISK_ADD; +- rv = imsm_read_serial(fd, devname, dd->serial); ++ 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) +-- +2.7.5 + diff --git a/SOURCES/0054-Create-add-support-for-RAID0-layouts.patch b/SOURCES/0054-Create-add-support-for-RAID0-layouts.patch new file mode 100644 index 0000000..b87e668 --- /dev/null +++ b/SOURCES/0054-Create-add-support-for-RAID0-layouts.patch @@ -0,0 +1,342 @@ +From 329dfc28debb58ffe7bd1967cea00fc583139aca Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 4 Nov 2019 14:27:49 +1100 +Subject: [RHEL8.2 PATCH 54/61] Create: add support for RAID0 layouts. + +Since Linux 5.4 a layout is needed for RAID0 arrays with +varying device sizes. +This patch makes the layout of an array visible (via --examine) +and sets the layout on newly created arrays. +--layout=dangerous +can be used to avoid setting a layout so that they array +can be used on older kernels. + +Tested-by: dann frazier +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Create.c | 11 +++++++++++ + Detail.c | 5 +++++ + maps.c | 12 ++++++++++++ + md.4 | 14 ++++++++++++++ + mdadm.8.in | 30 +++++++++++++++++++++++++++++- + mdadm.c | 8 ++++++++ + mdadm.h | 8 +++++++- + super0.c | 6 ++++++ + super1.c | 30 +++++++++++++++++++++++++++++- + 9 files changed, 121 insertions(+), 3 deletions(-) + +diff --git a/Create.c b/Create.c +index 292f92a..6f84e5b 100644 +--- a/Create.c ++++ b/Create.c +@@ -51,6 +51,9 @@ static int default_layout(struct supertype *st, int level, int verbose) + default: /* no layout */ + layout = 0; + break; ++ case 0: ++ layout = RAID0_ORIG_LAYOUT; ++ break; + case 10: + layout = 0x102; /* near=2, far=1 */ + if (verbose > 0) +@@ -950,6 +953,11 @@ int Create(struct supertype *st, char *mddev, + if (rv) { + pr_err("ADD_NEW_DISK for %s failed: %s\n", + dv->devname, strerror(errno)); ++ if (errno == EINVAL && ++ info.array.level == 0) { ++ pr_err("Possibly your kernel doesn't support RAID0 layouts.\n"); ++ pr_err("Either upgrade, or use --layout=dangerous\n"); ++ } + goto abort_locked; + } + break; +@@ -1046,6 +1054,9 @@ int Create(struct supertype *st, char *mddev, + if (ioctl(mdfd, RUN_ARRAY, ¶m)) { + pr_err("RUN_ARRAY failed: %s\n", + strerror(errno)); ++ if (errno == 524 /* ENOTSUP */ && ++ info.array.level == 0) ++ cont_err("Please use --layout=original or --layout=alternate\n"); + if (info.array.chunk_size & (info.array.chunk_size-1)) { + cont_err("Problem may be that chunk size is not a power of 2\n"); + } +diff --git a/Detail.c b/Detail.c +index 24fa462..832485f 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -525,6 +525,11 @@ int Detail(char *dev, struct context *c) + printf(" Layout : %s\n", + str ? str : "-unknown-"); + } ++ if (array.level == 0 && array.layout) { ++ str = map_num(r0layout, array.layout); ++ printf(" Layout : %s\n", ++ str ? str : "-unknown-"); ++ } + if (array.level == 6) { + str = map_num(r6layout, array.layout); + printf(" Layout : %s\n", +diff --git a/maps.c b/maps.c +index 49b7f2c..a4fd279 100644 +--- a/maps.c ++++ b/maps.c +@@ -73,6 +73,18 @@ mapping_t r6layout[] = { + { NULL, UnSet } + }; + ++/* raid0 layout is only needed because of a bug in 3.14 which changed ++ * the effective layout of raid0 arrays with varying device sizes. ++ */ ++mapping_t r0layout[] = { ++ { "original", RAID0_ORIG_LAYOUT}, ++ { "alternate", RAID0_ALT_MULTIZONE_LAYOUT}, ++ { "1", 1}, /* aka ORIG */ ++ { "2", 2}, /* aka ALT */ ++ { "dangerous", 0}, ++ { NULL, UnSet}, ++}; ++ + mapping_t pers[] = { + { "linear", LEVEL_LINEAR}, + { "raid0", 0}, +diff --git a/md.4 b/md.4 +index e86707a..6fe2755 100644 +--- a/md.4 ++++ b/md.4 +@@ -193,6 +193,20 @@ smallest device has been exhausted, the RAID0 driver starts + collecting chunks into smaller stripes that only span the drives which + still have remaining space. + ++A bug was introduced in linux 3.14 which changed the layout of blocks in ++a RAID0 beyond the region that is striped over all devices. This bug ++does not affect an array with all devices the same size, but can affect ++other RAID0 arrays. ++ ++Linux 5.4 (and some stable kernels to which the change was backported) ++will not normally assemble such an array as it cannot know which layout ++to use. There is a module parameter "raid0.default_layout" which can be ++set to "1" to force the kernel to use the pre-3.14 layout or to "2" to ++force it to use the 3.14-and-later layout. when creating a new RAID0 ++array, ++.I mdadm ++will record the chosen layout in the metadata in a way that allows newer ++kernels to assemble the array without needing a module parameter. + + .SS RAID1 + +diff --git a/mdadm.8.in b/mdadm.8.in +index 9aec9f4..fc9b6a6 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -593,6 +593,8 @@ to change the RAID level in some cases. See LEVEL CHANGES below. + This option configures the fine details of data layout for RAID5, RAID6, + and RAID10 arrays, and controls the failure modes for + .IR faulty . ++It can also be used for working around a kernel bug with RAID0, but generally ++doesn't need to be used explicitly. + + The layout of the RAID5 parity block can be one of + .BR left\-asymmetric , +@@ -652,7 +654,7 @@ option to set subsequent failure modes. + "clear" or "none" will remove any pending or periodic failure modes, + and "flush" will clear any persistent faults. + +-Finally, the layout options for RAID10 are one of 'n', 'o' or 'f' followed ++The layout options for RAID10 are one of 'n', 'o' or 'f' followed + by a small number. The default is 'n2'. The supported options are: + + .I 'n' +@@ -677,6 +679,32 @@ devices in the array. It does not need to divide evenly into that + number (e.g. it is perfectly legal to have an 'n2' layout for an array + with an odd number of devices). + ++A bug introduced in Linux 3.14 means that RAID0 arrays ++.B "with devices of differing sizes" ++started using a different layout. This could lead to ++data corruption. Since Linux 5.4 (and various stable releases that received ++backports), the kernel will not accept such an array unless ++a layout is explictly set. It can be set to ++.RB ' original ' ++or ++.RB ' alternate '. ++When creating a new array, ++.I mdadm ++will select ++.RB ' original ' ++by default, so the layout does not normally need to be set. ++An array created for either ++.RB ' original ' ++or ++.RB ' alternate ' ++will not be recognized by an (unpatched) kernel prior to 5.4. To create ++a RAID0 array with devices of differing sizes that can be used on an ++older kernel, you can set the layout to ++.RB ' dangerous '. ++This will use whichever layout the running kernel supports, so the data ++on the array may become corrupt when changing kernel from pre-3.14 to a ++later kernel. ++ + When an array is converted between RAID5 and RAID6 an intermediate + RAID6 layout is used in which the second parity block (Q) is always on + the last device. To convert a RAID5 to RAID6 and leave it in this new +diff --git a/mdadm.c b/mdadm.c +index 1fb8086..e438f9c 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -550,6 +550,14 @@ int main(int argc, char *argv[]) + pr_err("raid level must be given before layout.\n"); + exit(2); + ++ case 0: ++ s.layout = map_name(r0layout, optarg); ++ if (s.layout == UnSet) { ++ pr_err("layout %s not understood for raid0.\n", ++ optarg); ++ exit(2); ++ } ++ break; + case 5: + s.layout = map_name(r5layout, optarg); + if (s.layout == UnSet) { +diff --git a/mdadm.h b/mdadm.h +index 91f1338..9e98778 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -763,7 +763,8 @@ extern int restore_stripes(int *dest, unsigned long long *offsets, + + extern char *map_num(mapping_t *map, int num); + extern int map_name(mapping_t *map, char *name); +-extern mapping_t r5layout[], r6layout[], pers[], modes[], faultylayout[]; ++extern mapping_t r0layout[], r5layout[], r6layout[], ++ pers[], modes[], faultylayout[]; + extern mapping_t consistency_policies[], sysfs_array_states[]; + + extern char *map_dev_preferred(int major, int minor, int create, +@@ -1758,6 +1759,11 @@ char *xstrdup(const char *str); + #define makedev(M,m) (((M)<<8) | (m)) + #endif + ++enum r0layout { ++ RAID0_ORIG_LAYOUT = 1, ++ RAID0_ALT_MULTIZONE_LAYOUT = 2, ++}; ++ + /* for raid4/5/6 */ + #define ALGORITHM_LEFT_ASYMMETRIC 0 + #define ALGORITHM_RIGHT_ASYMMETRIC 1 +diff --git a/super0.c b/super0.c +index 6b7c0e3..6af140b 100644 +--- a/super0.c ++++ b/super0.c +@@ -1291,6 +1291,12 @@ static int validate_geometry0(struct supertype *st, int level, + if (*chunk == UnSet) + *chunk = DEFAULT_CHUNK; + ++ if (level == 0 && layout != UnSet) { ++ if (verbose) ++ pr_err("0.90 metadata does not support layouts for RAID0\n"); ++ return 0; ++ } ++ + if (!subdev) + return 1; + +diff --git a/super1.c b/super1.c +index 929466d..cedbb53 100644 +--- a/super1.c ++++ b/super1.c +@@ -43,7 +43,7 @@ struct mdp_superblock_1 { + + __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ + __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ +- __u32 layout; /* only for raid5 currently */ ++ __u32 layout; /* used for raid5, raid6, raid10, and raid0 */ + __u64 size; /* used size of component devices, in 512byte sectors */ + + __u32 chunksize; /* in 512byte sectors */ +@@ -144,6 +144,7 @@ struct misc_dev_info { + #define MD_FEATURE_JOURNAL 512 /* support write journal */ + #define MD_FEATURE_PPL 1024 /* support PPL */ + #define MD_FEATURE_MUTLIPLE_PPLS 2048 /* support for multiple PPLs */ ++#define MD_FEATURE_RAID0_LAYOUT 4096 /* layout is meaningful in RAID0 */ + #define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \ + |MD_FEATURE_RECOVERY_OFFSET \ + |MD_FEATURE_RESHAPE_ACTIVE \ +@@ -155,6 +156,7 @@ struct misc_dev_info { + |MD_FEATURE_JOURNAL \ + |MD_FEATURE_PPL \ + |MD_FEATURE_MULTIPLE_PPLS \ ++ |MD_FEATURE_RAID0_LAYOUT \ + ) + + static int role_from_sb(struct mdp_superblock_1 *sb) +@@ -498,6 +500,11 @@ static void examine_super1(struct supertype *st, char *homehost) + printf(" Events : %llu\n", + (unsigned long long)__le64_to_cpu(sb->events)); + printf("\n"); ++ if (__le32_to_cpu(sb->level) == 0 && ++ (sb->feature_map & __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT))) { ++ c = map_num(r0layout, __le32_to_cpu(sb->layout)); ++ printf(" Layout : %s\n", c?c:"-unknown-"); ++ } + if (__le32_to_cpu(sb->level) == 5) { + c = map_num(r5layout, __le32_to_cpu(sb->layout)); + printf(" Layout : %s\n", c?c:"-unknown-"); +@@ -1646,6 +1653,7 @@ struct devinfo { + int fd; + char *devname; + long long data_offset; ++ unsigned long long dev_size; + mdu_disk_info_t disk; + struct devinfo *next; + }; +@@ -1687,6 +1695,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk, + di->devname = devname; + di->disk = *dk; + di->data_offset = data_offset; ++ get_dev_size(fd, NULL, &di->dev_size); + di->next = NULL; + *dip = di; + +@@ -1888,10 +1897,25 @@ static int write_init_super1(struct supertype *st) + unsigned long long sb_offset; + unsigned long long data_offset; + long bm_offset; ++ int raid0_need_layout = 0; + + for (di = st->info; di; di = di->next) { + if (di->disk.state & (1 << MD_DISK_JOURNAL)) + sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL); ++ if (sb->level == 0 && sb->layout != 0) { ++ struct devinfo *di2 = st->info; ++ unsigned long long s1, s2; ++ s1 = di->dev_size; ++ if (di->data_offset != INVALID_SECTORS) ++ s1 -= di->data_offset; ++ s1 /= __le32_to_cpu(sb->chunksize); ++ s2 = di2->dev_size; ++ if (di2->data_offset != INVALID_SECTORS) ++ s2 -= di2->data_offset; ++ s2 /= __le32_to_cpu(sb->chunksize); ++ if (s1 != s2) ++ raid0_need_layout = 1; ++ } + } + + for (di = st->info; di; di = di->next) { +@@ -2039,6 +2063,10 @@ static int write_init_super1(struct supertype *st) + sb->bblog_offset = 0; + } + ++ /* RAID0 needs a layout if devices aren't all the same size */ ++ if (raid0_need_layout) ++ sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); ++ + sb->sb_csum = calc_sb_1_csum(sb); + rv = store_super1(st, di->fd); + +-- +2.7.5 + diff --git a/SOURCES/0055-Assemble-add-support-for-RAID0-layouts.patch b/SOURCES/0055-Assemble-add-support-for-RAID0-layouts.patch new file mode 100644 index 0000000..c747892 --- /dev/null +++ b/SOURCES/0055-Assemble-add-support-for-RAID0-layouts.patch @@ -0,0 +1,150 @@ +From 027c099fd1a31fb3815e592de75d0791a22353b4 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 4 Nov 2019 14:27:49 +1100 +Subject: [RHEL8.2 PATCH 55/61] Assemble: add support for RAID0 layouts. + +If you have a RAID0 array with varying sized devices +on a kernel before 5.4, you cannot assembling it on +5.4 or later without explicitly setting the layout. +This is now possible with + --update=layout-original (For 3.13 and earlier kernels) +or + --update=layout-alternate (for 3.14 and later kernels) + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Assemble.c | 8 ++++++++ + md.4 | 7 +++++++ + mdadm.8.in | 17 +++++++++++++++++ + mdadm.c | 4 ++++ + super1.c | 12 +++++++++++- + 5 files changed, 47 insertions(+), 1 deletion(-) + +diff --git a/Assemble.c b/Assemble.c +index b2e6914..6b5a7c8 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1031,6 +1031,11 @@ static int start_array(int mdfd, + pr_err("failed to add %s to %s: %s\n", + devices[j].devname, mddev, + strerror(errno)); ++ if (errno == EINVAL && content->array.level == 0 && ++ content->array.layout != 0) { ++ cont_err("Possibly your kernel doesn't support RAID0 layouts.\n"); ++ cont_err("Please upgrade.\n"); ++ } + if (i < content->array.raid_disks * 2 || + i == bestcnt) + okcnt--; +@@ -1220,6 +1225,9 @@ static int start_array(int mdfd, + return 0; + } + pr_err("failed to RUN_ARRAY %s: %s\n", mddev, strerror(errno)); ++ if (errno == 524 /* ENOTSUP */ && ++ content->array.level == 0 && content->array.layout == 0) ++ cont_err("Please use --update=layout-original or --update=layout-alternate\n"); + + if (!enough(content->array.level, content->array.raid_disks, + content->array.layout, 1, avail)) +diff --git a/md.4 b/md.4 +index 6fe2755..0712af2 100644 +--- a/md.4 ++++ b/md.4 +@@ -208,6 +208,13 @@ array, + will record the chosen layout in the metadata in a way that allows newer + kernels to assemble the array without needing a module parameter. + ++To assemble an old array on a new kernel without using the module parameter, ++use either the ++.B "--update=layout-original" ++option or the ++.B "--update=layout-alternate" ++option. ++ + .SS RAID1 + + A RAID1 array is also known as a mirrored set (though mirrors tend to +diff --git a/mdadm.8.in b/mdadm.8.in +index fc9b6a6..6b63bb4 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1213,6 +1213,8 @@ argument given to this flag can be one of + .BR no\-bbl , + .BR ppl , + .BR no\-ppl , ++.BR layout\-original , ++.BR layout\-alternate , + .BR metadata , + or + .BR super\-minor . +@@ -1364,6 +1366,21 @@ The + .B no\-ppl + option will disable PPL in the superblock. + ++The ++.B layout\-original ++and ++.B layout\-alternate ++options are for RAID0 arrays in use before Linux 5.4. If the array was being ++used with Linux 3.13 or earlier, then to assemble the array on a new kernel, ++.B \-\-update=layout\-original ++must be given. If the array was created and used with a kernel from Linux 3.14 to ++Linux 5.3, then ++.B \-\-update=layout\-alternate ++must be given. This only needs to be given once. Subsequent assembly of the array ++will happen normally. ++For more information, see ++.IR md (4). ++ + .TP + .BR \-\-freeze\-reshape + Option is intended to be used in start-up scripts during initrd boot phase. +diff --git a/mdadm.c b/mdadm.c +index e438f9c..256a97e 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -795,6 +795,9 @@ int main(int argc, char *argv[]) + continue; + if (strcmp(c.update, "revert-reshape") == 0) + continue; ++ if (strcmp(c.update, "layout-original") == 0 || ++ strcmp(c.update, "layout-alternate") == 0) ++ continue; + if (strcmp(c.update, "byteorder") == 0) { + if (ss) { + pr_err("must not set metadata type with --update=byteorder.\n"); +@@ -825,6 +828,7 @@ int main(int argc, char *argv[]) + " 'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n" + " 'no-bitmap', 'metadata', 'revert-reshape'\n" + " 'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n" ++ " 'layout-original', 'layout-alternate'\n" + ); + exit(outf == stdout ? 0 : 2); + +diff --git a/super1.c b/super1.c +index cedbb53..e0d80be 100644 +--- a/super1.c ++++ b/super1.c +@@ -1550,7 +1550,17 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->devflags |= FailFast1; + else if (strcmp(update, "nofailfast") == 0) + sb->devflags &= ~FailFast1; +- else ++ else if (strcmp(update, "layout-original") == 0 || ++ strcmp(update, "layout-alternate") == 0) { ++ if (__le32_to_cpu(sb->level) != 0) { ++ pr_err("%s: %s only supported for RAID0\n", ++ devname?:"", update); ++ rv = -1; ++ } else { ++ sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); ++ sb->layout = __cpu_to_le32(update[7] == 'o' ? 1 : 2); ++ } ++ } else + rv = -1; + + sb->sb_csum = calc_sb_1_csum(sb); +-- +2.7.5 + diff --git a/SOURCES/0056-Respect-CROSS_COMPILE-when-CC-is-the-default.patch b/SOURCES/0056-Respect-CROSS_COMPILE-when-CC-is-the-default.patch new file mode 100644 index 0000000..9219ae8 --- /dev/null +++ b/SOURCES/0056-Respect-CROSS_COMPILE-when-CC-is-the-default.patch @@ -0,0 +1,36 @@ +From aced6fc9542077a69b00d05bc9cd66c12fc34950 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Mon, 9 Dec 2019 13:54:13 -0700 +Subject: [RHEL8.2 PATCH 56/61] Respect $(CROSS_COMPILE) when $(CC) is the + default + +Commit 1180ed5 told make to only respect $(CROSS_COMPILE) when $(CC) +was unset. But that will never be the case, as make provides +a default value for $(CC). Change this logic to respect $(CROSS_COMPILE) +when $(CC) is the default. Patch originally by Helmet Grohne. + +Fixes: 1180ed5 ("Makefile: make the CC definition conditional") +Signed-off-by: dann frazier +Signed-off-by: Jes Sorensen +--- + Makefile | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index dfe00b0..a33319a 100644 +--- a/Makefile ++++ b/Makefile +@@ -46,7 +46,9 @@ ifdef COVERITY + COVERITY_FLAGS=-include coverity-gcc-hack.h + endif + +-CC ?= $(CROSS_COMPILE)gcc ++ifeq ($(origin CC),default) ++CC := $(CROSS_COMPILE)gcc ++endif + CXFLAGS ?= -ggdb + CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter + ifdef WARN_UNUSED +-- +2.7.5 + diff --git a/SOURCES/0057-Change-warning-message.patch b/SOURCES/0057-Change-warning-message.patch new file mode 100644 index 0000000..312cc13 --- /dev/null +++ b/SOURCES/0057-Change-warning-message.patch @@ -0,0 +1,39 @@ +From 1a87493014050e3bd94000cd36122c3cadf21270 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Tue, 10 Dec 2019 12:21:21 +0100 +Subject: [RHEL8.2 PATCH 57/61] Change warning message + +In commit 039b7225e6 ("md: allow creation of mdNNN arrays via +md_mod/parameters/new_array") support for name like mdNNN +was added. Special warning, when kernel is unable to handle +request, was added in commit 7105228e19 +("mdadm/mdopen: create new function create_named_array for +writing to new_array"), but it was not adequate enough, +because in this situation mdadm tries to do it in old way. +This commit changes warning to be more relevant when +creating RAID container with "/dev/mdNNN" name and mdadm +back to old approach. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + mdopen.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/mdopen.c b/mdopen.c +index 98c54e4..245be53 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -120,7 +120,8 @@ int create_named_array(char *devnm) + close(fd); + } + if (fd < 0 || n != (int)strlen(devnm)) { +- pr_err("Fail create %s when using %s\n", devnm, new_array_file); ++ pr_err("Fail to create %s when using %s, fallback to creation via node\n", ++ devnm, new_array_file); + return 0; + } + +-- +2.7.5 + diff --git a/SOURCES/0058-Manage-Remove-the-legacy-code-for-md-driver-prior-to.patch b/SOURCES/0058-Manage-Remove-the-legacy-code-for-md-driver-prior-to.patch new file mode 100644 index 0000000..9f664ff --- /dev/null +++ b/SOURCES/0058-Manage-Remove-the-legacy-code-for-md-driver-prior-to.patch @@ -0,0 +1,52 @@ +From 1cc3965d48deb0fb3e0657159c608ffb124643c1 Mon Sep 17 00:00:00 2001 +From: Xiao Yang +Date: Wed, 27 Nov 2019 11:59:24 +0800 +Subject: [RHEL8.2 PATCH 48/61] Manage: Remove the legacy code for md driver + prior to 0.90.03 + +Previous re-add operation only calls ioctl(HOT_ADD_DISK) for array without +metadata(e.g. mdadm -B/--build) when md driver is less than 0.90.02, but +commit 091e8e6 breaks the logic and current re-add operation can call +ioctl(HOT_ADD_DISK) even if md driver is 0.90.03. + +This issue is reproduced by 05r1-re-add-nosuper: +------------------------------------------------ +++ die 'resync or recovery is happening!' +++ echo -e '\n\tERROR: resync or recovery is happening! \n' +ERROR: resync or recovery is happening! +------------------------------------------------ + +Fixes: 091e8e6("Manage: Remove all references to md_get_version()") +Reported-by: kernel test robot +Signed-off-by: Xiao Yang +Signed-off-by: Jes Sorensen +--- + Manage.c | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 21536f5..ffe55f8 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -741,18 +741,6 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + " Adding anyway as --force was given.\n", + dv->devname, devname); + } +- if (!tst->ss->external && array->major_version == 0) { +- if (ioctl(fd, HOT_ADD_DISK, rdev)==0) { +- if (verbose >= 0) +- pr_err("hot added %s\n", +- dv->devname); +- return 1; +- } +- +- pr_err("hot add failed for %s: %s\n", +- dv->devname, strerror(errno)); +- return -1; +- } + + if (array->not_persistent == 0 || tst->ss->external) { + +-- +2.7.5 + diff --git a/SOURCES/0059-imsm-Update-grow-manual.patch b/SOURCES/0059-imsm-Update-grow-manual.patch new file mode 100644 index 0000000..2b54b8f --- /dev/null +++ b/SOURCES/0059-imsm-Update-grow-manual.patch @@ -0,0 +1,43 @@ +From 4431efebabd0dd39f33dc1dd8ada312b8da1c9d8 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Thu, 16 Jan 2020 09:34:44 +0100 +Subject: [RHEL8.2 PATCH 59/61] imsm: Update grow manual. + +Update --grow option description in manual, according to +the supported grow operations by IMSM. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 6b63bb4..ca02a33 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -481,9 +481,7 @@ still be larger than any replacement. + This value can be set with + .B \-\-grow + for RAID level 1/4/5/6 though +-.B CONTAINER +-based arrays such as those with IMSM metadata may not be able to +-support this. ++DDF arrays may not be able to support this. + If the array was created with a size smaller than the currently + active drives, the extra space can be accessed using + .BR \-\-grow . +@@ -2759,9 +2757,7 @@ container format. The number of devices in a container can be + increased - which affects all arrays in the container - or an array + in a container can be converted between levels where those levels are + supported by the container, and the conversion is on of those listed +-above. Resizing arrays in an IMSM container with +-.B "--grow --size" +-is not yet supported. ++above. + + .PP + Notes: +-- +2.7.5 + diff --git a/SOURCES/0060-Add-support-for-Tebibytes.patch b/SOURCES/0060-Add-support-for-Tebibytes.patch new file mode 100644 index 0000000..45d288e --- /dev/null +++ b/SOURCES/0060-Add-support-for-Tebibytes.patch @@ -0,0 +1,192 @@ +From 42e641abeb312a91b841f1b1ea73661e4bd5a31c Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Tue, 21 Jan 2020 10:38:52 +0100 +Subject: [RHEL8.2 PATCH 60/61] Add support for Tebibytes + +Adding support for Tebibytes enables display size of +volumes in Tebibytes and Terabytes when they are +bigger than 2048 GiB (or GB). + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 20 ++++++++++---------- + util.c | 47 +++++++++++++++++++++++++++++++++-------------- + 2 files changed, 43 insertions(+), 24 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index ca02a33..5d00faf 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -467,8 +467,8 @@ If this is not specified + size, though if there is a variance among the drives of greater than 1%, a warning is + issued. + +-A suffix of 'K', 'M' or 'G' can be given to indicate Kilobytes, Megabytes or +-Gigabytes respectively. ++A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, ++Megabytes, Gigabytes or Terabytes respectively. + + Sometimes a replacement drive can be a little smaller than the + original drives though this should be minimised by IDEMA standards. +@@ -532,8 +532,8 @@ problems the array can be made bigger again with no loss with another + .B "\-\-grow \-\-array\-size=" + command. + +-A suffix of 'K', 'M' or 'G' can be given to indicate Kilobytes, Megabytes or +-Gigabytes respectively. ++A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, ++Megabytes, Gigabytes or Terabytes respectively. + A value of + .B max + restores the apparent size of the array to be whatever the real +@@ -551,8 +551,8 @@ This is only meaningful for RAID0, RAID4, RAID5, RAID6, and RAID10. + RAID4, RAID5, RAID6, and RAID10 require the chunk size to be a power + of 2. In any case it must be a multiple of 4KB. + +-A suffix of 'K', 'M' or 'G' can be given to indicate Kilobytes, Megabytes or +-Gigabytes respectively. ++A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, ++Megabytes, Gigabytes or Terabytes respectively. + + .TP + .BR \-\-rounding= +@@ -767,8 +767,8 @@ When using an + bitmap, the chunksize defaults to 64Meg, or larger if necessary to + fit the bitmap into the available space. + +-A suffix of 'K', 'M' or 'G' can be given to indicate Kilobytes, Megabytes or +-Gigabytes respectively. ++A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, ++Megabytes, Gigabytes or Terabytes respectively. + + .TP + .BR \-W ", " \-\-write\-mostly +@@ -857,8 +857,8 @@ an array which was originally created using a different version of + which computed a different offset. + + Setting the offset explicitly over-rides the default. The value given +-is in Kilobytes unless a suffix of 'K', 'M' or 'G' is used to explicitly +-indicate Kilobytes, Megabytes or Gigabytes respectively. ++is in Kilobytes unless a suffix of 'K', 'M', 'G' or 'T' is used to explicitly ++indicate Kilobytes, Megabytes, Gigabytes or Terabytes respectively. + + Since Linux 3.4, + .B \-\-data\-offset +diff --git a/util.c b/util.c +index 64dd409..07f9dc3 100644 +--- a/util.c ++++ b/util.c +@@ -389,7 +389,7 @@ int mdadm_version(char *version) + unsigned long long parse_size(char *size) + { + /* parse 'size' which should be a number optionally +- * followed by 'K', 'M', or 'G'. ++ * followed by 'K', 'M'. 'G' or 'T'. + * Without a suffix, K is assumed. + * Number returned is in sectors (half-K) + * INVALID_SECTORS returned on error. +@@ -411,6 +411,10 @@ unsigned long long parse_size(char *size) + c++; + s *= 1024 * 1024 * 2; + break; ++ case 'T': ++ c++; ++ s *= 1024 * 1024 * 1024 * 2LL; ++ break; + case 's': /* sectors */ + c++; + break; +@@ -893,13 +897,14 @@ char *human_size(long long bytes) + { + static char buf[47]; + +- /* We convert bytes to either centi-M{ega,ibi}bytes or +- * centi-G{igi,ibi}bytes, with appropriate rounding, +- * and then print 1/100th of those as a decimal. ++ /* We convert bytes to either centi-M{ega,ibi}bytes, ++ * centi-G{igi,ibi}bytes or centi-T{era,ebi}bytes ++ * with appropriate rounding, and then print ++ * 1/100th of those as a decimal. + * We allow upto 2048Megabytes before converting to +- * gigabytes, as that shows more precision and isn't ++ * gigabytes and 2048Gigabytes before converting to ++ * terabytes, as that shows more precision and isn't + * too large a number. +- * Terabytes are not yet handled. + */ + + if (bytes < 5000*1024) +@@ -909,11 +914,16 @@ char *human_size(long long bytes) + long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; + snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)", + cMiB/100, cMiB % 100, cMB/100, cMB % 100); +- } else { ++ } else if (bytes < 2*1024LL*1024LL*1024LL*1024LL) { + long cGiB = (bytes * 200LL / (1LL<<30) +1) / 2; + long cGB = (bytes / (1000000000LL/200LL ) +1) /2; + snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)", + cGiB/100, cGiB % 100, cGB/100, cGB % 100); ++ } else { ++ long cTiB = (bytes * 200LL / (1LL<<40) + 1) / 2; ++ long cTB = (bytes / (1000000000000LL / 200LL) + 1) / 2; ++ snprintf(buf, sizeof(buf), " (%ld.%02ld TiB %ld.%02ld TB)", ++ cTiB/100, cTiB % 100, cTB/100, cTB % 100); + } + return buf; + } +@@ -922,13 +932,14 @@ char *human_size_brief(long long bytes, int prefix) + { + static char buf[30]; + +- /* We convert bytes to either centi-M{ega,ibi}bytes or +- * centi-G{igi,ibi}bytes, with appropriate rounding, +- * and then print 1/100th of those as a decimal. ++ /* We convert bytes to either centi-M{ega,ibi}bytes, ++ * centi-G{igi,ibi}bytes or centi-T{era,ebi}bytes ++ * with appropriate rounding, and then print ++ * 1/100th of those as a decimal. + * We allow upto 2048Megabytes before converting to +- * gigabytes, as that shows more precision and isn't ++ * gigabytes and 2048Gigabytes before converting to ++ * terabytes, as that shows more precision and isn't + * too large a number. +- * Terabytes are not yet handled. + * + * If prefix == IEC, we mean prefixes like kibi,mebi,gibi etc. + * If prefix == JEDEC, we mean prefixes like kilo,mega,giga etc. +@@ -941,10 +952,14 @@ char *human_size_brief(long long bytes, int prefix) + long cMiB = (bytes * 200LL / (1LL<<20) +1) /2; + snprintf(buf, sizeof(buf), "%ld.%02ldMiB", + cMiB/100, cMiB % 100); +- } else { ++ } else if (bytes < 2*1024LL*1024LL*1024LL*1024LL) { + long cGiB = (bytes * 200LL / (1LL<<30) +1) /2; + snprintf(buf, sizeof(buf), "%ld.%02ldGiB", + cGiB/100, cGiB % 100); ++ } else { ++ long cTiB = (bytes * 200LL / (1LL<<40) + 1) / 2; ++ snprintf(buf, sizeof(buf), "%ld.%02ldTiB", ++ cTiB/100, cTiB % 100); + } + } + else if (prefix == JEDEC) { +@@ -952,10 +967,14 @@ char *human_size_brief(long long bytes, int prefix) + long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; + snprintf(buf, sizeof(buf), "%ld.%02ldMB", + cMB/100, cMB % 100); +- } else { ++ } else if (bytes < 2*1024LL*1024LL*1024LL*1024LL) { + long cGB = (bytes / (1000000000LL/200LL ) +1) /2; + snprintf(buf, sizeof(buf), "%ld.%02ldGB", + cGB/100, cGB % 100); ++ } else { ++ long cTB = (bytes / (1000000000000LL / 200LL) + 1) / 2; ++ snprintf(buf, sizeof(buf), "%ld.%02ldTB", ++ cTB/100, cTB % 100); + } + } + else +-- +2.7.5 + diff --git a/SOURCES/0061-imsm-fill-working_disks-according-to-metadata.patch b/SOURCES/0061-imsm-fill-working_disks-according-to-metadata.patch new file mode 100644 index 0000000..8171435 --- /dev/null +++ b/SOURCES/0061-imsm-fill-working_disks-according-to-metadata.patch @@ -0,0 +1,65 @@ +From 1e93d0d15913c3fa6d0de5af3fb5e4e3b3f068da Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Fri, 17 Jan 2020 15:24:04 +0100 +Subject: [RHEL8.2 PATCH 61/61] imsm: fill working_disks according to metadata. + +Imsm tracks as "working_disk" each visible drive. +Assemble routine expects that the value will return count +of active member drives recorded in metadata. +As a side effect "--no-degraded" doesn't work correctly for imsm. +Align this field to others. +Added check, if the option --no-degraded is called with --scan. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + mdadm.c | 9 ++++++--- + super-intel.c | 5 ++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/mdadm.c b/mdadm.c +index 256a97e..13dc24e 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1485,9 +1485,12 @@ int main(int argc, char *argv[]) + rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0); + break; + case ASSEMBLE: +- if (devs_found == 1 && ident.uuid_set == 0 && +- ident.super_minor == UnSet && ident.name[0] == 0 && +- !c.scan ) { ++ if (!c.scan && c.runstop == -1) { ++ pr_err("--no-degraded not meaningful without a --scan assembly.\n"); ++ exit(1); ++ } else if (devs_found == 1 && ident.uuid_set == 0 && ++ ident.super_minor == UnSet && ident.name[0] == 0 && ++ !c.scan) { + /* Only a device has been given, so get details from config file */ + struct mddev_ident *array_ident = conf_get_ident(devlist->devname); + if (array_ident == NULL) { +diff --git a/super-intel.c b/super-intel.c +index 5c1f759..47809bc 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7946,7 +7946,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + skip = 1; + if (!skip && (ord & IMSM_ORD_REBUILD)) + recovery_start = 0; +- ++ if (!(ord & IMSM_ORD_REBUILD)) ++ this->array.working_disks++; + /* + * if we skip some disks the array will be assmebled degraded; + * reset resync start to avoid a dirty-degraded +@@ -7988,8 +7989,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + else + this->array.spare_disks++; + } +- if (info_d->recovery_start == MaxSector) +- this->array.working_disks++; + + info_d->events = __le32_to_cpu(mpb->generation_num); + info_d->data_offset = pba_of_lba0(map); +-- +2.7.5 + diff --git a/SOURCES/0062-mdadm.8-add-note-information-for-raid0-growing-opera.patch b/SOURCES/0062-mdadm.8-add-note-information-for-raid0-growing-opera.patch new file mode 100644 index 0000000..ded44c0 --- /dev/null +++ b/SOURCES/0062-mdadm.8-add-note-information-for-raid0-growing-opera.patch @@ -0,0 +1,55 @@ +From 2551061c253b8fd45ee93d1aab3e91d2c7ac9c20 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Mon, 24 Feb 2020 12:34:09 +0100 +Subject: [RHEL7.9 PATCH 62/77] mdadm.8: add note information for raid0 growing + operation + +When growing a raid0 device, if the new component disk size is not +big enough, the grow operation may fail due to lack of backup space. + +The minimum backup space should be larger than: + LCM(old, new) * chunk-size * 2 + +where LCM() is the least common multiple of the old and new count of +component disks, and "* 2" comes from the fact that mdadm refuses to +use more than half of a spare device for backup space. + +There are users reporting such failure when they grew a raid0 array +with small component disk. Neil Brown points out this is not a bug +and how the failure comes. This patch adds note information into +mdadm(8) man page in the Notes part of GROW MODE section to explain +the minimum size requirement of new component disk size or external +backup size. + +Reviewed-by: Petr Vorel +Cc: NeilBrown +Cc: Jes Sorensen +Cc: Paul Menzel +Cc: Wols Lists +Cc: Nix +Signed-off-by: Coly Li +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 5d00faf..a3494a1 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -2768,6 +2768,12 @@ option and it is transparent for assembly feature. + .IP \(bu 4 + Roaming between Windows(R) and Linux systems for IMSM metadata is not + supported during grow process. ++.IP \(bu 4 ++When growing a raid0 device, the new component disk size (or external ++backup size) should be larger than LCM(old, new) * chunk-size * 2, ++where LCM() is the least common multiple of the old and new count of ++component disks, and "* 2" comes from the fact that mdadm refuses to ++use more than half of a spare device for backup space. + + .SS SIZE CHANGES + Normally when an array is built the "size" is taken from the smallest +-- +2.7.5 + diff --git a/SOURCES/0063-Remove-the-legacy-whitespace.patch b/SOURCES/0063-Remove-the-legacy-whitespace.patch new file mode 100644 index 0000000..57890ee --- /dev/null +++ b/SOURCES/0063-Remove-the-legacy-whitespace.patch @@ -0,0 +1,59 @@ +From fd38b8ea80ff8e0317e12d1d70431148ceedd5fd Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 11 Feb 2020 21:44:15 +0800 +Subject: [RHEL7.9 PATCH 63/77] Remove the legacy whitespace + +The whitespace between Environment= and the true value causes confusion. +To avoid confusing other people in future, remove the whitespace to keep +it a simple, unambiguous syntax + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + systemd/mdcheck_continue.service | 2 +- + systemd/mdcheck_start.service | 2 +- + systemd/mdmonitor-oneshot.service | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service +index aa02dde..854317f 100644 +--- a/systemd/mdcheck_continue.service ++++ b/systemd/mdcheck_continue.service +@@ -11,7 +11,7 @@ ConditionPathExistsGlob = /var/lib/mdcheck/MD_UUID_* + + [Service] + Type=oneshot +-Environment= "MDADM_CHECK_DURATION=6 hours" ++Environment="MDADM_CHECK_DURATION=6 hours" + EnvironmentFile=-/run/sysconfig/mdadm + ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh + ExecStart=/usr/share/mdadm/mdcheck --continue --duration ${MDADM_CHECK_DURATION} +diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service +index da62d5f..3bb3d13 100644 +--- a/systemd/mdcheck_start.service ++++ b/systemd/mdcheck_start.service +@@ -11,7 +11,7 @@ Wants=mdcheck_continue.timer + + [Service] + Type=oneshot +-Environment= "MDADM_CHECK_DURATION=6 hours" ++Environment="MDADM_CHECK_DURATION=6 hours" + EnvironmentFile=-/run/sysconfig/mdadm + ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh + ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION} +diff --git a/systemd/mdmonitor-oneshot.service b/systemd/mdmonitor-oneshot.service +index fd469b1..373955a 100644 +--- a/systemd/mdmonitor-oneshot.service ++++ b/systemd/mdmonitor-oneshot.service +@@ -9,7 +9,7 @@ + Description=Reminder for degraded MD arrays + + [Service] +-Environment= MDADM_MONITOR_ARGS=--scan ++Environment=MDADM_MONITOR_ARGS=--scan + EnvironmentFile=-/run/sysconfig/mdadm + ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh + ExecStart=BINDIR/mdadm --monitor --oneshot $MDADM_MONITOR_ARGS +-- +2.7.5 + diff --git a/SOURCES/0064-imsm-pass-subarray-id-to-kill_subarray-function.patch b/SOURCES/0064-imsm-pass-subarray-id-to-kill_subarray-function.patch new file mode 100644 index 0000000..9b9023b --- /dev/null +++ b/SOURCES/0064-imsm-pass-subarray-id-to-kill_subarray-function.patch @@ -0,0 +1,91 @@ +From 3364781b929f571a3dc3a6afed09eb1b03ce607c Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Wed, 19 Feb 2020 10:54:49 +0100 +Subject: [RHEL7.9 PATCH 64/77] imsm: pass subarray id to kill_subarray + function + +After patch b6180160f ("imsm: save current_vol number") +current_vol for imsm is not set and kill_subarray() +cannot determine which volume has to be deleted. +Volume has to be passed as "subarray_id". +The parameter affects only IMSM metadata. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + Kill.c | 2 +- + mdadm.h | 3 ++- + super-ddf.c | 2 +- + super-intel.c | 9 ++++----- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/Kill.c b/Kill.c +index d4767e2..bfd0efd 100644 +--- a/Kill.c ++++ b/Kill.c +@@ -119,7 +119,7 @@ int Kill_subarray(char *dev, char *subarray, int verbose) + st->update_tail = &st->updates; + + /* ok we've found our victim, drop the axe */ +- rv = st->ss->kill_subarray(st); ++ rv = st->ss->kill_subarray(st, subarray); + if (rv) { + if (verbose >= 0) + pr_err("Failed to delete subarray-%s from %s\n", +diff --git a/mdadm.h b/mdadm.h +index 9e98778..d94569f 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1038,7 +1038,8 @@ extern struct superswitch { + /* query the supertype for default geometry */ + void (*default_geometry)(struct supertype *st, int *level, int *layout, int *chunk); /* optional */ + /* Permit subarray's to be deleted from inactive containers */ +- int (*kill_subarray)(struct supertype *st); /* optional */ ++ int (*kill_subarray)(struct supertype *st, ++ char *subarray_id); /* optional */ + /* Permit subarray's to be modified */ + int (*update_subarray)(struct supertype *st, char *subarray, + char *update, struct mddev_ident *ident); /* optional */ +diff --git a/super-ddf.c b/super-ddf.c +index 7802063..7cd5702 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -4446,7 +4446,7 @@ static int _kill_subarray_ddf(struct ddf_super *ddf, const char *guid) + return 0; + } + +-static int kill_subarray_ddf(struct supertype *st) ++static int kill_subarray_ddf(struct supertype *st, char *subarray_id) + { + struct ddf_super *ddf = st->sb; + /* +diff --git a/super-intel.c b/super-intel.c +index 47809bc..e4d2122 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7600,18 +7600,17 @@ static void default_geometry_imsm(struct supertype *st, int *level, int *layout, + + static void handle_missing(struct intel_super *super, struct imsm_dev *dev); + +-static int kill_subarray_imsm(struct supertype *st) ++static int kill_subarray_imsm(struct supertype *st, char *subarray_id) + { +- /* remove the subarray currently referenced by ->current_vol */ ++ /* remove the subarray currently referenced by subarray_id */ + __u8 i; + struct intel_dev **dp; + struct intel_super *super = st->sb; +- __u8 current_vol = super->current_vol; ++ __u8 current_vol = strtoul(subarray_id, NULL, 10); + struct imsm_super *mpb = super->anchor; + +- if (super->current_vol < 0) ++ if (mpb->num_raid_devs == 0) + return 2; +- super->current_vol = -1; /* invalidate subarray cursor */ + + /* block deletions that would change the uuid of active subarrays + * +-- +2.7.5 + diff --git a/SOURCES/0065-imsm-Remove-dump-restore-implementation.patch b/SOURCES/0065-imsm-Remove-dump-restore-implementation.patch new file mode 100644 index 0000000..55cd2d7 --- /dev/null +++ b/SOURCES/0065-imsm-Remove-dump-restore-implementation.patch @@ -0,0 +1,91 @@ +From 45c43276d02a32876c7e1f9f0d04580595141b3d Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Wed, 19 Feb 2020 11:13:17 +0100 +Subject: [RHEL7.9 PATCH 65/77] imsm: Remove --dump/--restore implementation + +Functionalities --dump and --restore are not supported. +Remove dead code from imsm. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + super-intel.c | 56 -------------------------------------------------------- + 1 file changed, 56 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index e4d2122..c9a1af5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2128,61 +2128,6 @@ static void export_examine_super_imsm(struct supertype *st) + printf("MD_DEVICES=%u\n", mpb->num_disks); + } + +-static int copy_metadata_imsm(struct supertype *st, int from, int to) +-{ +- /* The second last sector of the device contains +- * the "struct imsm_super" metadata. +- * This contains mpb_size which is the size in bytes of the +- * extended metadata. This is located immediately before +- * the imsm_super. +- * We want to read all that, plus the last sector which +- * may contain a migration record, and write it all +- * to the target. +- */ +- void *buf; +- unsigned long long dsize, offset; +- int sectors; +- struct imsm_super *sb; +- struct intel_super *super = st->sb; +- unsigned int sector_size = super->sector_size; +- unsigned int written = 0; +- +- if (posix_memalign(&buf, MAX_SECTOR_SIZE, MAX_SECTOR_SIZE) != 0) +- return 1; +- +- if (!get_dev_size(from, NULL, &dsize)) +- goto err; +- +- if (lseek64(from, dsize-(2*sector_size), 0) < 0) +- goto err; +- if ((unsigned int)read(from, buf, sector_size) != sector_size) +- goto err; +- sb = buf; +- if (strncmp((char*)sb->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0) +- goto err; +- +- sectors = mpb_sectors(sb, sector_size) + 2; +- offset = dsize - sectors * sector_size; +- if (lseek64(from, offset, 0) < 0 || +- lseek64(to, offset, 0) < 0) +- goto err; +- while (written < sectors * sector_size) { +- int n = sectors*sector_size - written; +- if (n > 4096) +- n = 4096; +- if (read(from, buf, n) != n) +- goto err; +- if (write(to, buf, n) != n) +- goto err; +- written += n; +- } +- free(buf); +- return 0; +-err: +- free(buf); +- return 1; +-} +- + static void detail_super_imsm(struct supertype *st, char *homehost, + char *subarray) + { +@@ -12270,7 +12215,6 @@ struct superswitch super_imsm = { + .reshape_super = imsm_reshape_super, + .manage_reshape = imsm_manage_reshape, + .recover_backup = recover_backup_imsm, +- .copy_metadata = copy_metadata_imsm, + .examine_badblocks = examine_badblocks_imsm, + .match_home = match_home_imsm, + .uuid_from_super= uuid_from_super_imsm, +-- +2.7.5 + diff --git a/SOURCES/0066-imsm-Correct-minimal-device-size.patch b/SOURCES/0066-imsm-Correct-minimal-device-size.patch new file mode 100644 index 0000000..377b7c7 --- /dev/null +++ b/SOURCES/0066-imsm-Correct-minimal-device-size.patch @@ -0,0 +1,32 @@ +From 06a6101c0a4d2658798dc42f461ace8e6900f840 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Wed, 11 Mar 2020 15:40:13 +0100 +Subject: [RHEL7.9 PATCH 66/77] imsm: Correct minimal device size. + +Check if given size of member drive is not less than 1 MibiByte. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + super-intel.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/super-intel.c b/super-intel.c +index c9a1af5..6680df2 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7425,7 +7425,10 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + verbose); + } + +- if (size && (size < 1024)) { ++ /* ++ * Size is given in sectors. ++ */ ++ if (size && (size < 2048)) { + pr_err("Given size must be greater than 1M.\n"); + /* Depends on algorithm in Create.c : + * if container was given (dev == NULL) return -1, +-- +2.7.5 + diff --git a/SOURCES/0067-Detail-show-correct-bitmap-info-for-cluster-raid-dev.patch b/SOURCES/0067-Detail-show-correct-bitmap-info-for-cluster-raid-dev.patch new file mode 100644 index 0000000..6fe3786 --- /dev/null +++ b/SOURCES/0067-Detail-show-correct-bitmap-info-for-cluster-raid-dev.patch @@ -0,0 +1,30 @@ +From 9e4494051de3f53228fabae56c116879bff5a0c8 Mon Sep 17 00:00:00 2001 +From: Lidong Zhong +Date: Mon, 16 Mar 2020 10:16:49 +0800 +Subject: [RHEL7.9 PATCH 67/77] Detail: show correct bitmap info for cluster + raid device + +Signed-off-by: Lidong Zhong +Signed-off-by: Jes Sorensen +--- + Detail.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Detail.c b/Detail.c +index 832485f..daec4f1 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -468,7 +468,9 @@ int Detail(char *dev, struct context *c) + if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) { + printf(" Intent Bitmap : %s\n", bmf.pathname); + printf("\n"); +- } else if (array.state & (1< +Date: Tue, 17 Mar 2020 10:20:12 +0100 +Subject: [RHEL7.9 PATCH 68/77] imsm: support the Array Creation Time field in + metadata + +Also present its value in --examine and --examine --export. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: Jes Sorensen +--- + super-intel.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 6680df2..8840fff 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -260,8 +260,9 @@ struct imsm_super { + * (starts at 1) + */ + __u16 filler1; /* 0x4E - 0x4F */ +-#define IMSM_FILLERS 34 +- __u32 filler[IMSM_FILLERS]; /* 0x50 - 0xD7 RAID_MPB_FILLERS */ ++ __u64 creation_time; /* 0x50 - 0x57 Array creation time */ ++#define IMSM_FILLERS 32 ++ __u32 filler[IMSM_FILLERS]; /* 0x58 - 0xD7 RAID_MPB_FILLERS */ + struct imsm_disk disk[1]; /* 0xD8 diskTbl[numDisks] */ + /* here comes imsm_dev[num_raid_devs] */ + /* here comes BBM logs */ +@@ -2014,6 +2015,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost) + __u32 sum; + __u32 reserved = imsm_reserved_sectors(super, super->disks); + struct dl *dl; ++ time_t creation_time; + + strncpy(str, (char *)mpb->sig, MPB_SIG_LEN); + str[MPB_SIG_LEN-1] = '\0'; +@@ -2022,6 +2024,9 @@ static void examine_super_imsm(struct supertype *st, char *homehost) + printf(" Orig Family : %08x\n", __le32_to_cpu(mpb->orig_family_num)); + printf(" Family : %08x\n", __le32_to_cpu(mpb->family_num)); + printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num)); ++ creation_time = __le64_to_cpu(mpb->creation_time); ++ printf(" Creation Time : %.24s\n", ++ creation_time ? ctime(&creation_time) : "Unknown"); + printf(" Attributes : "); + if (imsm_check_attributes(mpb->attributes)) + printf("All supported\n"); +@@ -2126,6 +2131,7 @@ static void export_examine_super_imsm(struct supertype *st) + printf("MD_LEVEL=container\n"); + printf("MD_UUID=%s\n", nbuf+5); + printf("MD_DEVICES=%u\n", mpb->num_disks); ++ printf("MD_CREATION_TIME=%llu\n", __le64_to_cpu(mpb->creation_time)); + } + + static void detail_super_imsm(struct supertype *st, char *homehost, +@@ -5762,6 +5768,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + sum += __gen_imsm_checksum(mpb); + mpb->family_num = __cpu_to_le32(sum); + mpb->orig_family_num = mpb->family_num; ++ mpb->creation_time = __cpu_to_le64((__u64)time(NULL)); + } + super->current_disk = dl; + return 0; +-- +2.7.5 + diff --git a/SOURCES/0069-imsm-show-Subarray-and-Volume-ID-in-examine-output.patch b/SOURCES/0069-imsm-show-Subarray-and-Volume-ID-in-examine-output.patch new file mode 100644 index 0000000..6d329bc --- /dev/null +++ b/SOURCES/0069-imsm-show-Subarray-and-Volume-ID-in-examine-output.patch @@ -0,0 +1,39 @@ +From ba1b3bc80ea555c288f1119e69d9273249967081 Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Tue, 17 Mar 2020 10:21:03 +0100 +Subject: [RHEL7.9 PATCH 69/77] imsm: show Subarray and Volume ID in --examine + output + +Show the index of the subarray as 'Subarray' and the value of the +my_vol_raid_dev_num field as 'Volume ID'. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: Jes Sorensen +--- + super-intel.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/super-intel.c b/super-intel.c +index 8840fff..562a58c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1579,6 +1579,7 @@ static void print_imsm_dev(struct intel_super *super, + + printf("\n"); + printf("[%.16s]:\n", dev->volume); ++ printf(" Subarray : %d\n", super->current_vol); + printf(" UUID : %s\n", uuid); + printf(" RAID Level : %d", get_imsm_raid_level(map)); + if (map2) +@@ -1683,6 +1684,8 @@ static void print_imsm_dev(struct intel_super *super, + printf("Multiple PPLs on journaling drive\n"); + else + printf("\n", dev->rwh_policy); ++ ++ printf(" Volume ID : %u\n", dev->my_vol_raid_dev_num); + } + + static void print_imsm_disk(struct imsm_disk *disk, +-- +2.7.5 + diff --git a/SOURCES/0070-udev-Ignore-change-event-for-imsm.patch b/SOURCES/0070-udev-Ignore-change-event-for-imsm.patch new file mode 100644 index 0000000..c7ae249 --- /dev/null +++ b/SOURCES/0070-udev-Ignore-change-event-for-imsm.patch @@ -0,0 +1,35 @@ +From e1b92ee0de26576a33b20c9dd6ef6bd8cab8e283 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 8 Apr 2020 16:44:52 +0200 +Subject: [RHEL7.9 PATCH 70/77] udev: Ignore change event for imsm + +When adding a device to a container mdadm has to close its file +descriptor before sysfs_add_disk(). This generates change event. +There is race possibility because metadata is already written and other +-I process can place drive differently. As a result device can be added +to two containers simultaneously. +From IMSM perspective there is no need to react for change event. IMSM +doesn't support stacked devices. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + udev-md-raid-assembly.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules +index 9f055ed..d668cdd 100644 +--- a/udev-md-raid-assembly.rules ++++ b/udev-md-raid-assembly.rules +@@ -23,7 +23,7 @@ IMPORT{cmdline}="nodmraid" + ENV{nodmraid}=="?*", GOTO="md_inc_end" + ENV{ID_FS_TYPE}=="ddf_raid_member", GOTO="md_inc" + ENV{noiswmd}=="?*", GOTO="md_inc_end" +-ENV{ID_FS_TYPE}=="isw_raid_member", GOTO="md_inc" ++ENV{ID_FS_TYPE}=="isw_raid_member", ACTION!="change", GOTO="md_inc" + GOTO="md_inc_end" + + LABEL="md_inc" +-- +2.7.5 + diff --git a/SOURCES/0071-Monitor-improve-check_one_sharer-for-checking-duplic.patch b/SOURCES/0071-Monitor-improve-check_one_sharer-for-checking-duplic.patch new file mode 100644 index 0000000..7ded57c --- /dev/null +++ b/SOURCES/0071-Monitor-improve-check_one_sharer-for-checking-duplic.patch @@ -0,0 +1,109 @@ +From 185ec4397e61ad00dd68c841e15eaa8629eb9514 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sat, 11 Apr 2020 00:24:46 +0800 +Subject: [RHEL7.9 PATCH 71/77] Monitor: improve check_one_sharer() for + checking duplicated process + +When running mdadm monitor with scan mode, only one autorebuild process +is allowed. check_one_sharer() checks duplicated process by following +steps, +1) Read autorebuild.pid file, + - if file does not exist, no duplicated process, go to 3). + - if file exists, continue to next step. +2) Read pid number from autorebuild.pid file, then check procfs pid + directory /proc/, + - if the directory does not exist, no duplicated process, go to 3) + - if the directory exists, print error message for duplicated process + and exit this mdadm. +3) Write current pid into autorebuild.pid file, continue to monitor in + scan mode. + +The problem for the above step 2) is, if after system reboots and +another different process happens to have exact same pid number which +autorebuild.pid file records, check_one_sharer() will treat it as a +duplicated mdadm process and returns error with message "Only one +autorebuild process allowed in scan mode, aborting". + +This patch tries to fix the above same-pid-but-different-process issue +by one more step to check the process command name, +1) Read autorebuild.pid file + - if file does not exist, no duplicated process, go to 4). + - if file exists, continue to next step. +2) Read pid number from autorebuild.pid file, then check procfs file + comm with the specific pid directory /proc//comm + - if the file does not exit, it means the directory /proc/ does + not exist, go to 4) + - if the file exits, continue next step +3) Read process command name from /proc//comm, compare the command + name with "mdadm" process name, + - if not equal, no duplicated process, goto 4) + - if strings are equal, print error message for duplicated process + and exit this mdadm. +4) Write current pid into autorebuild.pid file, continue to monitor in + scan mode. + +Now check_one_sharer() returns error for duplicated process only when +the recorded pid from autorebuild.pid exists, and the process has exact +same command name as "mdadm". + +Reported-by: Shinkichi Yamazaki +Signed-off-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Monitor.c | 32 ++++++++++++++++++++------------ + 1 file changed, 20 insertions(+), 12 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index b527165..2d6b3b9 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -301,26 +301,34 @@ static int make_daemon(char *pidfile) + + static int check_one_sharer(int scan) + { +- int pid, rv; ++ int pid; ++ FILE *comm_fp; + FILE *fp; +- char dir[20]; ++ char comm_path[100]; + char path[100]; +- struct stat buf; ++ char comm[20]; ++ + sprintf(path, "%s/autorebuild.pid", MDMON_DIR); + fp = fopen(path, "r"); + if (fp) { + if (fscanf(fp, "%d", &pid) != 1) + pid = -1; +- sprintf(dir, "/proc/%d", pid); +- rv = stat(dir, &buf); +- if (rv != -1) { +- if (scan) { +- pr_err("Only one autorebuild process allowed in scan mode, aborting\n"); +- fclose(fp); +- return 1; +- } else { +- pr_err("Warning: One autorebuild process already running.\n"); ++ snprintf(comm_path, sizeof(comm_path), ++ "/proc/%d/comm", pid); ++ comm_fp = fopen(comm_path, "r"); ++ if (comm_fp) { ++ if (fscanf(comm_fp, "%s", comm) && ++ strncmp(basename(comm), Name, strlen(Name)) == 0) { ++ if (scan) { ++ pr_err("Only one autorebuild process allowed in scan mode, aborting\n"); ++ fclose(comm_fp); ++ fclose(fp); ++ return 1; ++ } else { ++ pr_err("Warning: One autorebuild process already running.\n"); ++ } + } ++ fclose(comm_fp); + } + fclose(fp); + } +-- +2.7.5 + diff --git a/SOURCES/0072-Detail-adding-sync-status-for-cluster-device.patch b/SOURCES/0072-Detail-adding-sync-status-for-cluster-device.patch new file mode 100644 index 0000000..4b4faea --- /dev/null +++ b/SOURCES/0072-Detail-adding-sync-status-for-cluster-device.patch @@ -0,0 +1,85 @@ +From 1c294b5d960abeeb9e0f188af294d019bc82b20e Mon Sep 17 00:00:00 2001 +From: Lidong Zhong +Date: Tue, 14 Apr 2020 16:19:41 +0800 +Subject: [RHEL7.9 PATCH 72/77] Detail: adding sync status for cluster device + +On the node with /proc/mdstat is + +Personalities : [raid1] +md0 : active raid1 sdb[4] sdc[3] sdd[2] + 1046528 blocks super 1.2 [3/2] [UU_] + recover=REMOTE + bitmap: 1/1 pages [4KB], 65536KB chunk + +Let's change the 'State' of 'mdadm -Q -D' accordingly +State : clean, degraded +With this patch, it will be +State : clean, degraded, recovering (REMOTE) + +Signed-off-by: Lidong Zhong +Acked-by: Guoqing Jiang +Signed-off-by: Jes Sorensen +--- + Detail.c | 9 ++++++--- + mdadm.h | 3 ++- + mdstat.c | 2 ++ + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/Detail.c b/Detail.c +index daec4f1..24eeba0 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -498,17 +498,20 @@ int Detail(char *dev, struct context *c) + } else + arrayst = "active"; + +- printf(" State : %s%s%s%s%s%s \n", ++ printf(" State : %s%s%s%s%s%s%s \n", + arrayst, st, + (!e || (e->percent < 0 && + e->percent != RESYNC_PENDING && +- e->percent != RESYNC_DELAYED)) ? ++ e->percent != RESYNC_DELAYED && ++ e->percent != RESYNC_REMOTE)) ? + "" : sync_action[e->resync], + larray_size ? "": ", Not Started", + (e && e->percent == RESYNC_DELAYED) ? + " (DELAYED)": "", + (e && e->percent == RESYNC_PENDING) ? +- " (PENDING)": ""); ++ " (PENDING)": "", ++ (e && e->percent == RESYNC_REMOTE) ? ++ " (REMOTE)": ""); + } else if (inactive && !is_container) { + printf(" State : inactive\n"); + } +diff --git a/mdadm.h b/mdadm.h +index d94569f..399478b 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1815,7 +1815,8 @@ enum r0layout { + #define RESYNC_NONE -1 + #define RESYNC_DELAYED -2 + #define RESYNC_PENDING -3 +-#define RESYNC_UNKNOWN -4 ++#define RESYNC_REMOTE -4 ++#define RESYNC_UNKNOWN -5 + + /* When using "GET_DISK_INFO" it isn't certain how high + * we need to check. So we impose an absolute limit of +diff --git a/mdstat.c b/mdstat.c +index 7e600d0..20577a3 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -257,6 +257,8 @@ struct mdstat_ent *mdstat_read(int hold, int start) + ent->percent = RESYNC_DELAYED; + if (l > 8 && strcmp(w+l-8, "=PENDING") == 0) + ent->percent = RESYNC_PENDING; ++ if (l > 7 && strcmp(w+l-7, "=REMOTE") == 0) ++ ent->percent = RESYNC_REMOTE; + } else if (ent->percent == RESYNC_NONE && + w[0] >= '0' && + w[0] <= '9' && +-- +2.7.5 + diff --git a/SOURCES/0073-Manage-imsm-Write-metadata-before-add.patch b/SOURCES/0073-Manage-imsm-Write-metadata-before-add.patch new file mode 100644 index 0000000..463e9d8 --- /dev/null +++ b/SOURCES/0073-Manage-imsm-Write-metadata-before-add.patch @@ -0,0 +1,164 @@ +From 12724c018c964596aa277489fd287d5c3506361a Mon Sep 17 00:00:00 2001 +From: Tkaczyk Mariusz +Date: Fri, 17 Apr 2020 13:55:55 +0200 +Subject: [RHEL7.9 PATCH 73/77] Manage, imsm: Write metadata before add + +New drive in container always appears as spare. Manager is able to +handle that, and queues appropriative update to monitor. +No update from mdadm side has to be processed, just insert the drive and +ping the mdmon. Metadata has to be written if no mdmon is running (case +for Raid0 or container without arrays). + +If bare drive is added very early on startup (by custom bare rule), +there is possiblity that mdmon was not restarted after switch root. Old +one is not able to handle new drive. New one fails because there is +drive without metadata in container and metadata cannot be loaded. + +To prevent this, write spare metadata before adding device +to container. Mdmon will overwrite it (same case as spare migration, +if drive appears it writes the most recent metadata). +Metadata has to be written only on new drive before sysfs_add_disk(), +don't race with mdmon if running. + +Signed-off-by: Tkaczyk Mariusz +Signed-off-by: Jes Sorensen +--- + Manage.c | 6 +----- + super-intel.c | 66 ++++++++++++++++++++++++++++++++++++++--------------------- + 2 files changed, 44 insertions(+), 28 deletions(-) + +diff --git a/Manage.c b/Manage.c +index b22c396..0a5f09b 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -994,17 +994,13 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + + Kill(dv->devname, NULL, 0, -1, 0); + dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); +- if (mdmon_running(tst->container_devnm)) +- tst->update_tail = &tst->updates; + if (tst->ss->add_to_super(tst, &disc, dfd, + dv->devname, INVALID_SECTORS)) { + close(dfd); + close(container_fd); + return -1; + } +- if (tst->update_tail) +- flush_metadata_updates(tst); +- else ++ if (!mdmon_running(tst->container_devnm)) + tst->ss->sync_metadata(tst); + + sra = sysfs_read(container_fd, NULL, 0); +diff --git a/super-intel.c b/super-intel.c +index 562a58c..3a73d2b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5809,6 +5809,9 @@ int mark_spare(struct dl *disk) + return ret_val; + } + ++ ++static int write_super_imsm_spare(struct intel_super *super, struct dl *d); ++ + static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + int fd, char *devname, + unsigned long long data_offset) +@@ -5938,9 +5941,13 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + dd->next = super->disk_mgmt_list; + super->disk_mgmt_list = dd; + } else { ++ /* this is called outside of mdmon ++ * write initial spare metadata ++ * mdmon will overwrite it. ++ */ + dd->next = super->disks; + super->disks = dd; +- super->updates_pending++; ++ write_super_imsm_spare(super, dd); + } + + return 0; +@@ -5979,15 +5986,15 @@ static union { + struct imsm_super anchor; + } spare_record __attribute__ ((aligned(MAX_SECTOR_SIZE))); + +-/* spare records have their own family number and do not have any defined raid +- * devices +- */ +-static int write_super_imsm_spares(struct intel_super *super, int doclose) ++ ++static int write_super_imsm_spare(struct intel_super *super, struct dl *d) + { + struct imsm_super *mpb = super->anchor; + struct imsm_super *spare = &spare_record.anchor; + __u32 sum; +- struct dl *d; ++ ++ if (d->index != -1) ++ return 1; + + spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super)); + spare->generation_num = __cpu_to_le32(1UL); +@@ -6000,28 +6007,41 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose) + snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH, + MPB_SIGNATURE MPB_VERSION_RAID0); + +- for (d = super->disks; d; d = d->next) { +- if (d->index != -1) +- continue; ++ spare->disk[0] = d->disk; ++ if (__le32_to_cpu(d->disk.total_blocks_hi) > 0) ++ spare->attributes |= MPB_ATTRIB_2TB_DISK; + +- spare->disk[0] = d->disk; +- if (__le32_to_cpu(d->disk.total_blocks_hi) > 0) +- spare->attributes |= MPB_ATTRIB_2TB_DISK; ++ if (super->sector_size == 4096) ++ convert_to_4k_imsm_disk(&spare->disk[0]); + +- if (super->sector_size == 4096) +- convert_to_4k_imsm_disk(&spare->disk[0]); ++ sum = __gen_imsm_checksum(spare); ++ spare->family_num = __cpu_to_le32(sum); ++ spare->orig_family_num = 0; ++ sum = __gen_imsm_checksum(spare); ++ spare->check_sum = __cpu_to_le32(sum); + +- sum = __gen_imsm_checksum(spare); +- spare->family_num = __cpu_to_le32(sum); +- spare->orig_family_num = 0; +- sum = __gen_imsm_checksum(spare); +- spare->check_sum = __cpu_to_le32(sum); ++ if (store_imsm_mpb(d->fd, spare)) { ++ pr_err("failed for device %d:%d %s\n", ++ d->major, d->minor, strerror(errno)); ++ return 1; ++ } ++ ++ return 0; ++} ++/* spare records have their own family number and do not have any defined raid ++ * devices ++ */ ++static int write_super_imsm_spares(struct intel_super *super, int doclose) ++{ ++ struct dl *d; ++ ++ for (d = super->disks; d; d = d->next) { ++ if (d->index != -1) ++ continue; + +- if (store_imsm_mpb(d->fd, spare)) { +- pr_err("failed for device %d:%d %s\n", +- d->major, d->minor, strerror(errno)); ++ if (write_super_imsm_spare(super, d)) + return 1; +- } ++ + if (doclose) { + close(d->fd); + d->fd = -1; +-- +2.7.5 + diff --git a/SOURCES/0074-Assemble-print-error-message-if-mdadm-fails-assembli.patch b/SOURCES/0074-Assemble-print-error-message-if-mdadm-fails-assembli.patch new file mode 100644 index 0000000..7519aad --- /dev/null +++ b/SOURCES/0074-Assemble-print-error-message-if-mdadm-fails-assembli.patch @@ -0,0 +1,57 @@ +From 5cfb79dea26d9d7266f79c7c196a1a9f70c16a28 Mon Sep 17 00:00:00 2001 +From: Gioh Kim +Date: Tue, 16 Apr 2019 18:08:17 +0200 +Subject: [RHEL7.9 PATCH 74/77] Assemble: print error message if mdadm fails + assembling with --uuid option + +When mdadm tries to assemble one working device and one zeroed-out device, +it failed but print successful message because there is --uuid option. + +Following script always reproduce it. + +dd if=/dev/zero of=/dev/ram0 oflag=direct +dd if=/dev/zero of=/dev/ram1 oflag=direct +./mdadm -C /dev/md111 -e 1.2 --uuid="12345678:12345678:12345678:12345678" \ + -l1 -n2 /dev/ram0 /dev/ram1 +./mdadm -S /dev/md111 +dd if=/dev/zero of=/dev/ram1 oflag=direct +./mdadm -A /dev/md111 --uuid="12345678:12345678:12345678:12345678" \ + /dev/ram0 /dev/ram1 + +Following is message from mdadm. + +mdadm: No super block found on /dev/ram1 (Expected magic a92b4efc, got 00000000) +mdadm: no RAID superblock on /dev/ram1 +mdadm: /dev/md111 assembled from 1 drive - need all 2 to start it (use --run to insist). + +The mdadm say that it assembled but mdadm does not create /dev/md111. +The message is wrong. + +After applying this patch, mdadm reports error correctly as following. + +mdadm: No super block found on /dev/ram1 (Expected magic a92b4efc, got 00000000) +mdadm: no RAID superblock on /dev/ram1 +mdadm: /dev/ram1 has no superblock - assembly aborted + +Signed-off-by: Gioh Kim +Signed-off-by: Jes Sorensen +--- + Assemble.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Assemble.c b/Assemble.c +index 6b5a7c8..2ed5884 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -269,7 +269,7 @@ static int select_devices(struct mddev_dev *devlist, + if (auto_assem || !inargv) + /* Ignore unrecognised devices during auto-assembly */ + goto loop; +- if (ident->uuid_set || ident->name[0] || ++ if (ident->name[0] || + ident->super_minor != UnSet) + /* Ignore unrecognised device if looking for + * specific array */ +-- +2.7.5 + diff --git a/SOURCES/0075-clean-up-meaning-of-small-typo.patch b/SOURCES/0075-clean-up-meaning-of-small-typo.patch new file mode 100644 index 0000000..c5cd7f4 --- /dev/null +++ b/SOURCES/0075-clean-up-meaning-of-small-typo.patch @@ -0,0 +1,29 @@ +From ec7d7ceefc1c2b9ba82cac1ba0f6a34d41a4a913 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Mon, 4 May 2020 12:27:45 -0400 +Subject: [RHEL7.9 PATCH 75/77] clean up meaning of small typo + +Clean up the typo which leads to wrong understanding. + +Signed-off-by: Nigel Croxon +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index a3494a1..9e7cb96 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -2878,7 +2878,7 @@ operation, as described below under LAYOUT CHANGES. + + .SS CHUNK-SIZE AND LAYOUT CHANGES + +-Changing the chunk-size of layout without also changing the number of ++Changing the chunk-size or layout without also changing the number of + devices as the same time will involve re-writing all blocks in-place. + To ensure against data loss in the case of a crash, a + .B --backup-file +-- +2.7.5 + diff --git a/SOURCES/0076-Assemble.c-respect-force-flag.patch b/SOURCES/0076-Assemble.c-respect-force-flag.patch new file mode 100644 index 0000000..44e825d --- /dev/null +++ b/SOURCES/0076-Assemble.c-respect-force-flag.patch @@ -0,0 +1,95 @@ +From 7b99edab2834d5d08ef774b4cff784caaa1a186f Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 5 May 2020 12:17:17 +0200 +Subject: [RHEL7.9 PATCH 76/77] Assemble.c: respect force flag. + +If the array is dirty handler will set resync_start to 0 to inform kernel +that resync is needed. RWH affects only raid456 module, for other +levels array will be started even array is degraded and resync cannot be +performed. + +Force is really meaningful for raid456. If array is degraded and resync +is requested, kernel will reject an attempt to start the array. To +respect force, it has to be marked as clean (this will be done for each +array without PPL) and remove the resync request (only for raid 456). +Data corruption may occur so proper warning is added. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Assemble.c | 51 ++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 38 insertions(+), 13 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 2ed5884..3e5d4e6 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -2030,6 +2030,15 @@ int assemble_container_content(struct supertype *st, int mdfd, + free(avail); + return err; + } ++ } else if (c->force) { ++ /* Set the array as 'clean' so that we can proceed with starting ++ * it even if we don't have all devices. Mdmon doesn't care ++ * if the dirty flag is set in metadata, it will start managing ++ * it anyway. ++ * This is really important for raid456 (RWH case), other levels ++ * are started anyway. ++ */ ++ content->array.state |= 1; + } + + if (enough(content->array.level, content->array.raid_disks, +@@ -2049,20 +2058,36 @@ int assemble_container_content(struct supertype *st, int mdfd, + } + free(avail); + +- if (c->runstop <= 0 && +- (working + preexist + expansion) < +- content->array.working_disks) { +- if (c->export && result) +- *result |= INCR_UNSAFE; +- else if (c->verbose >= 0) { +- pr_err("%s assembled with %d device%s", +- chosen_name, preexist + working, +- preexist + working == 1 ? "":"s"); +- if (preexist) +- fprintf(stderr, " (%d new)", working); +- fprintf(stderr, " but not safe to start\n"); ++ if ((working + preexist + expansion) < content->array.working_disks) { ++ if (c->runstop <= 0) { ++ if (c->export && result) ++ *result |= INCR_UNSAFE; ++ else if (c->verbose >= 0) { ++ pr_err("%s assembled with %d device%s", ++ chosen_name, preexist + working, ++ preexist + working == 1 ? "":"s"); ++ if (preexist) ++ fprintf(stderr, " (%d new)", working); ++ fprintf(stderr, " but not safe to start\n"); ++ if (c->force) ++ pr_err("Consider --run to start array as degraded.\n"); ++ } ++ return 1; ++ } else if (content->array.level >= 4 && ++ content->array.level <= 6 && ++ content->resync_start != MaxSector && ++ c->force) { ++ /* Don't inform the kernel that the array is not ++ * clean and requires resync. ++ */ ++ content->resync_start = MaxSector; ++ err = sysfs_set_num(content, NULL, "resync_start", ++ MaxSector); ++ if (err) ++ return 1; ++ pr_err("%s array state forced to clean. It may cause data corruption.\n", ++ chosen_name); + } +- return 1; + } + + +-- +2.7.5 + diff --git a/SOURCES/0077-mdcheck-Log-when-done.patch b/SOURCES/0077-mdcheck-Log-when-done.patch new file mode 100644 index 0000000..d50c71a --- /dev/null +++ b/SOURCES/0077-mdcheck-Log-when-done.patch @@ -0,0 +1,45 @@ +From 3b7aae927bdb6e150d1aaf3aaf0d183a06abda0b Mon Sep 17 00:00:00 2001 +From: Donald Buczek +Date: Wed, 13 May 2020 15:16:46 +0200 +Subject: [RHEL7.9 PATCH 77/77] mdcheck: Log when done + +Currently mdcheck (when called with `--duration`) logs only the +beginning of the check, the pausing and the continuation but not the +completion. + +So, log the completion, too, so that it can be determined how long the +raid check took. + + 2020-05-08T18:00:02+02:00 deadpool root: mdcheck start checking /dev/md0 + 2020-05-08T18:00:02+02:00 deadpool root: mdcheck start checking /dev/md1 + 2020-05-09T15:32:04+02:00 deadpool root: mdcheck finished checking /dev/md1 + 2020-05-09T17:38:04+02:00 deadpool root: mdcheck finished checking /dev/md0 + +Cc: linux-raid@vger.kernel.org +Signed-off-by: Paul Menzel +Signed-off-by: Jes Sorensen +--- + misc/mdcheck | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/misc/mdcheck b/misc/mdcheck +index 42d4094..700c3e2 100644 +--- a/misc/mdcheck ++++ b/misc/mdcheck +@@ -125,11 +125,13 @@ do + do + eval fl=\$MD_${i}_fl + eval sys=\$MD_${i}_sys ++ eval dev=\$MD_${i}_dev + + if [ -z "$fl" ]; then continue; fi + + if [ "`cat $sys/md/sync_action`" != 'check' ] + then ++ logger -p daemon.info mdcheck finished checking $dev + eval MD_${i}_fl= + rm -f $fl + continue; +-- +2.7.5 + diff --git a/SOURCES/mdadm.conf b/SOURCES/mdadm.conf index 6200117..3207dda 100644 --- a/SOURCES/mdadm.conf +++ b/SOURCES/mdadm.conf @@ -1 +1 @@ -d /var/run/mdadm 0710 root root - +d /run/mdadm 0710 root root - diff --git a/SOURCES/mdadm_env.sh b/SOURCES/mdadm_env.sh new file mode 100644 index 0000000..c13b48a --- /dev/null +++ b/SOURCES/mdadm_env.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# extract configuration from /etc/sysconfig/mdadm and write +# environment to /run/sysconfig/mdadm to be used by +# systemd unit files. + +MDADM_SCAN="yes" + +# Following adapted from /etc/init.d/mdadmd on openSUSE + +mdadmd_CONFIG=/etc/sysconfig/mdadm +if test -r $mdadmd_CONFIG; then + . $mdadmd_CONFIG +fi + +if [ x$MDADM_DELAY != x"" ]; then + MDADM_DELAY="-d "$MDADM_DELAY; +fi + +if [ x$MDADM_MAIL != x"" ]; then + MDADM_MAIL="-m \"$MDADM_MAIL\"" +fi + +if [ x$MDADM_PROGRAM != x"" ]; then + MDADM_PROGRAM="-p \"$MDADM_PROGRAM\"" +fi + +if [ x$MDADM_SCAN = x"yes" ]; then + MDADM_SCAN="--scan" +else + MDADM_SCAN="" +fi + +if [ x$MDADM_SEND_MAIL_ON_START = x"yes" ]; then + MDADM_SEND_MAIL="-t" +else + MDADM_SEND_MAIL="" +fi + +if [ x$MDADM_CONFIG != x"" ]; then + MDADM_CONFIG="-c \"$MDADM_CONFIG\"" +fi + +mkdir -p /run/sysconfig +echo "MDADM_MONITOR_ARGS=$MDADM_RAIDDEVICES $MDADM_DELAY $MDADM_MAIL $MDADM_PROGRAM $MDADM_SCAN $MDADM_SEND_MAIL $MDADM_CONFIG" > /run/sysconfig/mdadm +if [ -n "$MDADM_CHECK_DURATION" ]; then + echo "MDADM_CHECK_DURATION=$MDADM_CHECK_DURATION" >> /run/sysconfig/mdadm +fi diff --git a/SOURCES/mdcheck b/SOURCES/mdcheck new file mode 100644 index 0000000..42d4094 --- /dev/null +++ b/SOURCES/mdcheck @@ -0,0 +1,164 @@ +#!/bin/bash + +# Copyright (C) 2014-2017 Neil Brown +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# Author: Neil Brown +# Email: + +# This script should be run periodically to automatically +# perform a 'check' on any md arrays. +# +# It supports a 'time budget' such that any incomplete 'check' +# will be checkpointed when that time has expired. +# A subsequent invocation can allow the 'check' to continue. +# +# Options are: +# --continue Don't start new checks, only continue old ones. +# --duration This is passed to "date --date=$duration" to find out +# when to finish +# +# To support '--continue', arrays are identified by UUID and the 'sync_completed' +# value is stored in /var/lib/mdcheck/$UUID + +# convert a /dev/md name into /sys/.../md equivalent +sysname() { + set `ls -lLd $1` + maj=${5%,} + min=$6 + readlink -f /sys/dev/block/$maj:$min +} + +args=$(getopt -o hcd: -l help,continue,duration: -n mdcheck -- "$@") +rv=$? +if [ $rv -ne 0 ]; then exit $rv; fi + +eval set -- $args + +cont= +endtime= +while [ " $1" != " --" ] +do + case $1 in + --help ) + echo >&2 'Usage: mdcheck [--continue] [--duration time-offset]' + echo >&2 ' time-offset must be understood by "date --date"' + exit 0 + ;; + --continue ) cont=yes ;; + --duration ) shift; dur=$1 + endtime=$(date --date "$dur" "+%s") + ;; + esac + shift +done +shift + +# We need a temp file occasionally... +tmp=/var/lib/mdcheck/.md-check-$$ +trap 'rm -f "$tmp"' 0 2 3 15 + + +# firstly, clean out really old state files +mkdir -p /var/lib/mdcheck +find /var/lib/mdcheck -name "MD_UUID*" -type f -mtime +180 -exec rm {} \; + +# Now look at each md device. +cnt=0 +for dev in /dev/md?* +do + [ -e "$dev" ] || continue + sys=`sysname $dev` + if [ ! -f "$sys/md/sync_action" ] + then # cannot check this array + continue + fi + if [ "`cat $sys/md/sync_action`" != 'idle' ] + then # This array is busy + continue + fi + + mdadm --detail --export "$dev" | grep '^MD_UUID=' > $tmp || continue + source $tmp + fl="/var/lib/mdcheck/MD_UUID_$MD_UUID" + if [ -z "$cont" ] + then + start=0 + logger -p daemon.info mdcheck start checking $dev + elif [ -z "$MD_UUID" -o ! -f "$fl" ] + then + # Nothing to continue here + continue + else + start=`cat "$fl"` + logger -p daemon.info mdcheck continue checking $dev from $start + fi + + cnt=$[cnt+1] + eval MD_${cnt}_fl=\$fl + eval MD_${cnt}_sys=\$sys + eval MD_${cnt}_dev=\$dev + echo $start > $fl + echo $start > $sys/md/sync_min + echo check > $sys/md/sync_action +done + +if [ -z "$endtime" ] +then + exit 0 +fi + +while [ `date +%s` -lt $endtime ] +do + any= + for i in `eval echo {1..$cnt}` + do + eval fl=\$MD_${i}_fl + eval sys=\$MD_${i}_sys + + if [ -z "$fl" ]; then continue; fi + + if [ "`cat $sys/md/sync_action`" != 'check' ] + then + eval MD_${i}_fl= + rm -f $fl + continue; + fi + read a rest < $sys/md/sync_completed + echo $a > $fl + any=yes + done + if [ -z "$any" ]; then exit 0; fi + sleep 120 +done + +# We've waited, and there are still checks running. +# Time to stop them. +for i in `eval echo {1..$cnt}` +do + eval fl=\$MD_${i}_fl + eval sys=\$MD_${i}_sys + eval dev=\$MD_${i}_dev + + if [ -z "$fl" ]; then continue; fi + + if [ "`cat $sys/md/sync_action`" != 'check' ] + then + eval MD_${i}_fl= + rm -f $fl + continue; + fi + echo idle > $sys/md/sync_action + cat $sys/md/sync_min > $fl + logger -p daemon.info pause checking $dev at `cat $fl` +done diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec index 8b631e2..19e6d8f 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: 4.1 -Release: 10%{?dist} +Release: 14%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz Source1: mdmonitor.init Source2: raid-check @@ -11,6 +11,8 @@ Source5: mdadm-cron Source6: mdmonitor.service Source7: mdadm.conf Source8: mdadm_event.conf +Source9: mdcheck +Source10: mdadm_env.sh Patch1: 0001-Assemble-keep-MD_DISK_FAILFAST-and-MD_DISK_WRITEMOST.patch Patch2: 0002-Document-PART-POLICY-lines.patch @@ -59,6 +61,36 @@ Patch44: 0044-mdcheck-when-mdcheck_start-is-enabled-enable-mdcheck.patch Patch45: 0045-mdcheck-use-to-pass-variable-to-mdcheck.patch Patch46: 0046-SUSE-mdadm_env.sh-handle-MDADM_CHECK_DURATION.patch Patch47: 0047-super-intel-don-t-mark-structs-packed-unnecessarily.patch +Patch48: 0048-mdcheck-service-can-t-start-succesfully-because-of-s.patch +Patch49: 0049-Remove-last-traces-of-HOT_ADD_DISK.patch +Patch50: 0050-Fix-up-a-few-formatting-issues.patch +Patch51: 0051-Remove-unused-code.patch +Patch52: 0052-imsm-return-correct-uuid-for-volume-in-detail.patch +Patch53: 0053-imsm-Change-the-way-of-printing-nvme-drives-in-detai.patch +Patch54: 0054-Create-add-support-for-RAID0-layouts.patch +Patch55: 0055-Assemble-add-support-for-RAID0-layouts.patch +Patch56: 0056-Respect-CROSS_COMPILE-when-CC-is-the-default.patch +Patch57: 0057-Change-warning-message.patch +Patch58: 0058-Manage-Remove-the-legacy-code-for-md-driver-prior-to.patch +Patch59: 0059-imsm-Update-grow-manual.patch +Patch60: 0060-Add-support-for-Tebibytes.patch +Patch61: 0061-imsm-fill-working_disks-according-to-metadata.patch +Patch62: 0062-mdadm.8-add-note-information-for-raid0-growing-opera.patch +Patch63: 0063-Remove-the-legacy-whitespace.patch +Patch64: 0064-imsm-pass-subarray-id-to-kill_subarray-function.patch +Patch65: 0065-imsm-Remove-dump-restore-implementation.patch +Patch66: 0066-imsm-Correct-minimal-device-size.patch +Patch67: 0067-Detail-show-correct-bitmap-info-for-cluster-raid-dev.patch +Patch68: 0068-imsm-support-the-Array-Creation-Time-field-in-metada.patch +Patch69: 0069-imsm-show-Subarray-and-Volume-ID-in-examine-output.patch +Patch70: 0070-udev-Ignore-change-event-for-imsm.patch +Patch71: 0071-Monitor-improve-check_one_sharer-for-checking-duplic.patch +Patch72: 0072-Detail-adding-sync-status-for-cluster-device.patch +Patch73: 0073-Manage-imsm-Write-metadata-before-add.patch +Patch74: 0074-Assemble-print-error-message-if-mdadm-fails-assembli.patch +Patch75: 0075-clean-up-meaning-of-small-typo.patch +Patch76: 0076-Assemble.c-respect-force-flag.patch +Patch77: 0077-mdcheck-Log-when-done.patch # RHEL customization patches Patch97: mdadm-3.3-udev.patch @@ -136,6 +168,36 @@ file can be used to help with some common tasks. %patch45 -p1 -b .0045 %patch46 -p1 -b .0046 %patch47 -p1 -b .0047 +%patch48 -p1 -b .0048 +%patch49 -p1 -b .0049 +%patch50 -p1 -b .0050 +%patch51 -p1 -b .0051 +%patch52 -p1 -b .0052 +%patch53 -p1 -b .0053 +%patch54 -p1 -b .0054 +%patch55 -p1 -b .0055 +%patch56 -p1 -b .0056 +%patch57 -p1 -b .0057 +%patch58 -p1 -b .0058 +%patch59 -p1 -b .0059 +%patch60 -p1 -b .0060 +%patch61 -p1 -b .0061 +%patch62 -p1 -b .0062 +%patch63 -p1 -b .0063 +%patch64 -p1 -b .0064 +%patch65 -p1 -b .0065 +%patch66 -p1 -b .0066 +%patch67 -p1 -b .0067 +%patch68 -p1 -b .0068 +%patch69 -p1 -b .0069 +%patch70 -p1 -b .0070 +%patch71 -p1 -b .0071 +%patch72 -p1 -b .0072 +%patch73 -p1 -b .0073 +%patch74 -p1 -b .0074 +%patch75 -p1 -b .0075 +%patch76 -p1 -b .0076 +%patch77 -p1 -b .0077 # RHEL customization patches %patch97 -p1 -b .udev @@ -152,6 +214,10 @@ install -Dp -m 644 %{SOURCE3} %{buildroot}%{_udevrulesdir}/65-md-incremental.rul install -Dp -m 644 %{SOURCE4} %{buildroot}%{_sysconfdir}/sysconfig/raid-check install -Dp -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/cron.d/raid-check mkdir -p -m 710 %{buildroot}/var/run/mdadm +mkdir -p -m 700 %{buildroot}/usr/share/mdadm +mkdir -p -m 700 %{buildroot}/usr/lib/mdadm +install -Dp -m 755 %{SOURCE9} %{buildroot}/usr/share/mdadm/mdcheck +install -Dp -m 755 %{SOURCE10} %{buildroot}/usr/lib/mdadm/mdadm_env.sh # systemd mkdir -p %{buildroot}%{_unitdir} @@ -199,13 +265,31 @@ rm -rf %{buildroot} %dir %{_localstatedir}/run/%{name}/ %config(noreplace) %{_tmpfilesdir}/%{name}.conf /etc/libreport/events.d/* +/usr/share/mdadm/mdcheck +/usr/lib/mdadm/mdadm_env.sh %changelog +* Fri Jun 05 2020 Xiao Ni - 4.1.14 +- Update to latest upstream +- Resolves rhbz#1780501 + +* Fri Feb 28 2020 Xiao Ni - 4.1.13 +- Remove the unnecessary whitespace in .service file +- Resolves rhbz#1803470 + +* Tue Feb 11 2020 Xiao Ni - 4.1.12 +- Update mdadm to latest upstream && change tmpfiles directory && correct changelog date +- Resolves rhbz#1800521 and rhbz#1657265 + +* Sun Feb 09 2020 Xiao Ni - 4.1.11 +- mdcheck start service can't start +- Resolves rhbz#1769823 + * Fri Nov 15 2019 Xiao Ni - 4.1.10 - Update mdadm to latest upstream - Resolves rhbz#1721937 -* Thu Jul 10 2019 Xiao Ni - 4.1.9 +* Wed Jul 10 2019 Xiao Ni - 4.1.9 - Add --incremental for ddf member disk in udev rule - Resolves rhbz#1693583