diff --git a/0001-Document-PART-POLICY-lines.patch b/0001-Document-PART-POLICY-lines.patch new file mode 100644 index 0000000..1e86c60 --- /dev/null +++ b/0001-Document-PART-POLICY-lines.patch @@ -0,0 +1,77 @@ +From 6b6112842030309c297a521918d1a2e982426fa3 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 9 Nov 2018 17:12:33 +1100 +Subject: [PATCH 1/5] Document PART-POLICY lines + +PART-POLICY has been accepted in mdadm.conf since the same +time that POLICY was accepted, but it was never documented. +So add the missing documentation. + +Also fix a bug which would have stopped it from working if +anyone had ever tried to use it. + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + mdadm.conf.5 | 24 +++++++++++++++++++++++- + policy.c | 2 +- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/mdadm.conf.5 b/mdadm.conf.5 +index 18512cb0ec7e..47c962ab2071 100644 +--- a/mdadm.conf.5 ++++ b/mdadm.conf.5 +@@ -501,7 +501,7 @@ To update hot plug configuration it is necessary to execute + .B mdadm \-\-udev\-rules + command after changing the config file + +-Key words used in the ++Keywords used in the + .I POLICY + line and supported values are: + +@@ -565,6 +565,28 @@ be automatically added to that array (or it's container) + as above and the disk will become a spare in remaining cases + .RE + ++.TP ++.B PART-POLICY ++This is similar to ++.B POLICY ++and accepts the same keyword assignments. It allows a consistent set ++of policies to applied to each of the partitions of a device. ++ ++A ++.B PART-POLICY ++line should set ++.I type=disk ++and identify the path to one or more disk devices. Each partition on ++these disks will be treated according to the ++.I action= ++setting from this line. If a ++.I domain ++is set in the line, then the domain associated with each patition will ++be based on the domain, but with ++.RB \(dq -part N\(dq ++appended, when N is the partition number for the partition that was ++found. ++ + .SH EXAMPLE + DEVICE /dev/sd[bcdjkl]1 + .br +diff --git a/policy.c b/policy.c +index c0d18a7eca5b..258f39317951 100644 +--- a/policy.c ++++ b/policy.c +@@ -300,7 +300,7 @@ static int path_has_part(char *path, char **part) + l--; + if (l < 5 || strncmp(path+l-5, "-part", 5) != 0) + return 0; +- *part = path+l-4; ++ *part = path+l-5; + return 1; + } + +-- +2.14.0.rc0.dirty + diff --git a/0002-policy-support-devices-with-multiple-paths.patch b/0002-policy-support-devices-with-multiple-paths.patch new file mode 100644 index 0000000..e0312e5 --- /dev/null +++ b/0002-policy-support-devices-with-multiple-paths.patch @@ -0,0 +1,334 @@ +From cd72f9d114da206baa01fd56ff2d8ffcc08f3239 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 9 Nov 2018 17:12:33 +1100 +Subject: [PATCH 2/5] policy: support devices with multiple paths. + +As new releases of Linux some time change the name of +a path, some distros keep "legacy" names as well. This +is useful, but confuses mdadm which assumes each device has +precisely one path. + +So change this assumption: allow a disk to have several +paths, and allow any to match when looking for a policy +which matches a disk. + +Reported-and-tested-by: Mariusz Tkaczyk +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Incremental.c | 5 +- + mdadm.h | 2 +- + policy.c | 163 ++++++++++++++++++++++++++++++++-------------------------- + 3 files changed, 95 insertions(+), 75 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index a4ff7d4bd22d..d4d3c353560d 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1080,6 +1080,7 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + struct supertype *st2 = NULL; + char *devname = NULL; + unsigned long long devsectors; ++ char *pathlist[2]; + + if (de->d_ino == 0 || de->d_name[0] == '.' || + (de->d_type != DT_LNK && de->d_type != DT_UNKNOWN)) +@@ -1094,7 +1095,9 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + /* This is a partition - skip it */ + goto next; + +- pol2 = path_policy(de->d_name, type_disk); ++ pathlist[0] = de->d_name; ++ pathlist[1] = NULL; ++ pol2 = path_policy(pathlist, type_disk); + + domain_merge(&domlist, pol2, st ? st->ss->name : NULL); + if (domain_test(domlist, pol, st ? st->ss->name : NULL) != 1) +diff --git a/mdadm.h b/mdadm.h +index 387e681aa4ed..705bd9b53b3a 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1247,7 +1247,7 @@ extern void policyline(char *line, char *type); + extern void policy_add(char *type, ...); + extern void policy_free(void); + +-extern struct dev_policy *path_policy(char *path, char *type); ++extern struct dev_policy *path_policy(char **paths, char *type); + extern struct dev_policy *disk_policy(struct mdinfo *disk); + extern struct dev_policy *devid_policy(int devid); + extern void dev_policy_free(struct dev_policy *p); +diff --git a/policy.c b/policy.c +index 258f39317951..fa67d5594c04 100644 +--- a/policy.c ++++ b/policy.c +@@ -189,15 +189,17 @@ struct dev_policy *pol_find(struct dev_policy *pol, char *name) + return pol; + } + +-static char *disk_path(struct mdinfo *disk) ++static char **disk_paths(struct mdinfo *disk) + { + struct stat stb; + int prefix_len; + DIR *by_path; + char symlink[PATH_MAX] = "/dev/disk/by-path/"; +- char nm[PATH_MAX]; ++ char **paths; ++ int cnt = 0; + struct dirent *ent; +- int rv; ++ ++ paths = xmalloc(sizeof(*paths) * (cnt+1)); + + by_path = opendir(symlink); + if (by_path) { +@@ -214,22 +216,13 @@ static char *disk_path(struct mdinfo *disk) + continue; + if (stb.st_rdev != makedev(disk->disk.major, disk->disk.minor)) + continue; +- closedir(by_path); +- return xstrdup(ent->d_name); ++ paths[cnt++] = xstrdup(ent->d_name); ++ paths = xrealloc(paths, sizeof(*paths) * (cnt+1)); + } + closedir(by_path); + } +- /* A NULL path isn't really acceptable - use the devname.. */ +- sprintf(symlink, "/sys/dev/block/%d:%d", disk->disk.major, disk->disk.minor); +- rv = readlink(symlink, nm, sizeof(nm)-1); +- if (rv > 0) { +- char *dname; +- nm[rv] = 0; +- dname = strrchr(nm, '/'); +- if (dname) +- return xstrdup(dname + 1); +- } +- return xstrdup("unknown"); ++ paths[cnt] = NULL; ++ return paths; + } + + char type_part[] = "part"; +@@ -246,18 +239,53 @@ static char *disk_type(struct mdinfo *disk) + return type_disk; + } + +-static int pol_match(struct rule *rule, char *path, char *type) ++static int path_has_part(char *path, char **part) ++{ ++ /* check if path ends with "-partNN" and ++ * if it does, place a pointer to "-pathNN" ++ * in 'part'. ++ */ ++ int l; ++ if (!path) ++ return 0; ++ l = strlen(path); ++ while (l > 1 && isdigit(path[l-1])) ++ l--; ++ if (l < 5 || strncmp(path+l-5, "-part", 5) != 0) ++ return 0; ++ *part = path+l-5; ++ return 1; ++} ++ ++static int pol_match(struct rule *rule, char **paths, char *type, char **part) + { +- /* check if this rule matches on path and type */ ++ /* Check if this rule matches on any path and type. ++ * If 'part' is not NULL, then 'path' must end in -partN, which ++ * we ignore for matching, and return in *part on success. ++ */ + int pathok = 0; /* 0 == no path, 1 == match, -1 == no match yet */ + int typeok = 0; + +- while (rule) { ++ for (; rule; rule = rule->next) { + if (rule->name == rule_path) { ++ char *p; ++ int i; + if (pathok == 0) + pathok = -1; +- if (path && fnmatch(rule->value, path, 0) == 0) +- pathok = 1; ++ if (!paths) ++ continue; ++ for (i = 0; paths[i]; i++) { ++ if (part) { ++ if (!path_has_part(paths[i], &p)) ++ continue; ++ *p = '\0'; ++ *part = p+1; ++ } ++ if (fnmatch(rule->value, paths[i], 0) == 0) ++ pathok = 1; ++ if (part) ++ *p = '-'; ++ } + } + if (rule->name == rule_type) { + if (typeok == 0) +@@ -265,7 +293,6 @@ static int pol_match(struct rule *rule, char *path, char *type) + if (type && strcmp(rule->value, type) == 0) + typeok = 1; + } +- rule = rule->next; + } + return pathok >= 0 && typeok >= 0; + } +@@ -286,24 +313,6 @@ static void pol_merge(struct dev_policy **pol, struct rule *rule) + pol_new(pol, r->name, r->value, metadata); + } + +-static int path_has_part(char *path, char **part) +-{ +- /* check if path ends with "-partNN" and +- * if it does, place a pointer to "-pathNN" +- * in 'part'. +- */ +- int l; +- if (!path) +- return 0; +- l = strlen(path); +- while (l > 1 && isdigit(path[l-1])) +- l--; +- if (l < 5 || strncmp(path+l-5, "-part", 5) != 0) +- return 0; +- *part = path+l-5; +- return 1; +-} +- + static void pol_merge_part(struct dev_policy **pol, struct rule *rule, char *part) + { + /* copy any name assignments from rule into pol, appending +@@ -352,7 +361,7 @@ static int config_rules_has_path = 0; + * path_policy() gathers policy information for the + * disk described in the given a 'path' and a 'type'. + */ +-struct dev_policy *path_policy(char *path, char *type) ++struct dev_policy *path_policy(char **paths, char *type) + { + struct pol_rule *rules; + struct dev_policy *pol = NULL; +@@ -361,27 +370,24 @@ struct dev_policy *path_policy(char *path, char *type) + rules = config_rules; + + while (rules) { +- char *part; ++ char *part = NULL; + if (rules->type == rule_policy) +- if (pol_match(rules->rule, path, type)) ++ if (pol_match(rules->rule, paths, type, NULL)) + pol_merge(&pol, rules->rule); + if (rules->type == rule_part && strcmp(type, type_part) == 0) +- if (path_has_part(path, &part)) { +- *part = 0; +- if (pol_match(rules->rule, path, type_disk)) +- pol_merge_part(&pol, rules->rule, part+1); +- *part = '-'; +- } ++ if (pol_match(rules->rule, paths, type_disk, &part)) ++ pol_merge_part(&pol, rules->rule, part); + rules = rules->next; + } + + /* Now add any metadata-specific internal knowledge + * about this path + */ +- for (i=0; path && superlist[i]; i++) ++ for (i=0; paths[0] && superlist[i]; i++) + if (superlist[i]->get_disk_controller_domain) { + const char *d = +- superlist[i]->get_disk_controller_domain(path); ++ superlist[i]->get_disk_controller_domain( ++ paths[0]); + if (d) + pol_new(&pol, pol_domain, d, superlist[i]->name); + } +@@ -400,22 +406,34 @@ void pol_add(struct dev_policy **pol, + pol_dedup(*pol); + } + ++static void free_paths(char **paths) ++{ ++ int i; ++ ++ if (!paths) ++ return; ++ ++ for (i = 0; paths[i]; i++) ++ free(paths[i]); ++ free(paths); ++} ++ + /* + * disk_policy() gathers policy information for the + * disk described in the given mdinfo (disk.{major,minor}). + */ + struct dev_policy *disk_policy(struct mdinfo *disk) + { +- char *path = NULL; ++ char **paths = NULL; + char *type = disk_type(disk); + struct dev_policy *pol = NULL; + + if (config_rules_has_path) +- path = disk_path(disk); ++ paths = disk_paths(disk); + +- pol = path_policy(path, type); ++ pol = path_policy(paths, type); + +- free(path); ++ free_paths(paths); + return pol; + } + +@@ -756,27 +774,26 @@ int policy_check_path(struct mdinfo *disk, struct map_ent *array) + { + char path[PATH_MAX]; + FILE *f = NULL; +- char *id_path = disk_path(disk); +- int rv; ++ char **id_paths = disk_paths(disk); ++ int i; ++ int rv = 0; + +- if (!id_path) +- return 0; ++ for (i = 0; id_paths[i]; i++) { ++ snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_paths[i]); ++ f = fopen(path, "r"); ++ if (!f) ++ continue; + +- snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); +- f = fopen(path, "r"); +- if (!f) { +- free(id_path); +- return 0; ++ rv = fscanf(f, " %s %x:%x:%x:%x\n", ++ array->metadata, ++ array->uuid, ++ array->uuid+1, ++ array->uuid+2, ++ array->uuid+3); ++ fclose(f); ++ break; + } +- +- rv = fscanf(f, " %s %x:%x:%x:%x\n", +- array->metadata, +- array->uuid, +- array->uuid+1, +- array->uuid+2, +- array->uuid+3); +- fclose(f); +- free(id_path); ++ free_paths(id_paths); + return rv == 5; + } + +-- +2.14.0.rc0.dirty + diff --git a/0003-mdcheck-add-systemd-unit-files-to-run-mdcheck.patch b/0003-mdcheck-add-systemd-unit-files-to-run-mdcheck.patch new file mode 100644 index 0000000..6432310 --- /dev/null +++ b/0003-mdcheck-add-systemd-unit-files-to-run-mdcheck.patch @@ -0,0 +1,137 @@ +From 4199d3c629c14866505923d19fa50017ee92d2e1 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 5 Dec 2018 16:35:00 +1100 +Subject: [PATCH 3/5] mdcheck: add systemd unit files to run mdcheck. + +Having the mdcheck script is not use if is never run. +This patch adds systemd unit files so that it can easily +be run on the first Sunday of each month for 6 hours, +then on every subsequent morning until the check is +finished. + +The units still need to be enabled with + systemctl enable mdcheck_start.timer + +The timer will only actually be started when an array +which might need it becomes active. + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Makefile | 5 ++++- + systemd/mdcheck_continue.service | 18 ++++++++++++++++++ + systemd/mdcheck_continue.timer | 13 +++++++++++++ + systemd/mdcheck_start.service | 17 +++++++++++++++++ + systemd/mdcheck_start.timer | 15 +++++++++++++++ + 5 files changed, 67 insertions(+), 1 deletion(-) + create mode 100644 systemd/mdcheck_continue.service + create mode 100644 systemd/mdcheck_continue.timer + create mode 100644 systemd/mdcheck_start.service + create mode 100644 systemd/mdcheck_start.timer + +diff --git a/Makefile b/Makefile +index 2767ac68396d..afb62cc6e3a6 100644 +--- a/Makefile ++++ b/Makefile +@@ -276,7 +276,10 @@ install-udev: udev-md-raid-arrays.rules udev-md-raid-assembly.rules udev-md-raid + + install-systemd: systemd/mdmon@.service + @for file in mdmon@.service mdmonitor.service mdadm-last-resort@.timer \ +- mdadm-last-resort@.service mdadm-grow-continue@.service; \ ++ mdadm-last-resort@.service mdadm-grow-continue@.service \ ++ mdcheck_start.timer mdcheck_start.service \ ++ mdcheck_continue.timer mdcheck_continue.service \ ++ ; \ + do sed -e 's,BINDIR,$(BINDIR),g' systemd/$$file > .install.tmp.2 && \ + $(ECHO) $(INSTALL) -D -m 644 systemd/$$file $(DESTDIR)$(SYSTEMD_DIR)/$$file ; \ + $(INSTALL) -D -m 644 .install.tmp.2 $(DESTDIR)$(SYSTEMD_DIR)/$$file ; \ +diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service +new file mode 100644 +index 000000000000..592c60798f82 +--- /dev/null ++++ b/systemd/mdcheck_continue.service +@@ -0,0 +1,18 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=MD array scrubbing - continuation ++ConditionPathExistsGlob = /var/lib/mdcheck/MD_UUID_* ++ ++[Service] ++Type=oneshot ++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_continue.timer b/systemd/mdcheck_continue.timer +new file mode 100644 +index 000000000000..3ccfd7858a3f +--- /dev/null ++++ b/systemd/mdcheck_continue.timer +@@ -0,0 +1,13 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=MD array scrubbing - continuation ++ ++[Timer] ++OnCalendar= 1:05:00 ++ +diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service +new file mode 100644 +index 000000000000..812141bb5c9a +--- /dev/null ++++ b/systemd/mdcheck_start.service +@@ -0,0 +1,17 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=MD array scrubbing ++Wants=mdcheck_continue.timer ++ ++[Service] ++Type=oneshot ++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/mdcheck_start.timer b/systemd/mdcheck_start.timer +new file mode 100644 +index 000000000000..64807362d649 +--- /dev/null ++++ b/systemd/mdcheck_start.timer +@@ -0,0 +1,15 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=MD array scrubbing ++ ++[Timer] ++OnCalendar=Sun *-*-1..7 1:00:00 ++ ++[Install] ++WantedBy= mdmonitor.service +-- +2.14.0.rc0.dirty + diff --git a/0004-Monitor-add-system-timer-to-run-oneshot-periodically.patch b/0004-Monitor-add-system-timer-to-run-oneshot-periodically.patch new file mode 100644 index 0000000..611a84d --- /dev/null +++ b/0004-Monitor-add-system-timer-to-run-oneshot-periodically.patch @@ -0,0 +1,82 @@ +From 7cd7e91ab3de5aa75dc963cb08b0618c1885cf0d Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 5 Dec 2018 16:35:00 +1100 +Subject: [PATCH 4/5] Monitor: add system timer to run --oneshot periodically + +"mdadm --monitor --oneshot" can be used to get a warning +if there are any degraded arrays. It can be helpful to get +this warning periodically while the condition persists. + +This patch add a systemd service and timer which can +be enabled with + systemctl enable mdmonitor-oneshot.service + +and will then provide daily warnings. + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Makefile | 1 + + systemd/mdmonitor-oneshot.service | 15 +++++++++++++++ + systemd/mdmonitor-oneshot.timer | 15 +++++++++++++++ + 3 files changed, 31 insertions(+) + create mode 100644 systemd/mdmonitor-oneshot.service + create mode 100644 systemd/mdmonitor-oneshot.timer + +diff --git a/Makefile b/Makefile +index afb62cc6e3a6..dfe00b0a0be8 100644 +--- a/Makefile ++++ b/Makefile +@@ -279,6 +279,7 @@ install-systemd: systemd/mdmon@.service + mdadm-last-resort@.service mdadm-grow-continue@.service \ + mdcheck_start.timer mdcheck_start.service \ + mdcheck_continue.timer mdcheck_continue.service \ ++ mdmonitor-oneshot.timer mdmonitor-oneshot.service \ + ; \ + do sed -e 's,BINDIR,$(BINDIR),g' systemd/$$file > .install.tmp.2 && \ + $(ECHO) $(INSTALL) -D -m 644 systemd/$$file $(DESTDIR)$(SYSTEMD_DIR)/$$file ; \ +diff --git a/systemd/mdmonitor-oneshot.service b/systemd/mdmonitor-oneshot.service +new file mode 100644 +index 000000000000..fd469b12cc78 +--- /dev/null ++++ b/systemd/mdmonitor-oneshot.service +@@ -0,0 +1,15 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=Reminder for degraded MD arrays ++ ++[Service] ++Environment= MDADM_MONITOR_ARGS=--scan ++EnvironmentFile=-/run/sysconfig/mdadm ++ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh ++ExecStart=BINDIR/mdadm --monitor --oneshot $MDADM_MONITOR_ARGS +diff --git a/systemd/mdmonitor-oneshot.timer b/systemd/mdmonitor-oneshot.timer +new file mode 100644 +index 000000000000..cb54bdaa8897 +--- /dev/null ++++ b/systemd/mdmonitor-oneshot.timer +@@ -0,0 +1,15 @@ ++# This file is part of mdadm. ++# ++# mdadm 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. ++ ++[Unit] ++Description=Reminder for degraded MD arrays ++ ++[Timer] ++OnCalendar= 2:00:00 ++ ++[Install] ++WantedBy= mdmonitor.service +-- +2.14.0.rc0.dirty + diff --git a/0005-imsm-update-metadata-correctly-while-raid10-double-d.patch b/0005-imsm-update-metadata-correctly-while-raid10-double-d.patch new file mode 100644 index 0000000..b573181 --- /dev/null +++ b/0005-imsm-update-metadata-correctly-while-raid10-double-d.patch @@ -0,0 +1,83 @@ +From d7a1fda2769ba272d89de6caeab35d52b73a9c3c Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 17 Oct 2018 12:11:41 +0200 +Subject: [PATCH 5/5] imsm: update metadata correctly while raid10 double + degradation + +Mdmon calls end_migration() when map state changes from normal to +degraded. It is not valid because in raid 10 double degradation case +mdmon breaks checkpointing but array is still rebuilding. +In this case mdmon has to mark map as degraded and continues marking +recovery checkpoint in metadata. Migration can be finished only if newly +failed device is a rebuilding device. + +Add catching double degraded to degraded transition. Migration is +finished but map state doesn't change, array is still degraded. + +Update failed_disk_num correctly. If double degradation +happens rebuild will start on the lowest slot, but this variable points +to the first failed slot. If second fail happens while rebuild this +variable shouldn't be updated until rebuild is not finished. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + super-intel.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 6438987b778c..d2035ccd8270 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -8136,7 +8136,8 @@ static int mark_failure(struct intel_super *super, + set_imsm_ord_tbl_ent(map2, slot2, + idx | IMSM_ORD_REBUILD); + } +- if (map->failed_disk_num == 0xff) ++ if (map->failed_disk_num == 0xff || ++ (!is_rebuilding(dev) && map->failed_disk_num > slot)) + map->failed_disk_num = slot; + + clear_disk_badblocks(super->bbm_log, ord_to_idx(ord)); +@@ -8558,13 +8559,25 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + break; + } + if (is_rebuilding(dev)) { +- dprintf_cont("while rebuilding."); ++ dprintf_cont("while rebuilding "); + if (map->map_state != map_state) { +- dprintf_cont(" Map state change"); +- end_migration(dev, super, map_state); ++ dprintf_cont("map state change "); ++ if (n == map->failed_disk_num) { ++ dprintf_cont("end migration"); ++ end_migration(dev, super, map_state); ++ } else { ++ dprintf_cont("raid10 double degradation, map state change"); ++ map->map_state = map_state; ++ } + super->updates_pending++; +- } else if (!rebuild_done) { ++ } else if (!rebuild_done) + break; ++ else if (n == map->failed_disk_num) { ++ /* r10 double degraded to degraded transition */ ++ dprintf_cont("raid10 double degradation end migration"); ++ end_migration(dev, super, map_state); ++ a->last_checkpoint = 0; ++ super->updates_pending++; + } + + /* check if recovery is really finished */ +@@ -8575,7 +8588,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + } + if (recovery_not_finished) { + dprintf_cont("\n"); +- dprintf("Rebuild has not finished yet, state not changed"); ++ dprintf_cont("Rebuild has not finished yet, map state changes only if raid10 double degradation happens"); + if (a->last_checkpoint < mdi->recovery_start) { + a->last_checkpoint = + mdi->recovery_start; +-- +2.14.0.rc0.dirty + diff --git a/0006-Grow-avoid-overflow-in-compute_backup_blocks.patch b/0006-Grow-avoid-overflow-in-compute_backup_blocks.patch new file mode 100644 index 0000000..4f32eaf --- /dev/null +++ b/0006-Grow-avoid-overflow-in-compute_backup_blocks.patch @@ -0,0 +1,34 @@ +From 085df42259cba7863cd6ebe5cd0d8492ac5b869e Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 6 Dec 2018 10:35:41 +1100 +Subject: [PATCH] Grow: avoid overflow in compute_backup_blocks() + +With a chunk size of 16Meg and data drive count of 8, +this calculate can easily overflow the 'int' type that +is used for the multiplications. +So force it to use "long" instead. + +Reported-and-tested-by: Ed Spiridonov +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Grow.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index 4436a4d6bd4c..76f82c075e38 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1196,7 +1196,8 @@ unsigned long compute_backup_blocks(int nchunk, int ochunk, + /* Find GCD */ + a = GCD(a, b); + /* LCM == product / GCD */ +- blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a; ++ blocks = (unsigned long)(ochunk/512) * (unsigned long)(nchunk/512) * ++ odata * ndata / a; + + return blocks; + } +-- +2.14.0.rc0.dirty + diff --git a/0007-Grow-report-correct-new-chunk-size.patch b/0007-Grow-report-correct-new-chunk-size.patch new file mode 100644 index 0000000..00e378d --- /dev/null +++ b/0007-Grow-report-correct-new-chunk-size.patch @@ -0,0 +1,30 @@ +From 76d505dec6c9f92564553596fc8350324be82463 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 6 Dec 2018 10:36:28 +1100 +Subject: [PATCH] Grow: report correct new chunk size. + +When using "--grow --chunk=" to change chunk +size, the old chunksize is reported instead of the new. + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + Grow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index 76f82c075e38..363b209d14a3 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -3286,7 +3286,7 @@ static int reshape_array(char *container, int fd, char *devname, + goto release; + } else if (verbose >= 0) + printf("chunk size for %s set to %d\n", +- devname, array.chunk_size); ++ devname, info->new_chunk); + } + unfreeze(st); + return 0; +-- +2.14.0.rc0.dirty + diff --git a/0008-policy.c-prevent-NULL-pointer-referencing.patch b/0008-policy.c-prevent-NULL-pointer-referencing.patch new file mode 100644 index 0000000..350925b --- /dev/null +++ b/0008-policy.c-prevent-NULL-pointer-referencing.patch @@ -0,0 +1,29 @@ +From 179cab343006df996f0a85a542b40e44db0c2e2f Mon Sep 17 00:00:00 2001 +From: Gioh Kim +Date: Fri, 7 Dec 2018 12:04:44 +0100 +Subject: [PATCH] policy.c: prevent NULL pointer referencing + +paths could be NULL and paths[0] should be followed by NULL pointer +checking. + +Signed-off-by: Gioh Kim +--- + policy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/policy.c b/policy.c +index fa67d5594c04..e3a0671f3a3a 100644 +--- a/policy.c ++++ b/policy.c +@@ -383,7 +383,7 @@ struct dev_policy *path_policy(char **paths, char *type) + /* Now add any metadata-specific internal knowledge + * about this path + */ +- for (i=0; paths[0] && superlist[i]; i++) ++ for (i=0; paths && paths[0] && superlist[i]; i++) + if (superlist[i]->get_disk_controller_domain) { + const char *d = + superlist[i]->get_disk_controller_domain( +-- +2.14.0.rc0.dirty + diff --git a/cron.d.mdadm b/cron.d.mdadm deleted file mode 100644 index 726e6df..0000000 --- a/cron.d.mdadm +++ /dev/null @@ -1,10 +0,0 @@ -# -# cron.d/mdadm - regular redundancy checks -# - -# Start checking each month early in the morning. -# Continue each day until all done - -PATH=/sbin:/usr/sbin:/bin:/usr/bin -0 1 * * 0 root source /etc/sysconfig/mdadm; [ -n "$MDADM_CHECK_DURATION" -a -x /usr/share/mdadm/mdcheck -a $(date +\%d) -le 7 ] && /usr/share/mdadm/mdcheck --duration "$MDADM_CHECK_DURATION" -0 1 * * 1-6 root source /etc/sysconfig/mdadm; [ -n "$MDADM_CHECK_DURATION" -a -x /usr/share/mdadm/mdcheck ] && /usr/share/mdadm/mdcheck --continue --duration "$MDADM_CHECK_DURATION" diff --git a/mdadm.changes b/mdadm.changes index 61bc1da..0fb73a7 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,22 @@ +------------------------------------------------------------------- +Mon Dec 10 01:52:35 UTC 2018 - Neil Brown + +- 0001-Document-PART-POLICY-lines.patch + 0002-policy-support-devices-with-multiple-paths.patch + 0008-policy.c-prevent-NULL-pointer-referencing.patch + (bsc#1106078) + +- 0003-mdcheck-add-systemd-unit-files-to-run-mdcheck.patch + 0004-Monitor-add-system-timer-to-run-oneshot-periodically.patch + Remove mdadm.cron + Remove crond.mdadm + (bsc#1115407) + +- 0005-imsm-update-metadata-correctly-while-raid10-double-d.patch + 0006-Grow-avoid-overflow-in-compute_backup_blocks.patch + 0007-Grow-report-correct-new-chunk-size.patch + Other useful upstream patches. + ------------------------------------------------------------------- Wed Oct 17 03:27:21 UTC 2018 - Coly Li diff --git a/mdadm.cron b/mdadm.cron deleted file mode 100644 index f8fe7bc..0000000 --- a/mdadm.cron +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -# Run "mdadm --monitor --oneshot" once a day to ensure -# degraded arrays don't go unnoticed. - -mdadm_BIN=/sbin/mdadm -mdadm_CONFIG=/etc/sysconfig/mdadm - -[ -x $mdadm_BIN ] || exit 0 - -[ -r $mdadm_CONFIG ] && . $mdadm_CONFIG - -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="-s" -else - MDADM_SCAN="" -fi - -if [ x$MDADM_CONFIG != x"" ]; then - MDADM_CONFIG="-c \"$MDADM_CONFIG\"" -fi - -# using --syslog avoids annoying warnings if no MAIL or PROGRAM are given -# in sysconfig or mdadm.conf -eval $mdadm_BIN -F $MDADM_RAIDDEVICES --oneshot --syslog $MDADM_MAIL $MDADM_PROGRAM $MDADM_SCAN $MDADM_SEND_MAIL $MDADM_CONFIG - -exit 0 diff --git a/mdadm.spec b/mdadm.spec index a50cc8a..93b07d2 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -32,7 +32,6 @@ BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(systemd) BuildRequires: pkgconfig(udev) PreReq: %fillup_prereq /sbin/mkinitrd coreutils -Recommends: cron Recommends: smtp_daemon Url: http://www.kernel.org/pub/linux/utils/raid/mdadm/ Summary: Utility for Configuring MD Setup @@ -42,9 +41,15 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build Source: https://www.kernel.org/pub/linux/utils/raid/mdadm/%{name}-%{version}.tar.xz Source1: Software-RAID.HOWTO.tar.bz2 Source2: sysconfig.mdadm -Source3: cron.d.mdadm -Source7: mdadm.cron Patch1: 0001-Makefile-install-mdadm_env.sh-to-usr-lib-mdadm.patch +Patch11: 0001-Document-PART-POLICY-lines.patch +Patch12: 0002-policy-support-devices-with-multiple-paths.patch +Patch13: 0003-mdcheck-add-systemd-unit-files-to-run-mdcheck.patch +Patch14: 0004-Monitor-add-system-timer-to-run-oneshot-periodically.patch +Patch15: 0005-imsm-update-metadata-correctly-while-raid10-double-d.patch +Patch16: 0006-Grow-avoid-overflow-in-compute_backup_blocks.patch +Patch17: 0007-Grow-report-correct-new-chunk-size.patch +Patch18: 0008-policy.c-prevent-NULL-pointer-referencing.patch Patch1001: 1001-display-timeout-status.patch %define _udevdir %(pkg-config --variable=udevdir udev) %define _systemdshutdowndir %{_unitdir}/../system-shutdown @@ -57,6 +62,14 @@ programs but with a very different interface. %prep %setup -q -a1 %patch1 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 %patch1001 -p1 %build @@ -71,16 +84,12 @@ rm -rf %{buildroot}/lib/udev install -d %{buildroot}%{_fillupdir} install -d %{buildroot}/usr/share/mdadm install -m 755 misc/mdcheck %{buildroot}/usr/share/mdadm/mdcheck -install -d %{buildroot}/etc/cron.daily -install -d %{buildroot}/etc/cron.d -install -m 755 %{S:7} %{buildroot}/etc/cron.daily/mdadm -install -m 644 %{S:3} %{buildroot}/etc/cron.d/mdadm install -m 644 %{S:2} %{buildroot}%{_fillupdir}/ install -d %{buildroot}%{_systemdshutdowndir} install -d %{buildroot}%{_sbindir} ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcmdmonitor -%define services mdmonitor.service +%define services mdmonitor.service mdcheck_start.service mdcheck_continue.service mdmonitor-oneshot.service %pre %service_add_pre %services @@ -115,10 +124,6 @@ ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcmdmonitor %{_udevdir}/rules.d/63-md-raid-arrays.rules %{_udevdir}/rules.d/64-md-raid-assembly.rules %{_udevdir}/rules.d/69-md-clustered-confirm-device.rules -%dir /etc/cron.daily -/etc/cron.daily/mdadm -%dir /etc/cron.d -%config /etc/cron.d/mdadm # %%{_systemdshutdowndir}/ is not owned by all versions of systemd-mini. # But we really do not want to pull in a full systemd, so we rather just own # that directory by ourselves too. After all, this is allowed. @@ -129,6 +134,12 @@ ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcmdmonitor %{_unitdir}/mdadm-last-resort@.timer %{_unitdir}/mdadm-last-resort@.service %{_unitdir}/mdadm-grow-continue@.service +%{_unitdir}/mdcheck_continue.service +%{_unitdir}/mdcheck_continue.timer +%{_unitdir}/mdcheck_start.service +%{_unitdir}/mdcheck_start.timer +%{_unitdir}/mdmonitor-oneshot.service +%{_unitdir}/mdmonitor-oneshot.timer %dir %{_libexecdir}/mdadm %{_libexecdir}/mdadm/mdadm_env.sh