2 * This file is part of the ZFS Event Daemon (ZED).
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_core.h>
24 #include <sys/zfs_ioctl.h>
27 #include <sys/fm/fs/zfs.h>
30 #include "zed_disk_event.h"
31 #include "zed_event.h"
35 #include "zed_strings.h"
37 #include "agents/zfs_agents.h"
42 * Open the libzfs interface.
45 zed_event_init(struct zed_conf *zcp)
48 zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
50 zcp->zfs_hdl = libzfs_init();
54 zed_log_die("Failed to initialize libzfs");
57 zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
58 if (zcp->zevent_fd < 0) {
61 zed_log_die("Failed to open \"%s\": %s",
62 ZFS_DEV, strerror(errno));
65 zfs_agent_init(zcp->zfs_hdl);
67 if (zed_disk_event_init() != 0) {
70 zed_log_die("Failed to initialize disk events");
77 * Close the libzfs interface.
80 zed_event_fini(struct zed_conf *zcp)
83 zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL));
85 zed_disk_event_fini();
88 if (zcp->zevent_fd >= 0) {
89 if (close(zcp->zevent_fd) < 0)
90 zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s",
91 ZFS_DEV, strerror(errno));
96 libzfs_fini(zcp->zfs_hdl);
104 * Seek to the event specified by [saved_eid] and [saved_etime].
105 * This protects against processing a given event more than once.
106 * Return 0 upon a successful seek to the specified event, or -1 otherwise.
108 * A zevent is considered to be uniquely specified by its (eid,time) tuple.
109 * The unsigned 64b eid is set to 1 when the kernel module is loaded, and
110 * incremented by 1 for each new event. Since the state file can persist
111 * across a kernel module reload, the time must be checked to ensure a match.
114 zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[])
126 zed_log_msg(LOG_ERR, "Failed to seek zevent: %s",
132 while ((eid < saved_eid) && !found) {
133 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped,
134 ZEVENT_NONBLOCK, zcp->zevent_fd);
136 if ((rv != 0) || !nvl)
140 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
142 * FIXME: Increase max size of event nvlist in
143 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
146 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
147 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
148 } else if (nvlist_lookup_int64_array(nvl, "time",
149 &etime, &nelem) != 0) {
150 zed_log_msg(LOG_WARNING,
151 "Failed to lookup zevent time (eid=%llu)", eid);
152 } else if (nelem != 2) {
153 zed_log_msg(LOG_WARNING,
154 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
156 } else if ((eid != saved_eid) ||
157 (etime[0] != saved_etime[0]) ||
158 (etime[1] != saved_etime[1])) {
165 if (!found && (saved_eid > 0)) {
166 if (zpool_events_seek(zcp->zfs_hdl, ZEVENT_SEEK_START,
168 zed_log_msg(LOG_WARNING, "Failed to seek to eid=0");
172 zed_log_msg(LOG_NOTICE, "Processing events since eid=%llu", eid);
173 return (found ? 0 : -1);
177 * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0.
180 _zed_event_value_is_hex(const char *name)
182 const char *hex_suffix[] = {
193 for (pp = hex_suffix; *pp; pp++) {
194 p = strstr(name, *pp);
195 if (p && strlen(p) == strlen(*pp))
202 * Add an environment variable for [eid] to the container [zsp].
204 * The variable name is the concatenation of [prefix] and [name] converted to
205 * uppercase with non-alphanumeric characters converted to underscores;
206 * [prefix] is optional, and [name] must begin with an alphabetic character.
207 * If the converted variable name already exists within the container [zsp],
208 * its existing value will be replaced with the new value.
210 * The variable value is specified by the format string [fmt].
212 * Returns 0 on success, and -1 on error (with errno set).
214 * All environment variables in [zsp] should be added through this function.
217 _zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
218 const char *prefix, const char *name, const char *fmt, ...)
234 zed_log_msg(LOG_WARNING,
235 "Failed to add variable for eid=%llu: Name is empty", eid);
237 } else if (!isalpha(name[0])) {
239 zed_log_msg(LOG_WARNING,
240 "Failed to add variable for eid=%llu: "
241 "Name \"%s\" is invalid", eid, name);
245 * Construct the string key by converting PREFIX (if present) and NAME.
248 lastp = keybuf + sizeof (keybuf);
250 for (srcp = prefix; *srcp && (dstp < lastp); srcp++)
251 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
253 for (srcp = name; *srcp && (dstp < lastp); srcp++)
254 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
257 errno = ENAMETOOLONG;
258 zed_log_msg(LOG_WARNING,
259 "Failed to add variable for eid=%llu: Name too long", eid);
264 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
267 buflen = sizeof (valbuf);
268 n = strlcpy(dstp, keybuf, buflen);
269 if (n >= sizeof (valbuf)) {
271 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
272 keybuf, eid, "Exceeded buffer size");
283 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
284 keybuf, eid, "Exceeded buffer size");
288 va_start(vargs, fmt);
289 n = vsnprintf(dstp, buflen, fmt, vargs);
292 if ((n < 0) || (n >= buflen)) {
294 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
295 keybuf, eid, "Exceeded buffer size");
297 } else if (zed_strings_add(zsp, keybuf, valbuf) < 0) {
298 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
299 keybuf, eid, strerror(errno));
306 _zed_event_add_array_err(uint64_t eid, const char *name)
309 zed_log_msg(LOG_WARNING,
310 "Failed to convert nvpair \"%s\" for eid=%llu: "
311 "Exceeded buffer size", name, eid);
316 _zed_event_add_int8_array(uint64_t eid, zed_strings_t *zsp,
317 const char *prefix, nvpair_t *nvp)
320 int buflen = sizeof (buf);
328 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT8_ARRAY));
330 name = nvpair_name(nvp);
331 (void) nvpair_value_int8_array(nvp, &i8p, &nelem);
332 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
333 n = snprintf(p, buflen, "%d ", i8p[i]);
334 if ((n < 0) || (n >= buflen))
335 return (_zed_event_add_array_err(eid, name));
342 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
346 _zed_event_add_uint8_array(uint64_t eid, zed_strings_t *zsp,
347 const char *prefix, nvpair_t *nvp)
350 int buflen = sizeof (buf);
358 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT8_ARRAY));
360 name = nvpair_name(nvp);
361 (void) nvpair_value_uint8_array(nvp, &u8p, &nelem);
362 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
363 n = snprintf(p, buflen, "%u ", u8p[i]);
364 if ((n < 0) || (n >= buflen))
365 return (_zed_event_add_array_err(eid, name));
372 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
376 _zed_event_add_int16_array(uint64_t eid, zed_strings_t *zsp,
377 const char *prefix, nvpair_t *nvp)
380 int buflen = sizeof (buf);
388 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT16_ARRAY));
390 name = nvpair_name(nvp);
391 (void) nvpair_value_int16_array(nvp, &i16p, &nelem);
392 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
393 n = snprintf(p, buflen, "%d ", i16p[i]);
394 if ((n < 0) || (n >= buflen))
395 return (_zed_event_add_array_err(eid, name));
402 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
406 _zed_event_add_uint16_array(uint64_t eid, zed_strings_t *zsp,
407 const char *prefix, nvpair_t *nvp)
410 int buflen = sizeof (buf);
418 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY));
420 name = nvpair_name(nvp);
421 (void) nvpair_value_uint16_array(nvp, &u16p, &nelem);
422 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
423 n = snprintf(p, buflen, "%u ", u16p[i]);
424 if ((n < 0) || (n >= buflen))
425 return (_zed_event_add_array_err(eid, name));
432 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
436 _zed_event_add_int32_array(uint64_t eid, zed_strings_t *zsp,
437 const char *prefix, nvpair_t *nvp)
440 int buflen = sizeof (buf);
448 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT32_ARRAY));
450 name = nvpair_name(nvp);
451 (void) nvpair_value_int32_array(nvp, &i32p, &nelem);
452 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
453 n = snprintf(p, buflen, "%d ", i32p[i]);
454 if ((n < 0) || (n >= buflen))
455 return (_zed_event_add_array_err(eid, name));
462 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
466 _zed_event_add_uint32_array(uint64_t eid, zed_strings_t *zsp,
467 const char *prefix, nvpair_t *nvp)
470 int buflen = sizeof (buf);
478 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT32_ARRAY));
480 name = nvpair_name(nvp);
481 (void) nvpair_value_uint32_array(nvp, &u32p, &nelem);
482 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
483 n = snprintf(p, buflen, "%u ", u32p[i]);
484 if ((n < 0) || (n >= buflen))
485 return (_zed_event_add_array_err(eid, name));
492 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
496 _zed_event_add_int64_array(uint64_t eid, zed_strings_t *zsp,
497 const char *prefix, nvpair_t *nvp)
500 int buflen = sizeof (buf);
508 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT64_ARRAY));
510 name = nvpair_name(nvp);
511 (void) nvpair_value_int64_array(nvp, &i64p, &nelem);
512 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
513 n = snprintf(p, buflen, "%lld ", (u_longlong_t)i64p[i]);
514 if ((n < 0) || (n >= buflen))
515 return (_zed_event_add_array_err(eid, name));
522 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
526 _zed_event_add_uint64_array(uint64_t eid, zed_strings_t *zsp,
527 const char *prefix, nvpair_t *nvp)
530 int buflen = sizeof (buf);
539 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY));
541 name = nvpair_name(nvp);
542 fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu ";
543 (void) nvpair_value_uint64_array(nvp, &u64p, &nelem);
544 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
545 n = snprintf(p, buflen, fmt, (u_longlong_t)u64p[i]);
546 if ((n < 0) || (n >= buflen))
547 return (_zed_event_add_array_err(eid, name));
554 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
558 _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
559 const char *prefix, nvpair_t *nvp)
562 int buflen = sizeof (buf);
570 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY));
572 name = nvpair_name(nvp);
573 (void) nvpair_value_string_array(nvp, &strp, &nelem);
574 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
575 n = snprintf(p, buflen, "%s ", strp[i] ? strp[i] : "<NULL>");
576 if ((n < 0) || (n >= buflen))
577 return (_zed_event_add_array_err(eid, name));
584 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
588 * Convert the nvpair [nvp] to a string which is added to the environment
589 * of the child process.
590 * Return 0 on success, -1 on error.
592 * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()?
595 _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
599 const char *prefix = ZEVENT_VAR_PREFIX;
611 name = nvpair_name(nvp);
612 type = nvpair_type(nvp);
615 case DATA_TYPE_BOOLEAN:
616 _zed_event_add_var(eid, zsp, prefix, name, "%s", "1");
618 case DATA_TYPE_BOOLEAN_VALUE:
619 (void) nvpair_value_boolean_value(nvp, &b);
620 _zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0");
623 (void) nvpair_value_byte(nvp, &i8);
624 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
627 (void) nvpair_value_int8(nvp, (int8_t *)&i8);
628 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
630 case DATA_TYPE_UINT8:
631 (void) nvpair_value_uint8(nvp, &i8);
632 _zed_event_add_var(eid, zsp, prefix, name, "%u", i8);
634 case DATA_TYPE_INT16:
635 (void) nvpair_value_int16(nvp, (int16_t *)&i16);
636 _zed_event_add_var(eid, zsp, prefix, name, "%d", i16);
638 case DATA_TYPE_UINT16:
639 (void) nvpair_value_uint16(nvp, &i16);
640 _zed_event_add_var(eid, zsp, prefix, name, "%u", i16);
642 case DATA_TYPE_INT32:
643 (void) nvpair_value_int32(nvp, (int32_t *)&i32);
644 _zed_event_add_var(eid, zsp, prefix, name, "%d", i32);
646 case DATA_TYPE_UINT32:
647 (void) nvpair_value_uint32(nvp, &i32);
648 _zed_event_add_var(eid, zsp, prefix, name, "%u", i32);
650 case DATA_TYPE_INT64:
651 (void) nvpair_value_int64(nvp, (int64_t *)&i64);
652 _zed_event_add_var(eid, zsp, prefix, name,
653 "%lld", (longlong_t)i64);
655 case DATA_TYPE_UINT64:
656 (void) nvpair_value_uint64(nvp, &i64);
657 _zed_event_add_var(eid, zsp, prefix, name,
658 (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"),
661 * shadow readable strings for vdev state pairs
663 if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
664 strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
667 (void) snprintf(alt, sizeof (alt), "%s_str", name);
668 _zed_event_add_var(eid, zsp, prefix, alt, "%s",
669 zpool_state_to_name(i64, VDEV_AUX_NONE));
672 * shadow readable strings for pool state
674 if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_POOL_STATE) == 0) {
677 (void) snprintf(alt, sizeof (alt), "%s_str", name);
678 _zed_event_add_var(eid, zsp, prefix, alt, "%s",
679 zpool_pool_state_to_name(i64));
682 case DATA_TYPE_DOUBLE:
683 (void) nvpair_value_double(nvp, &d);
684 _zed_event_add_var(eid, zsp, prefix, name, "%g", d);
686 case DATA_TYPE_HRTIME:
687 (void) nvpair_value_hrtime(nvp, (hrtime_t *)&i64);
688 _zed_event_add_var(eid, zsp, prefix, name,
689 "%llu", (u_longlong_t)i64);
691 case DATA_TYPE_NVLIST:
692 _zed_event_add_var(eid, zsp, prefix, name,
693 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
695 case DATA_TYPE_STRING:
696 (void) nvpair_value_string(nvp, &str);
697 _zed_event_add_var(eid, zsp, prefix, name,
698 "%s", (str ? str : "<NULL>"));
700 case DATA_TYPE_BOOLEAN_ARRAY:
701 _zed_event_add_var(eid, zsp, prefix, name,
702 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
704 case DATA_TYPE_BYTE_ARRAY:
705 _zed_event_add_var(eid, zsp, prefix, name,
706 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
708 case DATA_TYPE_INT8_ARRAY:
709 _zed_event_add_int8_array(eid, zsp, prefix, nvp);
711 case DATA_TYPE_UINT8_ARRAY:
712 _zed_event_add_uint8_array(eid, zsp, prefix, nvp);
714 case DATA_TYPE_INT16_ARRAY:
715 _zed_event_add_int16_array(eid, zsp, prefix, nvp);
717 case DATA_TYPE_UINT16_ARRAY:
718 _zed_event_add_uint16_array(eid, zsp, prefix, nvp);
720 case DATA_TYPE_INT32_ARRAY:
721 _zed_event_add_int32_array(eid, zsp, prefix, nvp);
723 case DATA_TYPE_UINT32_ARRAY:
724 _zed_event_add_uint32_array(eid, zsp, prefix, nvp);
726 case DATA_TYPE_INT64_ARRAY:
727 _zed_event_add_int64_array(eid, zsp, prefix, nvp);
729 case DATA_TYPE_UINT64_ARRAY:
730 _zed_event_add_uint64_array(eid, zsp, prefix, nvp);
732 case DATA_TYPE_STRING_ARRAY:
733 _zed_event_add_string_array(eid, zsp, prefix, nvp);
735 case DATA_TYPE_NVLIST_ARRAY:
736 _zed_event_add_var(eid, zsp, prefix, name,
737 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
741 zed_log_msg(LOG_WARNING,
742 "Failed to convert nvpair \"%s\" for eid=%llu: "
743 "Unrecognized type=%u", name, eid, (unsigned int) type);
749 * Restrict various environment variables to safe and sane values
750 * when constructing the environment for the child process, unless
751 * we're running with a custom $PATH (like under the ZFS test suite).
753 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
756 _zed_event_add_env_restrict(uint64_t eid, zed_strings_t *zsp,
759 const char *env_restrict[][2] = {
761 { "PATH", _PATH_STDPATH },
762 { "ZDB", SBINDIR "/zdb" },
763 { "ZED", SBINDIR "/zed" },
764 { "ZFS", SBINDIR "/zfs" },
765 { "ZINJECT", SBINDIR "/zinject" },
766 { "ZPOOL", SBINDIR "/zpool" },
767 { "ZFS_ALIAS", ZFS_META_ALIAS },
768 { "ZFS_VERSION", ZFS_META_VERSION },
769 { "ZFS_RELEASE", ZFS_META_RELEASE },
774 * If we have a custom $PATH, use the default ZFS binary locations
775 * instead of the hard-coded ones.
777 const char *env_path[][2] = {
779 { "PATH", NULL }, /* $PATH copied in later on */
783 { "ZINJECT", "zinject" },
784 { "ZPOOL", "zpool" },
785 { "ZFS_ALIAS", ZFS_META_ALIAS },
786 { "ZFS_VERSION", ZFS_META_VERSION },
787 { "ZFS_RELEASE", ZFS_META_RELEASE },
790 const char *(*pa)[2];
794 pa = path != NULL ? env_path : env_restrict;
796 for (; *(*pa); pa++) {
797 /* Use our custom $PATH if we have one */
798 if (path != NULL && strcmp((*pa)[0], "PATH") == 0)
801 _zed_event_add_var(eid, zsp, NULL, (*pa)[0], "%s", (*pa)[1]);
806 * Preserve specified variables from the parent environment
807 * when constructing the environment for the child process.
809 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
812 _zed_event_add_env_preserve(uint64_t eid, zed_strings_t *zsp)
814 const char *env_preserve[] = {
823 for (keyp = env_preserve; *keyp; keyp++) {
824 if ((val = getenv(*keyp)))
825 _zed_event_add_var(eid, zsp, NULL, *keyp, "%s", val);
830 * Compute the "subclass" by removing the first 3 components of [class]
831 * (which will always be of the form "*.fs.zfs"). Return a pointer inside
832 * the string [class], or NULL if insufficient components exist.
835 _zed_event_get_subclass(const char *class)
844 for (i = 0; i < 3; i++) {
854 * Convert the zevent time from a 2-element array of 64b integers
855 * into a more convenient form:
856 * - TIME_SECS is the second component of the time.
857 * - TIME_NSECS is the nanosecond component of the time.
858 * - TIME_STRING is an almost-RFC3339-compliant string representation.
861 _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
867 assert(etime != NULL);
869 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
870 "%lld", (long long int) etime[0]);
871 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
872 "%lld", (long long int) etime[1]);
874 if (!(stp = localtime((const time_t *) &etime[0]))) {
875 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
876 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
877 } else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", stp)) {
878 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
879 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
881 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_STRING",
887 * Service the next zevent, blocking until one is available.
890 zed_event_service(struct zed_conf *zcp)
900 const char *subclass;
905 zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
909 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
912 if ((rv != 0) || !nvl)
916 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
918 * FIXME: Increase max size of event nvlist in
919 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
922 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
923 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
924 } else if (nvlist_lookup_int64_array(
925 nvl, "time", &etime, &nelem) != 0) {
926 zed_log_msg(LOG_WARNING,
927 "Failed to lookup zevent time (eid=%llu)", eid);
928 } else if (nelem != 2) {
929 zed_log_msg(LOG_WARNING,
930 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
932 } else if (nvlist_lookup_string(nvl, "class", &class) != 0) {
933 zed_log_msg(LOG_WARNING,
934 "Failed to lookup zevent class (eid=%llu)", eid);
936 /* let internal modules see this event first */
937 zfs_agent_post_event(class, NULL, nvl);
939 zsp = zed_strings_create();
942 while ((nvp = nvlist_next_nvpair(nvl, nvp)))
943 _zed_event_add_nvpair(eid, zsp, nvp);
945 _zed_event_add_env_restrict(eid, zsp, zcp->path);
946 _zed_event_add_env_preserve(eid, zsp);
948 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "PID",
949 "%d", (int)getpid());
950 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "ZEDLET_DIR",
951 "%s", zcp->zedlet_dir);
952 subclass = _zed_event_get_subclass(class);
953 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "SUBCLASS",
954 "%s", (subclass ? subclass : class));
956 _zed_event_add_time_strings(eid, zsp, etime);
958 zed_exec_process(eid, class, subclass, zcp, zsp);
960 zed_conf_write_state(zcp, eid, etime);
962 zed_strings_destroy(zsp);