aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/cmd/zed
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/cmd/zed')
-rw-r--r--sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c67
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am24
-rwxr-xr-xsys/contrib/openzfs/cmd/zed/zed.d/deadman-sync-slot_off.sh (renamed from sys/contrib/openzfs/cmd/zed/zed.d/deadman-slot_off.sh)0
l---------sys/contrib/openzfs/cmd/zed/zed.d/pool_import-led.sh1
l---------sys/contrib/openzfs/cmd/zed/zed.d/pool_import-sync-led.sh1
-rwxr-xr-xsys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-led.sh (renamed from sys/contrib/openzfs/cmd/zed/zed.d/statechange-led.sh)0
-rwxr-xr-xsys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-slot_off.sh (renamed from sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh)0
l---------sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-led.sh1
l---------sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-sync-led.sh1
l---------sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-led.sh1
l---------sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-sync-led.sh1
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh3
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed_event.c2
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed_exec.c111
14 files changed, 144 insertions, 69 deletions
diff --git a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
index 8718dbde03b6..c0590edc7516 100644
--- a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
+++ b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
@@ -134,11 +134,13 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
* of blkid cache and L2ARC VDEV does not contain pool guid in its
* blkid, so this is a special case for L2ARC VDEV.
*/
- else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
+ else if (gsp->gs_vdev_guid != 0 &&
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
gsp->gs_vdev_guid == vdev_guid) {
- (void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
- &gsp->gs_devid);
+ if (gsp->gs_devid == NULL) {
+ (void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
+ &gsp->gs_devid);
+ }
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
&gsp->gs_vdev_expandtime);
return (B_TRUE);
@@ -156,22 +158,28 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
/*
* For each vdev in this pool, look for a match by devid
*/
- if ((config = zpool_get_config(zhp, NULL)) != NULL) {
- if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
- &nvl) == 0) {
- (void) zfs_agent_iter_vdev(zhp, nvl, gsp);
- }
- }
- /*
- * if a match was found then grab the pool guid
- */
- if (gsp->gs_vdev_guid && gsp->gs_devid) {
- (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
- &gsp->gs_pool_guid);
- }
+ boolean_t found = B_FALSE;
+ uint64_t pool_guid;
+ /* Get pool configuration and extract pool GUID */
+ if ((config = zpool_get_config(zhp, NULL)) == NULL ||
+ nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
+ &pool_guid) != 0)
+ goto out;
+
+ /* Skip this pool if we're looking for a specific pool */
+ if (gsp->gs_pool_guid != 0 && pool_guid != gsp->gs_pool_guid)
+ goto out;
+
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvl) == 0)
+ found = zfs_agent_iter_vdev(zhp, nvl, gsp);
+
+ if (found && gsp->gs_pool_guid == 0)
+ gsp->gs_pool_guid = pool_guid;
+
+out:
zpool_close(zhp);
- return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
+ return (found);
}
void
@@ -233,20 +241,17 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
* ZFS_EV_POOL_GUID may be missing so find them.
*/
- if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
- if (devid == NULL)
- search.gs_vdev_guid = vdev_guid;
- else
- search.gs_devid = devid;
- zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
- if (devid == NULL)
- devid = search.gs_devid;
- if (pool_guid == 0)
- pool_guid = search.gs_pool_guid;
- if (vdev_guid == 0)
- vdev_guid = search.gs_vdev_guid;
- devtype = search.gs_vdev_type;
- }
+ search.gs_devid = devid;
+ search.gs_vdev_guid = vdev_guid;
+ search.gs_pool_guid = pool_guid;
+ zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
+ if (devid == NULL)
+ devid = search.gs_devid;
+ if (pool_guid == 0)
+ pool_guid = search.gs_pool_guid;
+ if (vdev_guid == 0)
+ vdev_guid = search.gs_vdev_guid;
+ devtype = search.gs_vdev_type;
/*
* We want to avoid reporting "remove" events coming from
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am b/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
index 093a04c4636a..c0b161ecf248 100644
--- a/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
@@ -9,18 +9,18 @@ dist_zedexec_SCRIPTS = \
%D%/all-debug.sh \
%D%/all-syslog.sh \
%D%/data-notify.sh \
- %D%/deadman-slot_off.sh \
+ %D%/deadman-sync-slot_off.sh \
%D%/generic-notify.sh \
- %D%/pool_import-led.sh \
+ %D%/pool_import-sync-led.sh \
%D%/resilver_finish-notify.sh \
%D%/resilver_finish-start-scrub.sh \
%D%/scrub_finish-notify.sh \
- %D%/statechange-led.sh \
+ %D%/statechange-sync-led.sh \
%D%/statechange-notify.sh \
- %D%/statechange-slot_off.sh \
+ %D%/statechange-sync-slot_off.sh \
%D%/trim_finish-notify.sh \
- %D%/vdev_attach-led.sh \
- %D%/vdev_clear-led.sh
+ %D%/vdev_attach-sync-led.sh \
+ %D%/vdev_clear-sync-led.sh
nodist_zedexec_SCRIPTS = \
%D%/history_event-zfs-list-cacher.sh
@@ -30,17 +30,17 @@ SUBSTFILES += $(nodist_zedexec_SCRIPTS)
zedconfdefaults = \
all-syslog.sh \
data-notify.sh \
- deadman-slot_off.sh \
+ deadman-sync-slot_off.sh \
history_event-zfs-list-cacher.sh \
- pool_import-led.sh \
+ pool_import-sync-led.sh \
resilver_finish-notify.sh \
resilver_finish-start-scrub.sh \
scrub_finish-notify.sh \
- statechange-led.sh \
+ statechange-sync-led.sh \
statechange-notify.sh \
- statechange-slot_off.sh \
- vdev_attach-led.sh \
- vdev_clear-led.sh
+ statechange-sync-slot_off.sh \
+ vdev_attach-sync-led.sh \
+ vdev_clear-sync-led.sh
dist_noinst_DATA += %D%/README
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/deadman-slot_off.sh b/sys/contrib/openzfs/cmd/zed/zed.d/deadman-sync-slot_off.sh
index 7b339b3add01..7b339b3add01 100755
--- a/sys/contrib/openzfs/cmd/zed/zed.d/deadman-slot_off.sh
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/deadman-sync-slot_off.sh
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-led.sh
deleted file mode 120000
index 7d7404398a4a..000000000000
--- a/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-led.sh
+++ /dev/null
@@ -1 +0,0 @@
-statechange-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-sync-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-sync-led.sh
new file mode 120000
index 000000000000..8b9c10c11ebb
--- /dev/null
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/pool_import-sync-led.sh
@@ -0,0 +1 @@
+statechange-sync-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-led.sh
index 40cb61f17307..40cb61f17307 100755
--- a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-led.sh
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-led.sh
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-slot_off.sh
index 06acce93b8aa..06acce93b8aa 100755
--- a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-sync-slot_off.sh
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-led.sh
deleted file mode 120000
index 7d7404398a4a..000000000000
--- a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-led.sh
+++ /dev/null
@@ -1 +0,0 @@
-statechange-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-sync-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-sync-led.sh
new file mode 120000
index 000000000000..8b9c10c11ebb
--- /dev/null
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_attach-sync-led.sh
@@ -0,0 +1 @@
+statechange-sync-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-led.sh
deleted file mode 120000
index 7d7404398a4a..000000000000
--- a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-led.sh
+++ /dev/null
@@ -1 +0,0 @@
-statechange-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-sync-led.sh b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-sync-led.sh
new file mode 120000
index 000000000000..8b9c10c11ebb
--- /dev/null
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/vdev_clear-sync-led.sh
@@ -0,0 +1 @@
+statechange-sync-led.sh \ No newline at end of file
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh b/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh
index 6e00f153be1c..78d8f658ddd8 100644
--- a/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh
@@ -441,8 +441,9 @@ zed_notify_slack_webhook()
"${pathname}")"
# Construct the JSON message for posting.
+ # shellcheck disable=SC2016
#
- msg_json="$(printf '{"text": "*%s*\\n%s"}' "${subject}" "${msg_body}" )"
+ msg_json="$(printf '{"text": "*%s*\\n```%s```"}' "${subject}" "${msg_body}" )"
# Send the POST request and check for errors.
#
diff --git a/sys/contrib/openzfs/cmd/zed/zed_event.c b/sys/contrib/openzfs/cmd/zed/zed_event.c
index 296c222ca382..ba7cba304b1d 100644
--- a/sys/contrib/openzfs/cmd/zed/zed_event.c
+++ b/sys/contrib/openzfs/cmd/zed/zed_event.c
@@ -110,7 +110,7 @@ zed_event_fini(struct zed_conf *zcp)
static void
_bump_event_queue_length(void)
{
- int zzlm = -1, wr;
+ int zzlm, wr;
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
long int qlen, orig_qlen;
diff --git a/sys/contrib/openzfs/cmd/zed/zed_exec.c b/sys/contrib/openzfs/cmd/zed/zed_exec.c
index 036081decd64..a14af4f20a85 100644
--- a/sys/contrib/openzfs/cmd/zed/zed_exec.c
+++ b/sys/contrib/openzfs/cmd/zed/zed_exec.c
@@ -196,37 +196,29 @@ _nop(int sig)
(void) sig;
}
-static void *
-_reap_children(void *arg)
+static void
+wait_for_children(boolean_t do_pause, boolean_t wait)
{
- (void) arg;
- struct launched_process_node node, *pnode;
pid_t pid;
- int status;
struct rusage usage;
- struct sigaction sa = {};
-
- (void) sigfillset(&sa.sa_mask);
- (void) sigdelset(&sa.sa_mask, SIGCHLD);
- (void) pthread_sigmask(SIG_SETMASK, &sa.sa_mask, NULL);
-
- (void) sigemptyset(&sa.sa_mask);
- sa.sa_handler = _nop;
- sa.sa_flags = SA_NOCLDSTOP;
- (void) sigaction(SIGCHLD, &sa, NULL);
+ int status;
+ struct launched_process_node node, *pnode;
for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) {
(void) pthread_mutex_lock(&_launched_processes_lock);
- pid = wait4(0, &status, WNOHANG, &usage);
-
+ pid = wait4(0, &status, wait ? 0 : WNOHANG, &usage);
if (pid == 0 || pid == (pid_t)-1) {
(void) pthread_mutex_unlock(&_launched_processes_lock);
- if (pid == 0 || errno == ECHILD)
- pause();
- else if (errno != EINTR)
+ if ((pid == 0) || (errno == ECHILD)) {
+ if (do_pause)
+ pause();
+ } else if (errno != EINTR)
zed_log_msg(LOG_WARNING,
"Failed to wait for children: %s",
strerror(errno));
+ if (!do_pause)
+ return;
+
} else {
memset(&node, 0, sizeof (node));
node.pid = pid;
@@ -278,6 +270,25 @@ _reap_children(void *arg)
}
}
+}
+
+static void *
+_reap_children(void *arg)
+{
+ (void) arg;
+ struct sigaction sa = {};
+
+ (void) sigfillset(&sa.sa_mask);
+ (void) sigdelset(&sa.sa_mask, SIGCHLD);
+ (void) pthread_sigmask(SIG_SETMASK, &sa.sa_mask, NULL);
+
+ (void) sigemptyset(&sa.sa_mask);
+ sa.sa_handler = _nop;
+ sa.sa_flags = SA_NOCLDSTOP;
+ (void) sigaction(SIGCHLD, &sa, NULL);
+
+ wait_for_children(B_TRUE, B_FALSE);
+
return (NULL);
}
@@ -307,6 +318,45 @@ zed_exec_fini(void)
}
/*
+ * Check if the zedlet name indicates if it is a synchronous zedlet
+ *
+ * Synchronous zedlets have a "-sync-" immediately following the event name in
+ * their zedlet filename, like:
+ *
+ * EVENT_NAME-sync-ZEDLETNAME.sh
+ *
+ * For example, if you wanted a synchronous statechange script:
+ *
+ * statechange-sync-myzedlet.sh
+ *
+ * Synchronous zedlets are guaranteed to be the only zedlet running. No other
+ * zedlets may run in parallel with a synchronous zedlet. A synchronous
+ * zedlet will wait for all previously spawned zedlets to finish before running.
+ * Users should be careful to only use synchronous zedlets when needed, since
+ * they decrease parallelism.
+ */
+static boolean_t
+zedlet_is_sync(const char *zedlet, const char *event)
+{
+ const char *sync_str = "-sync-";
+ size_t sync_str_len;
+ size_t zedlet_len;
+ size_t event_len;
+
+ sync_str_len = strlen(sync_str);
+ zedlet_len = strlen(zedlet);
+ event_len = strlen(event);
+
+ if (event_len + sync_str_len >= zedlet_len)
+ return (B_FALSE);
+
+ if (strncmp(&zedlet[event_len], sync_str, sync_str_len) == 0)
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
+
+/*
* Process the event [eid] by synchronously invoking all zedlets with a
* matching class prefix.
*
@@ -368,9 +418,28 @@ zed_exec_process(uint64_t eid, const char *class, const char *subclass,
z = zed_strings_next(zcp->zedlets)) {
for (csp = class_strings; *csp; csp++) {
n = strlen(*csp);
- if ((strncmp(z, *csp, n) == 0) && !isalpha(z[n]))
+ if ((strncmp(z, *csp, n) == 0) && !isalpha(z[n])) {
+ boolean_t is_sync = zedlet_is_sync(z, *csp);
+
+ if (is_sync) {
+ /*
+ * Wait for previous zedlets to
+ * finish
+ */
+ wait_for_children(B_FALSE, B_TRUE);
+ }
+
_zed_exec_fork_child(eid, zcp->zedlet_dir,
z, e, zcp->zevent_fd, zcp->do_foreground);
+
+ if (is_sync) {
+ /*
+ * Wait for sync zedlet we just launched
+ * to finish.
+ */
+ wait_for_children(B_FALSE, B_TRUE);
+ }
+ }
}
}
free(e);