You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mdadm/SOURCES/0089-Mdmonitor-Add-helper-f...

407 lines
14 KiB

From cc3df167c599d2ee0c132149c86fc0ad70d9f14e Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:01 +0100
Subject: [PATCH 089/125] Mdmonitor: Add helper functions
Add functions:
- is_email_event(),
- get_syslog_event_priority(),
- sprint_event_message(),
with kernel style comments containing more detailed descriptions.
Also update event syslog priorities to be consistent with man. MoveSpare event was described in man as priority info, while implemented as warning. Move event data into a struct, so that it is passed between different functions if needed.
Sort function declarations alphabetically and remove redundant alert() declaration.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 228 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 158 insertions(+), 70 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 029e9efd..39598ba0 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -73,10 +73,12 @@ enum event {
EVENT_NEW_ARRAY,
EVENT_MOVE_SPARE,
EVENT_TEST_MESSAGE,
+ __SYSLOG_PRIORITY_WARNING,
EVENT_REBUILD_STARTED,
EVENT_REBUILD,
EVENT_REBUILD_FINISHED,
EVENT_SPARES_MISSING,
+ __SYSLOG_PRIORITY_CRITICAL,
EVENT_DEVICE_DISAPPEARED,
EVENT_FAIL,
EVENT_FAIL_SPARE,
@@ -100,18 +102,31 @@ mapping_t events_map[] = {
{NULL, EVENT_UNKNOWN}
};
-static int make_daemon(char *pidfile);
-static int check_one_sharer(int scan);
-static void write_autorebuild_pid(void);
-static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc);
-static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
+struct event_data {
+ enum event event_enum;
+ /*
+ * @event_name: Rebuild event name must be in form "RebuildXX", where XX is rebuild progress.
+ */
+ char event_name[EVENT_NAME_MAX];
+ char message[BUFSIZ];
+ const char *description;
+ const char *dev;
+ const char *disc;
+};
+
static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist);
static void try_spare_migration(struct state *statelist);
static void link_containers_with_subarrays(struct state *list);
static void free_statelist(struct state *statelist);
+static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
+static int check_one_sharer(int scan);
#ifndef NO_LIBUDEV
static int check_udev_activity(void);
#endif
+static void link_containers_with_subarrays(struct state *list);
+static int make_daemon(char *pidfile);
+static void try_spare_migration(struct state *statelist);
+static void write_autorebuild_pid(void);
int Monitor(struct mddev_dev *devlist,
char *mailaddr, char *alert_cmd,
@@ -450,7 +465,80 @@ static void write_autorebuild_pid()
}
}
-static void execute_alert_cmd(const char *event_name, const char *dev, const char *disc)
+#define BASE_MESSAGE "%s event detected on md device %s"
+#define COMPONENT_DEVICE_MESSAGE ", component device %s"
+#define DESCRIPTION_MESSAGE ": %s"
+/*
+ * sprint_event_message() - Writes basic message about detected event to destination ptr.
+ * @dest: message destination, should be at least the size of BUFSIZ
+ * @data: event data
+ *
+ * Return: 0 on success, 1 on error
+ */
+static int sprint_event_message(char *dest, const struct event_data *data)
+{
+ if (!dest || !data)
+ return 1;
+
+ if (data->disc && data->description)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE COMPONENT_DEVICE_MESSAGE DESCRIPTION_MESSAGE,
+ data->event_name, data->dev, data->disc, data->description);
+ else if (data->disc)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE COMPONENT_DEVICE_MESSAGE,
+ data->event_name, data->dev, data->disc);
+ else if (data->description)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE DESCRIPTION_MESSAGE,
+ data->event_name, data->dev, data->description);
+ else
+ snprintf(dest, BUFSIZ, BASE_MESSAGE, data->event_name, data->dev);
+
+ return 0;
+}
+
+/*
+ * get_syslog_event_priority() - Determines event priority.
+ * @event_enum: event to be checked
+ *
+ * Return: LOG_CRIT, LOG_WARNING or LOG_INFO
+ */
+static int get_syslog_event_priority(const enum event event_enum)
+{
+ if (event_enum > __SYSLOG_PRIORITY_CRITICAL)
+ return LOG_CRIT;
+ if (event_enum > __SYSLOG_PRIORITY_WARNING)
+ return LOG_WARNING;
+ return LOG_INFO;
+}
+
+/*
+ * is_email_event() - Determines whether email for event should be sent or not.
+ * @event_enum: event to be checked
+ *
+ * Return: true if email should be sent, false otherwise
+ */
+static bool is_email_event(const enum event event_enum)
+{
+ static const enum event email_events[] = {
+ EVENT_FAIL,
+ EVENT_FAIL_SPARE,
+ EVENT_DEGRADED_ARRAY,
+ EVENT_SPARES_MISSING,
+ EVENT_TEST_MESSAGE
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(email_events); ++i) {
+ if (event_enum == email_events[i])
+ return true;
+ }
+ return false;
+}
+
+/*
+ * execute_alert_cmd() - Forks and executes command provided as alert_cmd.
+ * @data: event data
+ */
+static void execute_alert_cmd(const struct event_data *data)
{
int pid = fork();
@@ -462,12 +550,16 @@ static void execute_alert_cmd(const char *event_name, const char *dev, const cha
pr_err("Cannot fork to execute alert command");
break;
case 0:
- execl(info.alert_cmd, info.alert_cmd, event_name, dev, disc, NULL);
+ execl(info.alert_cmd, info.alert_cmd, data->event_name, data->dev, data->disc, NULL);
exit(2);
}
}
-static void send_event_email(const char *event_name, const char *dev, const char *disc)
+/*
+ * send_event_email() - Sends an email about event detected by monitor.
+ * @data: event data
+ */
+static void send_event_email(const struct event_data *data)
{
FILE *mp, *mdstat;
char buf[BUFSIZ];
@@ -485,15 +577,9 @@ static void send_event_email(const char *event_name, const char *dev, const char
else
fprintf(mp, "From: %s monitoring <root>\n", Name);
fprintf(mp, "To: %s\n", info.mailaddr);
- fprintf(mp, "Subject: %s event on %s:%s\n\n", event_name, dev, info.hostname);
- fprintf(mp, "This is an automatically generated mail message. \n");
- fprintf(mp, "A %s event had been detected on md device %s.\n\n", event_name, dev);
-
- if (disc && disc[0] != ' ')
- fprintf(mp,
- "It could be related to component device %s.\n\n", disc);
- if (disc && disc[0] == ' ')
- fprintf(mp, "Extra information:%s.\n\n", disc);
+ fprintf(mp, "Subject: %s event on %s:%s\n\n", data->event_name, data->dev, info.hostname);
+ fprintf(mp, "This is an automatically generated mail message.\n");
+ fprintf(mp, "%s\n", data->message);
mdstat = fopen("/proc/mdstat", "r");
if (!mdstat) {
@@ -509,58 +595,60 @@ static void send_event_email(const char *event_name, const char *dev, const char
pclose(mp);
}
-static void log_event_to_syslog(const enum event event_enum, const char *event_name, const char *dev, const char *disc)
+/*
+ * log_event_to_syslog() - Logs an event into syslog.
+ * @data: event data
+ */
+static void log_event_to_syslog(const struct event_data *data)
{
int priority;
- /* Log at a different severity depending on the event.
- *
- * These are the critical events: */
- if (event_enum == EVENT_FAIL ||
- event_enum == EVENT_DEGRADED_ARRAY ||
- event_enum == EVENT_DEVICE_DISAPPEARED)
- priority = LOG_CRIT;
- /* Good to know about, but are not failures: */
- else if (event_enum == EVENT_REBUILD ||
- event_enum == EVENT_MOVE_SPARE ||
- event_enum == EVENT_SPARES_MISSING)
- priority = LOG_WARNING;
- /* Everything else: */
- else
- priority = LOG_INFO;
-
- if (disc && disc[0] != ' ')
- syslog(priority,
- "%s event detected on md device %s, component device %s",
- event_name, dev, disc);
- else if (disc)
- syslog(priority, "%s event detected on md device %s: %s", event_name, dev, disc);
- else
- syslog(priority, "%s event detected on md device %s", event_name, dev);
+
+ priority = get_syslog_event_priority(data->event_enum);
+
+ syslog(priority, "%s\n", data->message);
}
-static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc)
+/*
+ * alert() - Alerts about the monitor event.
+ * @event_enum: event to be sent
+ * @description: event description
+ * @progress: rebuild progress
+ * @dev: md device name
+ * @disc: component device
+ *
+ * If needed function executes alert command, sends an email or logs event to syslog.
+ */
+static void alert(const enum event event_enum, const char *description, const uint8_t progress,
+ const char *dev, const char *disc)
{
- char event_name[EVENT_NAME_MAX];
+ struct event_data data = {.dev = dev, .disc = disc, .description = description};
+
+ if (!dev)
+ return;
if (event_enum == EVENT_REBUILD) {
- snprintf(event_name, sizeof(event_name), "%s%02d",
+ snprintf(data.event_name, sizeof(data.event_name), "%s%02d",
map_num_s(events_map, EVENT_REBUILD), progress);
} else {
- snprintf(event_name, sizeof(event_name), "%s", map_num_s(events_map, event_enum));
+ snprintf(data.event_name, sizeof(data.event_name), "%s", map_num_s(events_map, event_enum));
}
- if (info.alert_cmd)
- execute_alert_cmd(event_name, dev, disc);
+ data.event_enum = event_enum;
- if (info.mailaddr && (event_enum == EVENT_FAIL ||
- event_enum == EVENT_TEST_MESSAGE ||
- event_enum == EVENT_SPARES_MISSING ||
- event_enum == EVENT_DEGRADED_ARRAY)) {
- send_event_email(event_name, dev, disc);
+ if (sprint_event_message(data.message, &data) != 0) {
+ pr_err("Cannot create event message.\n");
+ return;
}
+ pr_err("%s\n", data.message);
+
+ if (info.alert_cmd)
+ execute_alert_cmd(&data);
+
+ if (info.mailaddr && is_email_event(event_enum))
+ send_event_email(&data);
if (info.dosyslog)
- log_event_to_syslog(event_enum, event_name, dev, disc);
+ log_event_to_syslog(&data);
}
static int check_array(struct state *st, struct mdstat_ent *mdstat,
@@ -585,7 +673,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
unsigned long redundancy_only_flags = 0;
if (info.test)
- alert(EVENT_TEST_MESSAGE, 0, dev, NULL);
+ alert(EVENT_TEST_MESSAGE, NULL, 0, dev, NULL);
retval = 0;
@@ -634,7 +722,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
*/
if (sra->array.level == 0 || sra->array.level == -1) {
if (!st->err && !st->from_config)
- alert(EVENT_DEVICE_DISAPPEARED, 0, dev, " Wrong-Level");
+ alert(EVENT_DEVICE_DISAPPEARED, "Wrong-Level", 0, dev, NULL);
st->err++;
goto out;
}
@@ -651,7 +739,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
st->percent = RESYNC_NONE;
new_array = 1;
if (!is_container)
- alert(EVENT_NEW_ARRAY, 0, st->devname, NULL);
+ alert(EVENT_NEW_ARRAY, NULL, 0, st->devname, NULL);
}
if (st->utime == array.utime && st->failed == sra->array.failed_disks &&
@@ -664,20 +752,20 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
}
if (st->utime == 0 && /* new array */
mse->pattern && strchr(mse->pattern, '_') /* degraded */)
- alert(EVENT_DEGRADED_ARRAY, 0, dev, NULL);
+ alert(EVENT_DEGRADED_ARRAY, NULL, 0, dev, NULL);
if (st->utime == 0 && /* new array */ st->expected_spares > 0 &&
sra->array.spare_disks < st->expected_spares)
- alert(EVENT_SPARES_MISSING, 0, dev, NULL);
+ alert(EVENT_SPARES_MISSING, NULL, 0, dev, NULL);
if (st->percent < 0 && st->percent != RESYNC_UNKNOWN &&
mse->percent >= 0)
- alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
+ alert(EVENT_REBUILD_STARTED, NULL, 0, dev, NULL);
if (st->percent >= 0 && mse->percent >= 0 &&
(mse->percent / increments) > (st->percent / increments)) {
if((mse->percent / increments) == 0)
- alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
+ alert(EVENT_REBUILD_STARTED, NULL, 0, dev, NULL);
else
- alert(EVENT_REBUILD, mse->percent, dev, NULL);
+ alert(EVENT_REBUILD, NULL, mse->percent, dev, NULL);
}
if (mse->percent == RESYNC_NONE && st->percent >= 0) {
@@ -690,9 +778,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
snprintf(cnt, sizeof(cnt),
" mismatches found: %d (on raid level %d)",
sra->mismatch_cnt, sra->array.level);
- alert(EVENT_REBUILD_FINISHED, 0, dev, cnt);
+ alert(EVENT_REBUILD_FINISHED, NULL, 0, dev, cnt);
} else
- alert(EVENT_REBUILD_FINISHED, 0, dev, NULL);
+ alert(EVENT_REBUILD_FINISHED, NULL, 0, dev, NULL);
}
st->percent = mse->percent;
@@ -746,14 +834,14 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
change = newstate ^ st->devstate[i];
if (st->utime && change && !st->err && !new_array) {
if ((st->devstate[i]&change) & (1 << MD_DISK_SYNC))
- alert(EVENT_FAIL, 0, dev, dv);
+ alert(EVENT_FAIL, NULL, 0, dev, dv);
else if ((newstate & (1 << MD_DISK_FAULTY)) &&
(disc.major || disc.minor) &&
st->devid[i] == makedev(disc.major,
disc.minor))
- alert(EVENT_FAIL_SPARE, 0, dev, dv);
+ alert(EVENT_FAIL_SPARE, NULL, 0, dev, dv);
else if ((newstate&change) & (1 << MD_DISK_SYNC))
- alert(EVENT_SPARE_ACTIVE, 0, dev, dv);
+ alert(EVENT_SPARE_ACTIVE, NULL, 0, dev, dv);
}
st->devstate[i] = newstate;
st->devid[i] = makedev(disc.major, disc.minor);
@@ -777,7 +865,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
disappeared:
if (!st->err && !is_container)
- alert(EVENT_DEVICE_DISAPPEARED, 0, dev, NULL);
+ alert(EVENT_DEVICE_DISAPPEARED, NULL, 0, dev, NULL);
st->err++;
goto out;
}
@@ -836,7 +924,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
st->parent_devnm[0] = 0;
*statelist = st;
if (info.test)
- alert(EVENT_TEST_MESSAGE, 0, st->devname, NULL);
+ alert(EVENT_TEST_MESSAGE, NULL, 0, st->devname, NULL);
new_found = 1;
}
return new_found;
@@ -1059,7 +1147,7 @@ static void try_spare_migration(struct state *statelist)
if (devid > 0 &&
move_spare(from->devname, to->devname,
devid)) {
- alert(EVENT_MOVE_SPARE, 0, to->devname, from->devname);
+ alert(EVENT_MOVE_SPARE, NULL, 0, to->devname, from->devname);
break;
}
}
--
2.38.1