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 * shadow readable strings for pool state
660 if (strcmp(name
, FM_EREPORT_PAYLOAD_ZFS_POOL_STATE
) == 0) {
663 (void) snprintf(alt
, sizeof (alt
), "%s_str", name
);
664 _zed_event_add_var(eid
, zsp
, prefix
, alt
, "%s",
665 zpool_pool_state_to_name(i64
));
668 case DATA_TYPE_DOUBLE
:
669 (void) nvpair_value_double(nvp
, &d
);
670 _zed_event_add_var(eid
, zsp
, prefix
, name
, "%g", d
);
672 case DATA_TYPE_HRTIME
:
673 (void) nvpair_value_hrtime(nvp
, (hrtime_t
*)&i64
);
674 _zed_event_add_var(eid
, zsp
, prefix
, name
,
675 "%llu", (u_longlong_t
)i64
);
677 case DATA_TYPE_NVLIST
:
678 _zed_event_add_var(eid
, zsp
, prefix
, name
,
679 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
681 case DATA_TYPE_STRING
:
682 (void) nvpair_value_string(nvp
, &str
);
683 _zed_event_add_var(eid
, zsp
, prefix
, name
,
684 "%s", (str
? str
: "<NULL>"));
686 case DATA_TYPE_BOOLEAN_ARRAY
:
687 _zed_event_add_var(eid
, zsp
, prefix
, name
,
688 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
690 case DATA_TYPE_BYTE_ARRAY
:
691 _zed_event_add_var(eid
, zsp
, prefix
, name
,
692 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
694 case DATA_TYPE_INT8_ARRAY
:
695 _zed_event_add_int8_array(eid
, zsp
, prefix
, nvp
);
697 case DATA_TYPE_UINT8_ARRAY
:
698 _zed_event_add_uint8_array(eid
, zsp
, prefix
, nvp
);
700 case DATA_TYPE_INT16_ARRAY
:
701 _zed_event_add_int16_array(eid
, zsp
, prefix
, nvp
);
703 case DATA_TYPE_UINT16_ARRAY
:
704 _zed_event_add_uint16_array(eid
, zsp
, prefix
, nvp
);
706 case DATA_TYPE_INT32_ARRAY
:
707 _zed_event_add_int32_array(eid
, zsp
, prefix
, nvp
);
709 case DATA_TYPE_UINT32_ARRAY
:
710 _zed_event_add_uint32_array(eid
, zsp
, prefix
, nvp
);
712 case DATA_TYPE_INT64_ARRAY
:
713 _zed_event_add_int64_array(eid
, zsp
, prefix
, nvp
);
715 case DATA_TYPE_UINT64_ARRAY
:
716 _zed_event_add_uint64_array(eid
, zsp
, prefix
, nvp
);
718 case DATA_TYPE_STRING_ARRAY
:
719 _zed_event_add_string_array(eid
, zsp
, prefix
, nvp
);
721 case DATA_TYPE_NVLIST_ARRAY
:
722 _zed_event_add_var(eid
, zsp
, prefix
, name
,
723 "%s", "_NOT_IMPLEMENTED_"); /* FIXME */
727 zed_log_msg(LOG_WARNING
,
728 "Failed to convert nvpair \"%s\" for eid=%llu: "
729 "Unrecognized type=%u", name
, eid
, (unsigned int) type
);
735 * Restrict various environment variables to safe and sane values
736 * when constructing the environment for the child process, unless
737 * we're running with a custom $PATH (like under the ZFS test suite).
739 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
742 _zed_event_add_env_restrict(uint64_t eid
, zed_strings_t
*zsp
,
745 const char *env_restrict
[][2] = {
747 { "PATH", _PATH_STDPATH
},
748 { "ZDB", SBINDIR
"/zdb" },
749 { "ZED", SBINDIR
"/zed" },
750 { "ZFS", SBINDIR
"/zfs" },
751 { "ZINJECT", SBINDIR
"/zinject" },
752 { "ZPOOL", SBINDIR
"/zpool" },
753 { "ZFS_ALIAS", ZFS_META_ALIAS
},
754 { "ZFS_VERSION", ZFS_META_VERSION
},
755 { "ZFS_RELEASE", ZFS_META_RELEASE
},
760 * If we have a custom $PATH, use the default ZFS binary locations
761 * instead of the hard-coded ones.
763 const char *env_path
[][2] = {
765 { "PATH", NULL
}, /* $PATH copied in later on */
769 { "ZINJECT", "zinject" },
770 { "ZPOOL", "zpool" },
771 { "ZFS_ALIAS", ZFS_META_ALIAS
},
772 { "ZFS_VERSION", ZFS_META_VERSION
},
773 { "ZFS_RELEASE", ZFS_META_RELEASE
},
776 const char *(*pa
)[2];
780 pa
= path
!= NULL
? env_path
: env_restrict
;
782 for (; *(*pa
); pa
++) {
783 /* Use our custom $PATH if we have one */
784 if (path
!= NULL
&& strcmp((*pa
)[0], "PATH") == 0)
787 _zed_event_add_var(eid
, zsp
, NULL
, (*pa
)[0], "%s", (*pa
)[1]);
792 * Preserve specified variables from the parent environment
793 * when constructing the environment for the child process.
795 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
798 _zed_event_add_env_preserve(uint64_t eid
, zed_strings_t
*zsp
)
800 const char *env_preserve
[] = {
809 for (keyp
= env_preserve
; *keyp
; keyp
++) {
810 if ((val
= getenv(*keyp
)))
811 _zed_event_add_var(eid
, zsp
, NULL
, *keyp
, "%s", val
);
816 * Compute the "subclass" by removing the first 3 components of [class]
817 * (which will always be of the form "*.fs.zfs"). Return a pointer inside
818 * the string [class], or NULL if insufficient components exist.
821 _zed_event_get_subclass(const char *class)
830 for (i
= 0; i
< 3; i
++) {
840 * Convert the zevent time from a 2-element array of 64b integers
841 * into a more convenient form:
842 * - TIME_SECS is the second component of the time.
843 * - TIME_NSECS is the nanosecond component of the time.
844 * - TIME_STRING is an almost-RFC3339-compliant string representation.
847 _zed_event_add_time_strings(uint64_t eid
, zed_strings_t
*zsp
, int64_t etime
[])
853 assert(etime
!= NULL
);
855 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_SECS",
856 "%lld", (long long int) etime
[0]);
857 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_NSECS",
858 "%lld", (long long int) etime
[1]);
860 if (!(stp
= localtime((const time_t *) &etime
[0]))) {
861 zed_log_msg(LOG_WARNING
, "Failed to add %s%s for eid=%llu: %s",
862 ZEVENT_VAR_PREFIX
, "TIME_STRING", eid
, "localtime error");
863 } else if (!strftime(buf
, sizeof (buf
), "%Y-%m-%d %H:%M:%S%z", stp
)) {
864 zed_log_msg(LOG_WARNING
, "Failed to add %s%s for eid=%llu: %s",
865 ZEVENT_VAR_PREFIX
, "TIME_STRING", eid
, "strftime error");
867 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "TIME_STRING",
873 * Service the next zevent, blocking until one is available.
876 zed_event_service(struct zed_conf
*zcp
)
886 const char *subclass
;
891 zed_log_msg(LOG_ERR
, "Failed to service zevent: %s",
895 rv
= zpool_events_next(zcp
->zfs_hdl
, &nvl
, &n_dropped
, ZEVENT_NONE
,
898 if ((rv
!= 0) || !nvl
)
902 zed_log_msg(LOG_WARNING
, "Missed %d events", n_dropped
);
904 * FIXME: Increase max size of event nvlist in
905 * /sys/module/zfs/parameters/zfs_zevent_len_max ?
908 if (nvlist_lookup_uint64(nvl
, "eid", &eid
) != 0) {
909 zed_log_msg(LOG_WARNING
, "Failed to lookup zevent eid");
910 } else if (nvlist_lookup_int64_array(
911 nvl
, "time", &etime
, &nelem
) != 0) {
912 zed_log_msg(LOG_WARNING
,
913 "Failed to lookup zevent time (eid=%llu)", eid
);
914 } else if (nelem
!= 2) {
915 zed_log_msg(LOG_WARNING
,
916 "Failed to lookup zevent time (eid=%llu, nelem=%u)",
918 } else if (nvlist_lookup_string(nvl
, "class", &class) != 0) {
919 zed_log_msg(LOG_WARNING
,
920 "Failed to lookup zevent class (eid=%llu)", eid
);
922 /* let internal modules see this event first */
923 zfs_agent_post_event(class, NULL
, nvl
);
925 zsp
= zed_strings_create();
928 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)))
929 _zed_event_add_nvpair(eid
, zsp
, nvp
);
931 _zed_event_add_env_restrict(eid
, zsp
, zcp
->path
);
932 _zed_event_add_env_preserve(eid
, zsp
);
934 _zed_event_add_var(eid
, zsp
, ZED_VAR_PREFIX
, "PID",
935 "%d", (int)getpid());
936 _zed_event_add_var(eid
, zsp
, ZED_VAR_PREFIX
, "ZEDLET_DIR",
937 "%s", zcp
->zedlet_dir
);
938 subclass
= _zed_event_get_subclass(class);
939 _zed_event_add_var(eid
, zsp
, ZEVENT_VAR_PREFIX
, "SUBCLASS",
940 "%s", (subclass
? subclass
: class));
942 _zed_event_add_time_strings(eid
, zsp
, etime
);
944 zed_exec_process(eid
, class, subclass
,
945 zcp
->zedlet_dir
, zcp
->zedlets
, zsp
, zcp
->zevent_fd
);
947 zed_conf_write_state(zcp
, eid
, etime
);
949 zed_strings_destroy(zsp
);