2 * This file is part of the ZFS Event Daemon (ZED)
3 * for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
4 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
5 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
6 * Refer to the ZoL git commit log for authoritative copyright attribution.
8 * The contents of this file are subject to the terms of the
9 * Common Development and Distribution License Version 1.0 (CDDL-1.0).
10 * You can obtain a copy of the license from the top-level file
11 * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
12 * You may not use this file except in compliance with the license.
18 #include <libzfs.h> /* FIXME: Replace with libzfs_core. */
24 #include <sys/zfs_ioctl.h>
27 #include <sys/fm/fs/zfs.h>
30 #include "zed_disk_event.h"
34 #include "zed_strings.h"
36 #include "agents/zfs_agents.h"
41 * Open the libzfs interface.
44 zed_event_init(struct zed_conf *zcp)
47 zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
49 zcp->zfs_hdl = libzfs_init();
51 zed_log_die("Failed to initialize libzfs");
53 zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
54 if (zcp->zevent_fd < 0)
55 zed_log_die("Failed to open \"%s\": %s",
56 ZFS_DEV, strerror(errno));
58 zfs_agent_init(zcp->zfs_hdl);
60 if (zed_disk_event_init() != 0)
61 zed_log_die("Failed to initialize disk events");
65 * Close the libzfs interface.
68 zed_event_fini(struct zed_conf *zcp)
71 zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL));
73 zed_disk_event_fini();
76 if (zcp->zevent_fd >= 0) {
77 if (close(zcp->zevent_fd) < 0)
78 zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s",
79 ZFS_DEV, strerror(errno));
84 libzfs_fini(zcp->zfs_hdl);
90 * Seek to the event specified by [saved_eid] and [saved_etime].
91 * This protects against processing a given event more than once.
92 * Return 0 upon a successful seek to the specified event, or -1 otherwise.
94 * A zevent is considered to be uniquely specified by its (eid,time) tuple.
95 * The unsigned 64b eid is set to 1 when the kernel module is loaded, and
96 * incremented by 1 for each new event. Since the state file can persist
97 * across a kernel module reload, the time must be checked to ensure a match.
100 zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[])
112 zed_log_msg(LOG_ERR, "Failed to seek zevent: %s",
118 while ((eid < saved_eid) && !found) {
119 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped,
120 ZEVENT_NONBLOCK, zcp->zevent_fd);
122 if ((rv != 0) || !nvl)
126 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
128 * FIXME: Increase max size of event nvlist in
129 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
132 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
133 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
134 } else if (nvlist_lookup_int64_array(nvl, "time",
135 &etime, &nelem) != 0) {
136 zed_log_msg(LOG_WARNING,
137 "Failed to lookup zevent time (eid=%llu)", eid);
138 } else if (nelem != 2) {
139 zed_log_msg(LOG_WARNING,
140 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
142 } else if ((eid != saved_eid) ||
143 (etime[0] != saved_etime[0]) ||
144 (etime[1] != saved_etime[1])) {
151 if (!found && (saved_eid > 0)) {
152 if (zpool_events_seek(zcp->zfs_hdl, ZEVENT_SEEK_START,
154 zed_log_msg(LOG_WARNING, "Failed to seek to eid=0");
158 zed_log_msg(LOG_NOTICE, "Processing events since eid=%llu", eid);
159 return (found ? 0 : -1);
163 * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0.
166 _zed_event_value_is_hex(const char *name)
168 const char *hex_suffix[] = {
179 for (pp = hex_suffix; *pp; pp++) {
180 p = strstr(name, *pp);
181 if (p && strlen(p) == strlen(*pp))
188 * Add an environment variable for [eid] to the container [zsp].
190 * The variable name is the concatenation of [prefix] and [name] converted to
191 * uppercase with non-alphanumeric characters converted to underscores;
192 * [prefix] is optional, and [name] must begin with an alphabetic character.
193 * If the converted variable name already exists within the container [zsp],
194 * its existing value will be replaced with the new value.
196 * The variable value is specified by the format string [fmt].
198 * Returns 0 on success, and -1 on error (with errno set).
200 * All environment variables in [zsp] should be added through this function.
203 _zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
204 const char *prefix, const char *name, const char *fmt, ...)
220 zed_log_msg(LOG_WARNING,
221 "Failed to add variable for eid=%llu: Name is empty", eid);
223 } else if (!isalpha(name[0])) {
225 zed_log_msg(LOG_WARNING,
226 "Failed to add variable for eid=%llu: "
227 "Name \"%s\" is invalid", eid, name);
231 * Construct the string key by converting PREFIX (if present) and NAME.
234 lastp = keybuf + sizeof (keybuf);
236 for (srcp = prefix; *srcp && (dstp < lastp); srcp++)
237 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
239 for (srcp = name; *srcp && (dstp < lastp); srcp++)
240 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
243 errno = ENAMETOOLONG;
244 zed_log_msg(LOG_WARNING,
245 "Failed to add variable for eid=%llu: Name too long", eid);
250 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
253 buflen = sizeof (valbuf);
254 n = strlcpy(dstp, keybuf, buflen);
255 if (n >= sizeof (valbuf)) {
257 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
258 keybuf, eid, "Exceeded buffer size");
269 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
270 keybuf, eid, "Exceeded buffer size");
274 va_start(vargs, fmt);
275 n = vsnprintf(dstp, buflen, fmt, vargs);
278 if ((n < 0) || (n >= buflen)) {
280 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
281 keybuf, eid, "Exceeded buffer size");
283 } else if (zed_strings_add(zsp, keybuf, valbuf) < 0) {
284 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
285 keybuf, eid, strerror(errno));
292 _zed_event_add_array_err(uint64_t eid, const char *name)
295 zed_log_msg(LOG_WARNING,
296 "Failed to convert nvpair \"%s\" for eid=%llu: "
297 "Exceeded buffer size", name, eid);
302 _zed_event_add_int8_array(uint64_t eid, zed_strings_t *zsp,
303 const char *prefix, nvpair_t *nvp)
306 int buflen = sizeof (buf);
314 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT8_ARRAY));
316 name = nvpair_name(nvp);
317 (void) nvpair_value_int8_array(nvp, &i8p, &nelem);
318 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
319 n = snprintf(p, buflen, "%d ", i8p[i]);
320 if ((n < 0) || (n >= buflen))
321 return (_zed_event_add_array_err(eid, name));
328 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
332 _zed_event_add_uint8_array(uint64_t eid, zed_strings_t *zsp,
333 const char *prefix, nvpair_t *nvp)
336 int buflen = sizeof (buf);
344 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT8_ARRAY));
346 name = nvpair_name(nvp);
347 (void) nvpair_value_uint8_array(nvp, &u8p, &nelem);
348 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
349 n = snprintf(p, buflen, "%u ", u8p[i]);
350 if ((n < 0) || (n >= buflen))
351 return (_zed_event_add_array_err(eid, name));
358 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
362 _zed_event_add_int16_array(uint64_t eid, zed_strings_t *zsp,
363 const char *prefix, nvpair_t *nvp)
366 int buflen = sizeof (buf);
374 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT16_ARRAY));
376 name = nvpair_name(nvp);
377 (void) nvpair_value_int16_array(nvp, &i16p, &nelem);
378 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
379 n = snprintf(p, buflen, "%d ", i16p[i]);
380 if ((n < 0) || (n >= buflen))
381 return (_zed_event_add_array_err(eid, name));
388 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
392 _zed_event_add_uint16_array(uint64_t eid, zed_strings_t *zsp,
393 const char *prefix, nvpair_t *nvp)
396 int buflen = sizeof (buf);
404 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY));
406 name = nvpair_name(nvp);
407 (void) nvpair_value_uint16_array(nvp, &u16p, &nelem);
408 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
409 n = snprintf(p, buflen, "%u ", u16p[i]);
410 if ((n < 0) || (n >= buflen))
411 return (_zed_event_add_array_err(eid, name));
418 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
422 _zed_event_add_int32_array(uint64_t eid, zed_strings_t *zsp,
423 const char *prefix, nvpair_t *nvp)
426 int buflen = sizeof (buf);
434 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT32_ARRAY));
436 name = nvpair_name(nvp);
437 (void) nvpair_value_int32_array(nvp, &i32p, &nelem);
438 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
439 n = snprintf(p, buflen, "%d ", i32p[i]);
440 if ((n < 0) || (n >= buflen))
441 return (_zed_event_add_array_err(eid, name));
448 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
452 _zed_event_add_uint32_array(uint64_t eid, zed_strings_t *zsp,
453 const char *prefix, nvpair_t *nvp)
456 int buflen = sizeof (buf);
464 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT32_ARRAY));
466 name = nvpair_name(nvp);
467 (void) nvpair_value_uint32_array(nvp, &u32p, &nelem);
468 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
469 n = snprintf(p, buflen, "%u ", u32p[i]);
470 if ((n < 0) || (n >= buflen))
471 return (_zed_event_add_array_err(eid, name));
478 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
482 _zed_event_add_int64_array(uint64_t eid, zed_strings_t *zsp,
483 const char *prefix, nvpair_t *nvp)
486 int buflen = sizeof (buf);
494 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT64_ARRAY));
496 name = nvpair_name(nvp);
497 (void) nvpair_value_int64_array(nvp, &i64p, &nelem);
498 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
499 n = snprintf(p, buflen, "%lld ", (u_longlong_t)i64p[i]);
500 if ((n < 0) || (n >= buflen))
501 return (_zed_event_add_array_err(eid, name));
508 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
512 _zed_event_add_uint64_array(uint64_t eid, zed_strings_t *zsp,
513 const char *prefix, nvpair_t *nvp)
516 int buflen = sizeof (buf);
525 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY));
527 name = nvpair_name(nvp);
528 fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu ";
529 (void) nvpair_value_uint64_array(nvp, &u64p, &nelem);
530 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
531 n = snprintf(p, buflen, fmt, (u_longlong_t)u64p[i]);
532 if ((n < 0) || (n >= buflen))
533 return (_zed_event_add_array_err(eid, name));
540 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
544 _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
545 const char *prefix, nvpair_t *nvp)
548 int buflen = sizeof (buf);
556 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY));
558 name = nvpair_name(nvp);
559 (void) nvpair_value_string_array(nvp, &strp, &nelem);
560 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
561 n = snprintf(p, buflen, "%s ", strp[i] ? strp[i] : "<NULL>");
562 if ((n < 0) || (n >= buflen))
563 return (_zed_event_add_array_err(eid, name));
570 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
574 * Convert the nvpair [nvp] to a string which is added to the environment
575 * of the child process.
576 * Return 0 on success, -1 on error.
578 * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()?
581 _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
585 const char *prefix = ZEVENT_VAR_PREFIX;
597 name = nvpair_name(nvp);
598 type = nvpair_type(nvp);
601 case DATA_TYPE_BOOLEAN:
602 _zed_event_add_var(eid, zsp, prefix, name, "%s", "1");
604 case DATA_TYPE_BOOLEAN_VALUE:
605 (void) nvpair_value_boolean_value(nvp, &b);
606 _zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0");
609 (void) nvpair_value_byte(nvp, &i8);
610 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
613 (void) nvpair_value_int8(nvp, (int8_t *)&i8);
614 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
616 case DATA_TYPE_UINT8:
617 (void) nvpair_value_uint8(nvp, &i8);
618 _zed_event_add_var(eid, zsp, prefix, name, "%u", i8);
620 case DATA_TYPE_INT16:
621 (void) nvpair_value_int16(nvp, (int16_t *)&i16);
622 _zed_event_add_var(eid, zsp, prefix, name, "%d", i16);
624 case DATA_TYPE_UINT16:
625 (void) nvpair_value_uint16(nvp, &i16);
626 _zed_event_add_var(eid, zsp, prefix, name, "%u", i16);
628 case DATA_TYPE_INT32:
629 (void) nvpair_value_int32(nvp, (int32_t *)&i32);
630 _zed_event_add_var(eid, zsp, prefix, name, "%d", i32);
632 case DATA_TYPE_UINT32:
633 (void) nvpair_value_uint32(nvp, &i32);
634 _zed_event_add_var(eid, zsp, prefix, name, "%u", i32);
636 case DATA_TYPE_INT64:
637 (void) nvpair_value_int64(nvp, (int64_t *)&i64);
638 _zed_event_add_var(eid, zsp, prefix, name,
639 "%lld", (longlong_t)i64);
641 case DATA_TYPE_UINT64:
642 (void) nvpair_value_uint64(nvp, &i64);
643 _zed_event_add_var(eid, zsp, prefix, name,
644 (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"),
647 * shadow readable strings for vdev state pairs
649 if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
650 strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
653 (void) snprintf(alt, sizeof (alt), "%s_str", name);
654 _zed_event_add_var(eid, zsp, prefix, alt, "%s",
655 zpool_state_to_name(i64, VDEV_AUX_NONE));
658 case DATA_TYPE_DOUBLE:
659 (void) nvpair_value_double(nvp, &d);
660 _zed_event_add_var(eid, zsp, prefix, name, "%g", d);
662 case DATA_TYPE_HRTIME:
663 (void) nvpair_value_hrtime(nvp, (hrtime_t *)&i64);
664 _zed_event_add_var(eid, zsp, prefix, name,
665 "%llu", (u_longlong_t)i64);
667 case DATA_TYPE_NVLIST:
668 _zed_event_add_var(eid, zsp, prefix, name,
669 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
671 case DATA_TYPE_STRING:
672 (void) nvpair_value_string(nvp, &str);
673 _zed_event_add_var(eid, zsp, prefix, name,
674 "%s", (str ? str : "<NULL>"));
676 case DATA_TYPE_BOOLEAN_ARRAY:
677 _zed_event_add_var(eid, zsp, prefix, name,
678 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
680 case DATA_TYPE_BYTE_ARRAY:
681 _zed_event_add_var(eid, zsp, prefix, name,
682 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
684 case DATA_TYPE_INT8_ARRAY:
685 _zed_event_add_int8_array(eid, zsp, prefix, nvp);
687 case DATA_TYPE_UINT8_ARRAY:
688 _zed_event_add_uint8_array(eid, zsp, prefix, nvp);
690 case DATA_TYPE_INT16_ARRAY:
691 _zed_event_add_int16_array(eid, zsp, prefix, nvp);
693 case DATA_TYPE_UINT16_ARRAY:
694 _zed_event_add_uint16_array(eid, zsp, prefix, nvp);
696 case DATA_TYPE_INT32_ARRAY:
697 _zed_event_add_int32_array(eid, zsp, prefix, nvp);
699 case DATA_TYPE_UINT32_ARRAY:
700 _zed_event_add_uint32_array(eid, zsp, prefix, nvp);
702 case DATA_TYPE_INT64_ARRAY:
703 _zed_event_add_int64_array(eid, zsp, prefix, nvp);
705 case DATA_TYPE_UINT64_ARRAY:
706 _zed_event_add_uint64_array(eid, zsp, prefix, nvp);
708 case DATA_TYPE_STRING_ARRAY:
709 _zed_event_add_string_array(eid, zsp, prefix, nvp);
711 case DATA_TYPE_NVLIST_ARRAY:
712 _zed_event_add_var(eid, zsp, prefix, name,
713 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
717 zed_log_msg(LOG_WARNING,
718 "Failed to convert nvpair \"%s\" for eid=%llu: "
719 "Unrecognized type=%u", name, eid, (unsigned int) type);
725 * Restrict various environment variables to safe and sane values
726 * when constructing the environment for the child process.
728 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
731 _zed_event_add_env_restrict(uint64_t eid, zed_strings_t *zsp)
733 const char *env_restrict[][2] = {
735 { "PATH", _PATH_STDPATH },
736 { "ZDB", SBINDIR "/zdb" },
737 { "ZED", SBINDIR "/zed" },
738 { "ZFS", SBINDIR "/zfs" },
739 { "ZINJECT", SBINDIR "/zinject" },
740 { "ZPOOL", SBINDIR "/zpool" },
741 { "ZFS_ALIAS", ZFS_META_ALIAS },
742 { "ZFS_VERSION", ZFS_META_VERSION },
743 { "ZFS_RELEASE", ZFS_META_RELEASE },
746 const char *(*pa)[2];
750 for (pa = env_restrict; *(*pa); pa++) {
751 _zed_event_add_var(eid, zsp, NULL, (*pa)[0], "%s", (*pa)[1]);
756 * Preserve specified variables from the parent environment
757 * when constructing the environment for the child process.
759 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
762 _zed_event_add_env_preserve(uint64_t eid, zed_strings_t *zsp)
764 const char *env_preserve[] = {
773 for (keyp = env_preserve; *keyp; keyp++) {
774 if ((val = getenv(*keyp)))
775 _zed_event_add_var(eid, zsp, NULL, *keyp, "%s", val);
780 * Compute the "subclass" by removing the first 3 components of [class]
781 * (which will always be of the form "*.fs.zfs"). Return a pointer inside
782 * the string [class], or NULL if insufficient components exist.
785 _zed_event_get_subclass(const char *class)
794 for (i = 0; i < 3; i++) {
804 * Convert the zevent time from a 2-element array of 64b integers
805 * into a more convenient form:
806 * - TIME_SECS is the second component of the time.
807 * - TIME_NSECS is the nanosecond component of the time.
808 * - TIME_STRING is an almost-RFC3339-compliant string representation.
811 _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
817 assert(etime != NULL);
819 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
820 "%lld", (long long int) etime[0]);
821 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
822 "%lld", (long long int) etime[1]);
824 if (!(stp = localtime((const time_t *) &etime[0]))) {
825 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
826 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
827 } else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", stp)) {
828 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
829 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
831 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_STRING",
837 * Service the next zevent, blocking until one is available.
840 zed_event_service(struct zed_conf *zcp)
850 const char *subclass;
855 zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
859 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
862 if ((rv != 0) || !nvl)
866 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
868 * FIXME: Increase max size of event nvlist in
869 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
872 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
873 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
874 } else if (nvlist_lookup_int64_array(
875 nvl, "time", &etime, &nelem) != 0) {
876 zed_log_msg(LOG_WARNING,
877 "Failed to lookup zevent time (eid=%llu)", eid);
878 } else if (nelem != 2) {
879 zed_log_msg(LOG_WARNING,
880 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
882 } else if (nvlist_lookup_string(nvl, "class", &class) != 0) {
883 zed_log_msg(LOG_WARNING,
884 "Failed to lookup zevent class (eid=%llu)", eid);
886 /* let internal modules see this event first */
887 zfs_agent_post_event(class, NULL, nvl);
889 zsp = zed_strings_create();
892 while ((nvp = nvlist_next_nvpair(nvl, nvp)))
893 _zed_event_add_nvpair(eid, zsp, nvp);
895 _zed_event_add_env_restrict(eid, zsp);
896 _zed_event_add_env_preserve(eid, zsp);
898 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "PID",
899 "%d", (int)getpid());
900 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "ZEDLET_DIR",
901 "%s", zcp->zedlet_dir);
902 subclass = _zed_event_get_subclass(class);
903 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "SUBCLASS",
904 "%s", (subclass ? subclass : class));
906 _zed_event_add_time_strings(eid, zsp, etime);
908 zed_exec_process(eid, class, subclass,
909 zcp->zedlet_dir, zcp->zedlets, zsp, zcp->zevent_fd);
911 zed_conf_write_state(zcp, eid, etime);
913 zed_strings_destroy(zsp);