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 if (zfs_slm_init(zcp
->zfs_hdl
) != 0)
59 zed_log_die("Failed to initialize zfs slm");
60 if (zfs_diagnosis_init(zcp
->zfs_hdl
) != 0)
61 zed_log_die("Failed to initialize zfs diagnosis");
62 if (zfs_retire_init(zcp
->zfs_hdl
) != 0)
63 zed_log_die("Failed to initialize zfs retire");
64 if (zed_disk_event_init() != 0)
65 zed_log_die("Failed to initialize disk events");
69 * Close the libzfs interface.
72 zed_event_fini(struct zed_conf
*zcp
)
75 zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL
));
77 zed_disk_event_fini();
82 if (zcp
->zevent_fd
>= 0) {
83 if (close(zcp
->zevent_fd
) < 0)
84 zed_log_msg(LOG_WARNING
, "Failed to close \"%s\": %s",
85 ZFS_DEV
, strerror(errno
));
90 libzfs_fini(zcp
->zfs_hdl
);
96 * Seek to the event specified by [saved_eid] and [saved_etime].
97 * This protects against processing a given event more than once.
98 * Return 0 upon a successful seek to the specified event, or -1 otherwise.
100 * A zevent is considered to be uniquely specified by its (eid,time) tuple.
101 * The unsigned 64b eid is set to 1 when the kernel module is loaded, and
102 * incremented by 1 for each new event. Since the state file can persist
103 * across a kernel module reload, the time must be checked to ensure a match.
106 zed_event_seek(struct zed_conf
*zcp
, uint64_t saved_eid
, int64_t saved_etime
[])
118 zed_log_msg(LOG_ERR
, "Failed to seek zevent: %s",
124 while ((eid
< saved_eid
) && !found
) {
125 rv
= zpool_events_next(zcp
->zfs_hdl
, &nvl
, &n_dropped
,
126 ZEVENT_NONBLOCK
, zcp
->zevent_fd
);
128 if ((rv
!= 0) || !nvl
)
132 zed_log_msg(LOG_WARNING
, "Missed %d events", n_dropped
);
134 * FIXME: Increase max size of event nvlist in
135 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
138 if (nvlist_lookup_uint64(nvl
, "eid", &eid
) != 0) {
139 zed_log_msg(LOG_WARNING
, "Failed to lookup zevent eid");
140 } else if (nvlist_lookup_int64_array(nvl
, "time",
141 &etime
, &nelem
) != 0) {
142 zed_log_msg(LOG_WARNING
,
143 "Failed to lookup zevent time (eid=%llu)", eid
);
144 } else if (nelem
!= 2) {
145 zed_log_msg(LOG_WARNING
,
146 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
148 } else if ((eid
!= saved_eid
) ||
149 (etime
[0] != saved_etime
[0]) ||
150 (etime
[1] != saved_etime
[1])) {
157 if (!found
&& (saved_eid
> 0)) {
158 if (zpool_events_seek(zcp
->zfs_hdl
, ZEVENT_SEEK_START
,
160 zed_log_msg(LOG_WARNING
, "Failed to seek to eid=0");
164 zed_log_msg(LOG_NOTICE
, "Processing events since eid=%llu", eid
);
165 return (found
? 0 : -1);
169 * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0.
172 _zed_event_value_is_hex(const char *name
)
174 const char *hex_suffix
[] = {
185 for (pp
= hex_suffix
; *pp
; pp
++) {
186 p
= strstr(name
, *pp
);
187 if (p
&& strlen(p
) == strlen(*pp
))
194 * Add an environment variable for [eid] to the container [zsp].
196 * The variable name is the concatenation of [prefix] and [name] converted to
197 * uppercase with non-alphanumeric characters converted to underscores;
198 * [prefix] is optional, and [name] must begin with an alphabetic character.
199 * If the converted variable name already exists within the container [zsp],
200 * its existing value will be replaced with the new value.
202 * The variable value is specified by the format string [fmt].
204 * Returns 0 on success, and -1 on error (with errno set).
206 * All environment variables in [zsp] should be added through this function.
209 _zed_event_add_var(uint64_t eid
, zed_strings_t
*zsp
,
210 const char *prefix
, const char *name
, const char *fmt
, ...)
226 zed_log_msg(LOG_WARNING
,
227 "Failed to add variable for eid=%llu: Name is empty", eid
);
229 } else if (!isalpha(name
[0])) {
231 zed_log_msg(LOG_WARNING
,
232 "Failed to add variable for eid=%llu: "
233 "Name \"%s\" is invalid", eid
, name
);
237 * Construct the string key by converting PREFIX (if present) and NAME.
240 lastp
= keybuf
+ sizeof (keybuf
);
242 for (srcp
= prefix
; *srcp
&& (dstp
< lastp
); srcp
++)
243 *dstp
++ = isalnum(*srcp
) ? toupper(*srcp
) : '_';
245 for (srcp
= name
; *srcp
&& (dstp
< lastp
); srcp
++)
246 *dstp
++ = isalnum(*srcp
) ? toupper(*srcp
) : '_';
249 errno
= ENAMETOOLONG
;
250 zed_log_msg(LOG_WARNING
,
251 "Failed to add variable for eid=%llu: Name too long", eid
);
256 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
259 buflen
= sizeof (valbuf
);
260 n
= strlcpy(dstp
, keybuf
, buflen
);
261 if (n
>= sizeof (valbuf
)) {
263 zed_log_msg(LOG_WARNING
, "Failed to add %s for eid=%llu: %s",
264 keybuf
, eid
, "Exceeded buffer size");
273 va_start(vargs
, fmt
);
274 n
= vsnprintf(dstp
, buflen
, fmt
, vargs
);
277 if ((n
< 0) || (n
>= buflen
)) {
279 zed_log_msg(LOG_WARNING
, "Failed to add %s for eid=%llu: %s",
280 keybuf
, eid
, "Exceeded buffer size");
282 } else if (zed_strings_add(zsp
, keybuf
, valbuf
) < 0) {
283 zed_log_msg(LOG_WARNING
, "Failed to add %s for eid=%llu: %s",
284 keybuf
, eid
, strerror(errno
));
291 _zed_event_add_array_err(uint64_t eid
, const char *name
)
294 zed_log_msg(LOG_WARNING
,
295 "Failed to convert nvpair \"%s\" for eid=%llu: "
296 "Exceeded buffer size", name
, eid
);
301 _zed_event_add_int8_array(uint64_t eid
, zed_strings_t
*zsp
,
302 const char *prefix
, nvpair_t
*nvp
)
305 int buflen
= sizeof (buf
);
313 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_INT8_ARRAY
));
315 name
= nvpair_name(nvp
);
316 (void) nvpair_value_int8_array(nvp
, &i8p
, &nelem
);
317 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
318 n
= snprintf(p
, buflen
, "%d ", i8p
[i
]);
319 if ((n
< 0) || (n
>= buflen
))
320 return (_zed_event_add_array_err(eid
, name
));
327 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
331 _zed_event_add_uint8_array(uint64_t eid
, zed_strings_t
*zsp
,
332 const char *prefix
, nvpair_t
*nvp
)
335 int buflen
= sizeof (buf
);
343 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_UINT8_ARRAY
));
345 name
= nvpair_name(nvp
);
346 (void) nvpair_value_uint8_array(nvp
, &u8p
, &nelem
);
347 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
348 n
= snprintf(p
, buflen
, "%u ", u8p
[i
]);
349 if ((n
< 0) || (n
>= buflen
))
350 return (_zed_event_add_array_err(eid
, name
));
357 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
361 _zed_event_add_int16_array(uint64_t eid
, zed_strings_t
*zsp
,
362 const char *prefix
, nvpair_t
*nvp
)
365 int buflen
= sizeof (buf
);
373 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_INT16_ARRAY
));
375 name
= nvpair_name(nvp
);
376 (void) nvpair_value_int16_array(nvp
, &i16p
, &nelem
);
377 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
378 n
= snprintf(p
, buflen
, "%d ", i16p
[i
]);
379 if ((n
< 0) || (n
>= buflen
))
380 return (_zed_event_add_array_err(eid
, name
));
387 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
391 _zed_event_add_uint16_array(uint64_t eid
, zed_strings_t
*zsp
,
392 const char *prefix
, nvpair_t
*nvp
)
395 int buflen
= sizeof (buf
);
403 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_UINT16_ARRAY
));
405 name
= nvpair_name(nvp
);
406 (void) nvpair_value_uint16_array(nvp
, &u16p
, &nelem
);
407 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
408 n
= snprintf(p
, buflen
, "%u ", u16p
[i
]);
409 if ((n
< 0) || (n
>= buflen
))
410 return (_zed_event_add_array_err(eid
, name
));
417 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
421 _zed_event_add_int32_array(uint64_t eid
, zed_strings_t
*zsp
,
422 const char *prefix
, nvpair_t
*nvp
)
425 int buflen
= sizeof (buf
);
433 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_INT32_ARRAY
));
435 name
= nvpair_name(nvp
);
436 (void) nvpair_value_int32_array(nvp
, &i32p
, &nelem
);
437 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
438 n
= snprintf(p
, buflen
, "%d ", i32p
[i
]);
439 if ((n
< 0) || (n
>= buflen
))
440 return (_zed_event_add_array_err(eid
, name
));
447 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
451 _zed_event_add_uint32_array(uint64_t eid
, zed_strings_t
*zsp
,
452 const char *prefix
, nvpair_t
*nvp
)
455 int buflen
= sizeof (buf
);
463 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_UINT32_ARRAY
));
465 name
= nvpair_name(nvp
);
466 (void) nvpair_value_uint32_array(nvp
, &u32p
, &nelem
);
467 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
468 n
= snprintf(p
, buflen
, "%u ", u32p
[i
]);
469 if ((n
< 0) || (n
>= buflen
))
470 return (_zed_event_add_array_err(eid
, name
));
477 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
481 _zed_event_add_int64_array(uint64_t eid
, zed_strings_t
*zsp
,
482 const char *prefix
, nvpair_t
*nvp
)
485 int buflen
= sizeof (buf
);
493 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_INT64_ARRAY
));
495 name
= nvpair_name(nvp
);
496 (void) nvpair_value_int64_array(nvp
, &i64p
, &nelem
);
497 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
498 n
= snprintf(p
, buflen
, "%lld ", (u_longlong_t
) i64p
[i
]);
499 if ((n
< 0) || (n
>= buflen
))
500 return (_zed_event_add_array_err(eid
, name
));
507 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
511 _zed_event_add_uint64_array(uint64_t eid
, zed_strings_t
*zsp
,
512 const char *prefix
, nvpair_t
*nvp
)
515 int buflen
= sizeof (buf
);
524 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_UINT64_ARRAY
));
526 name
= nvpair_name(nvp
);
527 fmt
= _zed_event_value_is_hex(name
) ? "0x%.16llX " : "%llu ";
528 (void) nvpair_value_uint64_array(nvp
, &u64p
, &nelem
);
529 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
530 n
= snprintf(p
, buflen
, fmt
, (u_longlong_t
) u64p
[i
]);
531 if ((n
< 0) || (n
>= buflen
))
532 return (_zed_event_add_array_err(eid
, name
));
539 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
543 _zed_event_add_string_array(uint64_t eid
, zed_strings_t
*zsp
,
544 const char *prefix
, nvpair_t
*nvp
)
547 int buflen
= sizeof (buf
);
555 assert((nvp
!= NULL
) && (nvpair_type(nvp
) == DATA_TYPE_STRING_ARRAY
));
557 name
= nvpair_name(nvp
);
558 (void) nvpair_value_string_array(nvp
, &strp
, &nelem
);
559 for (i
= 0, p
= buf
; (i
< nelem
) && (buflen
> 0); i
++) {
560 n
= snprintf(p
, buflen
, "%s ", strp
[i
] ? strp
[i
] : "<NULL>");
561 if ((n
< 0) || (n
>= buflen
))
562 return (_zed_event_add_array_err(eid
, name
));
569 return (_zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", buf
));
573 * Convert the nvpair [nvp] to a string which is added to the environment
574 * of the child process.
575 * Return 0 on success, -1 on error.
577 * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()?
580 _zed_event_add_nvpair(uint64_t eid
, zed_strings_t
*zsp
, nvpair_t
*nvp
)
584 const char *prefix
= ZEVENT_VAR_PREFIX
;
596 name
= nvpair_name(nvp
);
597 type
= nvpair_type(nvp
);
600 case DATA_TYPE_BOOLEAN
:
601 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", "1");
603 case DATA_TYPE_BOOLEAN_VALUE
:
604 (void) nvpair_value_boolean_value(nvp
, &b
);
605 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%s", b
? "1" : "0");
608 (void) nvpair_value_byte(nvp
, &i8
);
609 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%d", i8
);
612 (void) nvpair_value_int8(nvp
, (int8_t *) &i8
);
613 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%d", i8
);
615 case DATA_TYPE_UINT8
:
616 (void) nvpair_value_uint8(nvp
, &i8
);
617 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%u", i8
);
619 case DATA_TYPE_INT16
:
620 (void) nvpair_value_int16(nvp
, (int16_t *) &i16
);
621 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%d", i16
);
623 case DATA_TYPE_UINT16
:
624 (void) nvpair_value_uint16(nvp
, &i16
);
625 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%u", i16
);
627 case DATA_TYPE_INT32
:
628 (void) nvpair_value_int32(nvp
, (int32_t *) &i32
);
629 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%d", i32
);
631 case DATA_TYPE_UINT32
:
632 (void) nvpair_value_uint32(nvp
, &i32
);
633 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%u", i32
);
635 case DATA_TYPE_INT64
:
636 (void) nvpair_value_int64(nvp
, (int64_t *) &i64
);
637 _zed_event_add_var(eid
, zsp
, prefix
, name
,
638 "%lld", (longlong_t
) i64
);
640 case DATA_TYPE_UINT64
:
641 (void) nvpair_value_uint64(nvp
, &i64
);
642 _zed_event_add_var(eid
, zsp
, prefix
, name
,
643 (_zed_event_value_is_hex(name
) ? "0x%.16llX" : "%llu"),
646 * shadow readable strings for vdev state pairs
648 if (strcmp(name
, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE
) == 0 ||
649 strcmp(name
, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE
) == 0) {
652 (void) snprintf(alt
, sizeof (alt
), "%s_str", name
);
653 _zed_event_add_var(eid
, zsp
, prefix
, alt
, "%s",
654 zpool_state_to_name(i64
, VDEV_AUX_NONE
));
657 case DATA_TYPE_DOUBLE
:
658 (void) nvpair_value_double(nvp
, &d
);
659 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%g", d
);
661 case DATA_TYPE_HRTIME
:
662 (void) nvpair_value_hrtime(nvp
, (hrtime_t
*) &i64
);
663 _zed_event_add_var(eid
, zsp
, prefix
, name
,
664 "%llu", (u_longlong_t
) i64
);
666 case DATA_TYPE_NVLIST
:
667 _zed_event_add_var(eid
, zsp
, prefix
, name
,
668 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
670 case DATA_TYPE_STRING
:
671 (void) nvpair_value_string(nvp
, &str
);
672 _zed_event_add_var(eid
, zsp
, prefix
, name
,
673 "%s", (str
? str
: "<NULL>"));
675 case DATA_TYPE_BOOLEAN_ARRAY
:
676 _zed_event_add_var(eid
, zsp
, prefix
, name
,
677 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
679 case DATA_TYPE_BYTE_ARRAY
:
680 _zed_event_add_var(eid
, zsp
, prefix
, name
,
681 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
683 case DATA_TYPE_INT8_ARRAY
:
684 _zed_event_add_int8_array(eid
, zsp
, prefix
, nvp
);
686 case DATA_TYPE_UINT8_ARRAY
:
687 _zed_event_add_uint8_array(eid
, zsp
, prefix
, nvp
);
689 case DATA_TYPE_INT16_ARRAY
:
690 _zed_event_add_int16_array(eid
, zsp
, prefix
, nvp
);
692 case DATA_TYPE_UINT16_ARRAY
:
693 _zed_event_add_uint16_array(eid
, zsp
, prefix
, nvp
);
695 case DATA_TYPE_INT32_ARRAY
:
696 _zed_event_add_int32_array(eid
, zsp
, prefix
, nvp
);
698 case DATA_TYPE_UINT32_ARRAY
:
699 _zed_event_add_uint32_array(eid
, zsp
, prefix
, nvp
);
701 case DATA_TYPE_INT64_ARRAY
:
702 _zed_event_add_int64_array(eid
, zsp
, prefix
, nvp
);
704 case DATA_TYPE_UINT64_ARRAY
:
705 _zed_event_add_uint64_array(eid
, zsp
, prefix
, nvp
);
707 case DATA_TYPE_STRING_ARRAY
:
708 _zed_event_add_string_array(eid
, zsp
, prefix
, nvp
);
710 case DATA_TYPE_NVLIST_ARRAY
:
711 _zed_event_add_var(eid
, zsp
, prefix
, name
,
712 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
716 zed_log_msg(LOG_WARNING
,
717 "Failed to convert nvpair \"%s\" for eid=%llu: "
718 "Unrecognized type=%u", name
, eid
, (unsigned int) type
);
724 * Restrict various environment variables to safe and sane values
725 * when constructing the environment for the child process.
727 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
730 _zed_event_add_env_restrict(uint64_t eid
, zed_strings_t
*zsp
)
732 const char *env_restrict
[][2] = {
734 { "PATH", _PATH_STDPATH
},
735 { "ZDB", SBINDIR
"/zdb" },
736 { "ZED", SBINDIR
"/zed" },
737 { "ZFS", SBINDIR
"/zfs" },
738 { "ZINJECT", SBINDIR
"/zinject" },
739 { "ZPOOL", SBINDIR
"/zpool" },
740 { "ZFS_ALIAS", ZFS_META_ALIAS
},
741 { "ZFS_VERSION", ZFS_META_VERSION
},
742 { "ZFS_RELEASE", ZFS_META_RELEASE
},
745 const char *(*pa
)[2];
749 for (pa
= env_restrict
; *(*pa
); pa
++) {
750 _zed_event_add_var(eid
, zsp
, NULL
, (*pa
)[0], "%s", (*pa
)[1]);
755 * Preserve specified variables from the parent environment
756 * when constructing the environment for the child process.
758 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
761 _zed_event_add_env_preserve(uint64_t eid
, zed_strings_t
*zsp
)
763 const char *env_preserve
[] = {
772 for (keyp
= env_preserve
; *keyp
; keyp
++) {
773 if ((val
= getenv(*keyp
)))
774 _zed_event_add_var(eid
, zsp
, NULL
, *keyp
, "%s", val
);
779 * Compute the "subclass" by removing the first 3 components of [class]
780 * (which will always be of the form "*.fs.zfs"). Return a pointer inside
781 * the string [class], or NULL if insufficient components exist.
784 _zed_event_get_subclass(const char *class)
793 for (i
= 0; i
< 3; i
++) {
803 * Convert the zevent time from a 2-element array of 64b integers
804 * into a more convenient form:
805 * - TIME_SECS is the second component of the time.
806 * - TIME_NSECS is the nanosecond component of the time.
807 * - TIME_STRING is an almost-RFC3339-compliant string representation.
810 _zed_event_add_time_strings(uint64_t eid
, zed_strings_t
*zsp
, int64_t etime
[])
816 assert(etime
!= NULL
);
818 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_SECS",
819 "%lld", (long long int) etime
[0]);
820 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_NSECS",
821 "%lld", (long long int) etime
[1]);
823 if (!(stp
= localtime((const time_t *) &etime
[0]))) {
824 zed_log_msg(LOG_WARNING
, "Failed to add %s%s for eid=%llu: %s",
825 ZEVENT_VAR_PREFIX
, "TIME_STRING", eid
, "localtime error");
826 } else if (!strftime(buf
, sizeof (buf
), "%Y-%m-%d %H:%M:%S%z", stp
)) {
827 zed_log_msg(LOG_WARNING
, "Failed to add %s%s for eid=%llu: %s",
828 ZEVENT_VAR_PREFIX
, "TIME_STRING", eid
, "strftime error");
830 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_STRING",
836 _zed_internal_event(const char *class, nvlist_t
*nvl
)
839 * NOTE: only vdev check is handled for now
841 if (strcmp(class, "sysevent.fs.zfs.vdev_check") == 0) {
842 (void) zfs_slm_event("EC_zfs", "ESC_ZFS_vdev_check", nvl
);
847 * Service the next zevent, blocking until one is available.
850 zed_event_service(struct zed_conf
*zcp
)
860 const char *subclass
;
865 zed_log_msg(LOG_ERR
, "Failed to service zevent: %s",
869 rv
= zpool_events_next(zcp
->zfs_hdl
, &nvl
, &n_dropped
, ZEVENT_NONE
,
872 if ((rv
!= 0) || !nvl
)
876 zed_log_msg(LOG_WARNING
, "Missed %d events", n_dropped
);
878 * FIXME: Increase max size of event nvlist in
879 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
882 if (nvlist_lookup_uint64(nvl
, "eid", &eid
) != 0) {
883 zed_log_msg(LOG_WARNING
, "Failed to lookup zevent eid");
884 } else if (nvlist_lookup_int64_array(
885 nvl
, "time", &etime
, &nelem
) != 0) {
886 zed_log_msg(LOG_WARNING
,
887 "Failed to lookup zevent time (eid=%llu)", eid
);
888 } else if (nelem
!= 2) {
889 zed_log_msg(LOG_WARNING
,
890 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
892 } else if (nvlist_lookup_string(nvl
, "class", &class) != 0) {
893 zed_log_msg(LOG_WARNING
,
894 "Failed to lookup zevent class (eid=%llu)", eid
);
896 /* let internal modules see this event first */
897 _zed_internal_event(class, nvl
);
899 zsp
= zed_strings_create();
902 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)))
903 _zed_event_add_nvpair(eid
, zsp
, nvp
);
905 _zed_event_add_env_restrict(eid
, zsp
);
906 _zed_event_add_env_preserve(eid
, zsp
);
908 _zed_event_add_var(eid
, zsp
, ZED_VAR_PREFIX
, "PID",
909 "%d", (int) getpid());
910 _zed_event_add_var(eid
, zsp
, ZED_VAR_PREFIX
, "ZEDLET_DIR",
911 "%s", zcp
->zedlet_dir
);
912 subclass
= _zed_event_get_subclass(class);
913 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "SUBCLASS",
914 "%s", (subclass
? subclass
: class));
916 _zed_event_add_time_strings(eid
, zsp
, etime
);
918 zed_exec_process(eid
, class, subclass
,
919 zcp
->zedlet_dir
, zcp
->zedlets
, zsp
, zcp
->zevent_fd
);
921 zed_conf_write_state(zcp
, eid
, etime
);
923 zed_strings_destroy(zsp
);