xref: /freebsd-src/sys/contrib/openzfs/cmd/zed/zed_event.c (revision 14c2e0a0c57e48a41433fdca668fac8882fb04df)
1eda14cbcSMatt Macy /*
2180f8225SMatt Macy  * This file is part of the ZFS Event Daemon (ZED).
3180f8225SMatt Macy  *
4eda14cbcSMatt Macy  * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
5eda14cbcSMatt Macy  * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
616038816SMartin Matuska  * Refer to the OpenZFS git commit log for authoritative copyright attribution.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
9eda14cbcSMatt Macy  * Common Development and Distribution License Version 1.0 (CDDL-1.0).
10eda14cbcSMatt Macy  * You can obtain a copy of the license from the top-level file
11eda14cbcSMatt Macy  * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
12eda14cbcSMatt Macy  * You may not use this file except in compliance with the license.
13eda14cbcSMatt Macy  */
14eda14cbcSMatt Macy 
15eda14cbcSMatt Macy #include <ctype.h>
16eda14cbcSMatt Macy #include <errno.h>
17eda14cbcSMatt Macy #include <fcntl.h>
1816038816SMartin Matuska #include <libzfs_core.h>
19eda14cbcSMatt Macy #include <paths.h>
20eda14cbcSMatt Macy #include <stdarg.h>
21eda14cbcSMatt Macy #include <stdio.h>
22eda14cbcSMatt Macy #include <stdlib.h>
23eda14cbcSMatt Macy #include <string.h>
24eda14cbcSMatt Macy #include <sys/zfs_ioctl.h>
25eda14cbcSMatt Macy #include <time.h>
26eda14cbcSMatt Macy #include <unistd.h>
27eda14cbcSMatt Macy #include <sys/fm/fs/zfs.h>
28eda14cbcSMatt Macy #include "zed.h"
29eda14cbcSMatt Macy #include "zed_conf.h"
30eda14cbcSMatt Macy #include "zed_disk_event.h"
31eda14cbcSMatt Macy #include "zed_event.h"
32eda14cbcSMatt Macy #include "zed_exec.h"
33eda14cbcSMatt Macy #include "zed_file.h"
34eda14cbcSMatt Macy #include "zed_log.h"
35eda14cbcSMatt Macy #include "zed_strings.h"
36eda14cbcSMatt Macy 
37eda14cbcSMatt Macy #include "agents/zfs_agents.h"
38*14c2e0a0SMartin Matuska #include <libzutil.h>
39eda14cbcSMatt Macy 
40eda14cbcSMatt Macy #define	MAXBUF	4096
41eda14cbcSMatt Macy 
4208aba0aeSMartin Matuska static int max_zevent_buf_len = 1 << 20;
4308aba0aeSMartin Matuska 
44eda14cbcSMatt Macy /*
45eda14cbcSMatt Macy  * Open the libzfs interface.
46eda14cbcSMatt Macy  */
47eda14cbcSMatt Macy int
zed_event_init(struct zed_conf * zcp)48eda14cbcSMatt Macy zed_event_init(struct zed_conf *zcp)
49eda14cbcSMatt Macy {
50eda14cbcSMatt Macy 	if (!zcp)
51eda14cbcSMatt Macy 		zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
52eda14cbcSMatt Macy 
53eda14cbcSMatt Macy 	zcp->zfs_hdl = libzfs_init();
54eda14cbcSMatt Macy 	if (!zcp->zfs_hdl) {
55eda14cbcSMatt Macy 		if (zcp->do_idle)
56eda14cbcSMatt Macy 			return (-1);
57eda14cbcSMatt Macy 		zed_log_die("Failed to initialize libzfs");
58eda14cbcSMatt Macy 	}
59eda14cbcSMatt Macy 
6016038816SMartin Matuska 	zcp->zevent_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC);
61eda14cbcSMatt Macy 	if (zcp->zevent_fd < 0) {
62eda14cbcSMatt Macy 		if (zcp->do_idle)
63eda14cbcSMatt Macy 			return (-1);
64eda14cbcSMatt Macy 		zed_log_die("Failed to open \"%s\": %s",
65eda14cbcSMatt Macy 		    ZFS_DEV, strerror(errno));
66eda14cbcSMatt Macy 	}
67eda14cbcSMatt Macy 
68eda14cbcSMatt Macy 	zfs_agent_init(zcp->zfs_hdl);
69eda14cbcSMatt Macy 
70eda14cbcSMatt Macy 	if (zed_disk_event_init() != 0) {
71eda14cbcSMatt Macy 		if (zcp->do_idle)
72eda14cbcSMatt Macy 			return (-1);
73eda14cbcSMatt Macy 		zed_log_die("Failed to initialize disk events");
74eda14cbcSMatt Macy 	}
75eda14cbcSMatt Macy 
7608aba0aeSMartin Matuska 	if (zcp->max_zevent_buf_len != 0)
7708aba0aeSMartin Matuska 		max_zevent_buf_len = zcp->max_zevent_buf_len;
7808aba0aeSMartin Matuska 
79eda14cbcSMatt Macy 	return (0);
80eda14cbcSMatt Macy }
81eda14cbcSMatt Macy 
82eda14cbcSMatt Macy /*
83eda14cbcSMatt Macy  * Close the libzfs interface.
84eda14cbcSMatt Macy  */
85eda14cbcSMatt Macy void
zed_event_fini(struct zed_conf * zcp)86eda14cbcSMatt Macy zed_event_fini(struct zed_conf *zcp)
87eda14cbcSMatt Macy {
88eda14cbcSMatt Macy 	if (!zcp)
89eda14cbcSMatt Macy 		zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL));
90eda14cbcSMatt Macy 
91eda14cbcSMatt Macy 	zed_disk_event_fini();
92eda14cbcSMatt Macy 	zfs_agent_fini();
93eda14cbcSMatt Macy 
94eda14cbcSMatt Macy 	if (zcp->zevent_fd >= 0) {
95eda14cbcSMatt Macy 		if (close(zcp->zevent_fd) < 0)
96eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s",
97eda14cbcSMatt Macy 			    ZFS_DEV, strerror(errno));
98eda14cbcSMatt Macy 
99eda14cbcSMatt Macy 		zcp->zevent_fd = -1;
100eda14cbcSMatt Macy 	}
101eda14cbcSMatt Macy 	if (zcp->zfs_hdl) {
102eda14cbcSMatt Macy 		libzfs_fini(zcp->zfs_hdl);
103eda14cbcSMatt Macy 		zcp->zfs_hdl = NULL;
104eda14cbcSMatt Macy 	}
10516038816SMartin Matuska 
10616038816SMartin Matuska 	zed_exec_fini();
10716038816SMartin Matuska }
10816038816SMartin Matuska 
10916038816SMartin Matuska static void
_bump_event_queue_length(void)11016038816SMartin Matuska _bump_event_queue_length(void)
11116038816SMartin Matuska {
11216038816SMartin Matuska 	int zzlm = -1, wr;
11316038816SMartin Matuska 	char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
11408aba0aeSMartin Matuska 	long int qlen, orig_qlen;
11516038816SMartin Matuska 
11616038816SMartin Matuska 	zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
11716038816SMartin Matuska 	if (zzlm < 0)
11816038816SMartin Matuska 		goto done;
11916038816SMartin Matuska 
12016038816SMartin Matuska 	if (read(zzlm, qlen_buf, sizeof (qlen_buf)) < 0)
12116038816SMartin Matuska 		goto done;
12216038816SMartin Matuska 	qlen_buf[sizeof (qlen_buf) - 1] = '\0';
12316038816SMartin Matuska 
12416038816SMartin Matuska 	errno = 0;
12508aba0aeSMartin Matuska 	orig_qlen = qlen = strtol(qlen_buf, NULL, 10);
12616038816SMartin Matuska 	if (errno == ERANGE)
12716038816SMartin Matuska 		goto done;
12816038816SMartin Matuska 
12916038816SMartin Matuska 	if (qlen <= 0)
13016038816SMartin Matuska 		qlen = 512; /* default zfs_zevent_len_max value */
13116038816SMartin Matuska 	else
13216038816SMartin Matuska 		qlen *= 2;
13316038816SMartin Matuska 
13408aba0aeSMartin Matuska 	/*
13508aba0aeSMartin Matuska 	 * Don't consume all of kernel memory with event logs if something
13608aba0aeSMartin Matuska 	 * goes wrong.
13708aba0aeSMartin Matuska 	 */
13808aba0aeSMartin Matuska 	if (qlen > max_zevent_buf_len)
13908aba0aeSMartin Matuska 		qlen = max_zevent_buf_len;
14008aba0aeSMartin Matuska 	if (qlen == orig_qlen)
14108aba0aeSMartin Matuska 		goto done;
14216038816SMartin Matuska 	wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
143dbd5678dSMartin Matuska 	if (wr >= sizeof (qlen_buf)) {
144dbd5678dSMartin Matuska 		wr = sizeof (qlen_buf) - 1;
145dbd5678dSMartin Matuska 		zed_log_msg(LOG_WARNING, "Truncation in %s()", __func__);
146dbd5678dSMartin Matuska 	}
14716038816SMartin Matuska 
148dbd5678dSMartin Matuska 	if (pwrite(zzlm, qlen_buf, wr + 1, 0) < 0)
14916038816SMartin Matuska 		goto done;
15016038816SMartin Matuska 
15116038816SMartin Matuska 	zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
15216038816SMartin Matuska 
15316038816SMartin Matuska done:
15416038816SMartin Matuska 	if (zzlm > -1)
15516038816SMartin Matuska 		(void) close(zzlm);
156eda14cbcSMatt Macy }
157eda14cbcSMatt Macy 
158eda14cbcSMatt Macy /*
159eda14cbcSMatt Macy  * Seek to the event specified by [saved_eid] and [saved_etime].
160eda14cbcSMatt Macy  * This protects against processing a given event more than once.
161eda14cbcSMatt Macy  * Return 0 upon a successful seek to the specified event, or -1 otherwise.
162eda14cbcSMatt Macy  *
163eda14cbcSMatt Macy  * A zevent is considered to be uniquely specified by its (eid,time) tuple.
164eda14cbcSMatt Macy  * The unsigned 64b eid is set to 1 when the kernel module is loaded, and
165eda14cbcSMatt Macy  * incremented by 1 for each new event.  Since the state file can persist
166eda14cbcSMatt Macy  * across a kernel module reload, the time must be checked to ensure a match.
167eda14cbcSMatt Macy  */
168eda14cbcSMatt Macy int
zed_event_seek(struct zed_conf * zcp,uint64_t saved_eid,int64_t saved_etime[])169eda14cbcSMatt Macy zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[])
170eda14cbcSMatt Macy {
171eda14cbcSMatt Macy 	uint64_t eid;
172eda14cbcSMatt Macy 	int found;
173eda14cbcSMatt Macy 	nvlist_t *nvl;
174eda14cbcSMatt Macy 	int n_dropped;
175eda14cbcSMatt Macy 	int64_t *etime;
176eda14cbcSMatt Macy 	uint_t nelem;
177eda14cbcSMatt Macy 	int rv;
178eda14cbcSMatt Macy 
179eda14cbcSMatt Macy 	if (!zcp) {
180eda14cbcSMatt Macy 		errno = EINVAL;
181eda14cbcSMatt Macy 		zed_log_msg(LOG_ERR, "Failed to seek zevent: %s",
182eda14cbcSMatt Macy 		    strerror(errno));
183eda14cbcSMatt Macy 		return (-1);
184eda14cbcSMatt Macy 	}
185eda14cbcSMatt Macy 	eid = 0;
186eda14cbcSMatt Macy 	found = 0;
187eda14cbcSMatt Macy 	while ((eid < saved_eid) && !found) {
188eda14cbcSMatt Macy 		rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped,
189eda14cbcSMatt Macy 		    ZEVENT_NONBLOCK, zcp->zevent_fd);
190eda14cbcSMatt Macy 
191eda14cbcSMatt Macy 		if ((rv != 0) || !nvl)
192eda14cbcSMatt Macy 			break;
193eda14cbcSMatt Macy 
194eda14cbcSMatt Macy 		if (n_dropped > 0) {
195eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
19616038816SMartin Matuska 			_bump_event_queue_length();
197eda14cbcSMatt Macy 		}
198eda14cbcSMatt Macy 		if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
199eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
200eda14cbcSMatt Macy 		} else if (nvlist_lookup_int64_array(nvl, "time",
201eda14cbcSMatt Macy 		    &etime, &nelem) != 0) {
202eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING,
203eda14cbcSMatt Macy 			    "Failed to lookup zevent time (eid=%llu)", eid);
204eda14cbcSMatt Macy 		} else if (nelem != 2) {
205eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING,
206eda14cbcSMatt Macy 			    "Failed to lookup zevent time (eid=%llu, nelem=%u)",
207eda14cbcSMatt Macy 			    eid, nelem);
208eda14cbcSMatt Macy 		} else if ((eid != saved_eid) ||
209eda14cbcSMatt Macy 		    (etime[0] != saved_etime[0]) ||
210eda14cbcSMatt Macy 		    (etime[1] != saved_etime[1])) {
211eda14cbcSMatt Macy 			/* no-op */
212eda14cbcSMatt Macy 		} else {
213eda14cbcSMatt Macy 			found = 1;
214eda14cbcSMatt Macy 		}
215eda14cbcSMatt Macy 		free(nvl);
216eda14cbcSMatt Macy 	}
217eda14cbcSMatt Macy 	if (!found && (saved_eid > 0)) {
218eda14cbcSMatt Macy 		if (zpool_events_seek(zcp->zfs_hdl, ZEVENT_SEEK_START,
219eda14cbcSMatt Macy 		    zcp->zevent_fd) < 0)
220eda14cbcSMatt Macy 			zed_log_msg(LOG_WARNING, "Failed to seek to eid=0");
221eda14cbcSMatt Macy 		else
222eda14cbcSMatt Macy 			eid = 0;
223eda14cbcSMatt Macy 	}
224eda14cbcSMatt Macy 	zed_log_msg(LOG_NOTICE, "Processing events since eid=%llu", eid);
225eda14cbcSMatt Macy 	return (found ? 0 : -1);
226eda14cbcSMatt Macy }
227eda14cbcSMatt Macy 
228eda14cbcSMatt Macy /*
229eda14cbcSMatt Macy  * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0.
230eda14cbcSMatt Macy  */
231eda14cbcSMatt Macy static int
_zed_event_value_is_hex(const char * name)232eda14cbcSMatt Macy _zed_event_value_is_hex(const char *name)
233eda14cbcSMatt Macy {
234eda14cbcSMatt Macy 	const char *hex_suffix[] = {
235eda14cbcSMatt Macy 		"_guid",
236eda14cbcSMatt Macy 		"_guids",
237eda14cbcSMatt Macy 		NULL
238eda14cbcSMatt Macy 	};
239eda14cbcSMatt Macy 	const char **pp;
240eda14cbcSMatt Macy 	char *p;
241eda14cbcSMatt Macy 
242eda14cbcSMatt Macy 	if (!name)
243eda14cbcSMatt Macy 		return (0);
244eda14cbcSMatt Macy 
245eda14cbcSMatt Macy 	for (pp = hex_suffix; *pp; pp++) {
246eda14cbcSMatt Macy 		p = strstr(name, *pp);
247eda14cbcSMatt Macy 		if (p && strlen(p) == strlen(*pp))
248eda14cbcSMatt Macy 			return (1);
249eda14cbcSMatt Macy 	}
250eda14cbcSMatt Macy 	return (0);
251eda14cbcSMatt Macy }
252eda14cbcSMatt Macy 
253eda14cbcSMatt Macy /*
254eda14cbcSMatt Macy  * Add an environment variable for [eid] to the container [zsp].
255eda14cbcSMatt Macy  *
256eda14cbcSMatt Macy  * The variable name is the concatenation of [prefix] and [name] converted to
257eda14cbcSMatt Macy  * uppercase with non-alphanumeric characters converted to underscores;
258eda14cbcSMatt Macy  * [prefix] is optional, and [name] must begin with an alphabetic character.
259eda14cbcSMatt Macy  * If the converted variable name already exists within the container [zsp],
260eda14cbcSMatt Macy  * its existing value will be replaced with the new value.
261eda14cbcSMatt Macy  *
262eda14cbcSMatt Macy  * The variable value is specified by the format string [fmt].
263eda14cbcSMatt Macy  *
264eda14cbcSMatt Macy  * Returns 0 on success, and -1 on error (with errno set).
265eda14cbcSMatt Macy  *
266eda14cbcSMatt Macy  * All environment variables in [zsp] should be added through this function.
267eda14cbcSMatt Macy  */
26816038816SMartin Matuska static __attribute__((format(printf, 5, 6))) int
_zed_event_add_var(uint64_t eid,zed_strings_t * zsp,const char * prefix,const char * name,const char * fmt,...)269eda14cbcSMatt Macy _zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
270eda14cbcSMatt Macy     const char *prefix, const char *name, const char *fmt, ...)
271eda14cbcSMatt Macy {
272eda14cbcSMatt Macy 	char keybuf[MAXBUF];
273eda14cbcSMatt Macy 	char valbuf[MAXBUF];
274eda14cbcSMatt Macy 	char *dstp;
275eda14cbcSMatt Macy 	const char *srcp;
276eda14cbcSMatt Macy 	const char *lastp;
277eda14cbcSMatt Macy 	int n;
278eda14cbcSMatt Macy 	int buflen;
279eda14cbcSMatt Macy 	va_list vargs;
280eda14cbcSMatt Macy 
281eda14cbcSMatt Macy 	assert(zsp != NULL);
282eda14cbcSMatt Macy 	assert(fmt != NULL);
283eda14cbcSMatt Macy 
284eda14cbcSMatt Macy 	if (!name) {
285eda14cbcSMatt Macy 		errno = EINVAL;
286eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
287eda14cbcSMatt Macy 		    "Failed to add variable for eid=%llu: Name is empty", eid);
288eda14cbcSMatt Macy 		return (-1);
289eda14cbcSMatt Macy 	} else if (!isalpha(name[0])) {
290eda14cbcSMatt Macy 		errno = EINVAL;
291eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
292eda14cbcSMatt Macy 		    "Failed to add variable for eid=%llu: "
293eda14cbcSMatt Macy 		    "Name \"%s\" is invalid", eid, name);
294eda14cbcSMatt Macy 		return (-1);
295eda14cbcSMatt Macy 	}
296eda14cbcSMatt Macy 	/*
297eda14cbcSMatt Macy 	 * Construct the string key by converting PREFIX (if present) and NAME.
298eda14cbcSMatt Macy 	 */
299eda14cbcSMatt Macy 	dstp = keybuf;
300eda14cbcSMatt Macy 	lastp = keybuf + sizeof (keybuf);
301eda14cbcSMatt Macy 	if (prefix) {
302eda14cbcSMatt Macy 		for (srcp = prefix; *srcp && (dstp < lastp); srcp++)
303eda14cbcSMatt Macy 			*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
304eda14cbcSMatt Macy 	}
305eda14cbcSMatt Macy 	for (srcp = name; *srcp && (dstp < lastp); srcp++)
306eda14cbcSMatt Macy 		*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
307eda14cbcSMatt Macy 
308eda14cbcSMatt Macy 	if (dstp == lastp) {
309eda14cbcSMatt Macy 		errno = ENAMETOOLONG;
310eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
311eda14cbcSMatt Macy 		    "Failed to add variable for eid=%llu: Name too long", eid);
312eda14cbcSMatt Macy 		return (-1);
313eda14cbcSMatt Macy 	}
314eda14cbcSMatt Macy 	*dstp = '\0';
315eda14cbcSMatt Macy 	/*
316eda14cbcSMatt Macy 	 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
317eda14cbcSMatt Macy 	 */
318eda14cbcSMatt Macy 	dstp = valbuf;
319eda14cbcSMatt Macy 	buflen = sizeof (valbuf);
320eda14cbcSMatt Macy 	n = strlcpy(dstp, keybuf, buflen);
321eda14cbcSMatt Macy 	if (n >= sizeof (valbuf)) {
322eda14cbcSMatt Macy 		errno = EMSGSIZE;
323eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
324eda14cbcSMatt Macy 		    keybuf, eid, "Exceeded buffer size");
325eda14cbcSMatt Macy 		return (-1);
326eda14cbcSMatt Macy 	}
327eda14cbcSMatt Macy 	dstp += n;
328eda14cbcSMatt Macy 	buflen -= n;
329eda14cbcSMatt Macy 
330eda14cbcSMatt Macy 	*dstp++ = '=';
331eda14cbcSMatt Macy 	buflen--;
332eda14cbcSMatt Macy 
333eda14cbcSMatt Macy 	if (buflen <= 0) {
334eda14cbcSMatt Macy 		errno = EMSGSIZE;
335eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
336eda14cbcSMatt Macy 		    keybuf, eid, "Exceeded buffer size");
337eda14cbcSMatt Macy 		return (-1);
338eda14cbcSMatt Macy 	}
339eda14cbcSMatt Macy 
340eda14cbcSMatt Macy 	va_start(vargs, fmt);
341eda14cbcSMatt Macy 	n = vsnprintf(dstp, buflen, fmt, vargs);
342eda14cbcSMatt Macy 	va_end(vargs);
343eda14cbcSMatt Macy 
344eda14cbcSMatt Macy 	if ((n < 0) || (n >= buflen)) {
345eda14cbcSMatt Macy 		errno = EMSGSIZE;
346eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
347eda14cbcSMatt Macy 		    keybuf, eid, "Exceeded buffer size");
348eda14cbcSMatt Macy 		return (-1);
349eda14cbcSMatt Macy 	} else if (zed_strings_add(zsp, keybuf, valbuf) < 0) {
350eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
351eda14cbcSMatt Macy 		    keybuf, eid, strerror(errno));
352eda14cbcSMatt Macy 		return (-1);
353eda14cbcSMatt Macy 	}
354eda14cbcSMatt Macy 	return (0);
355eda14cbcSMatt Macy }
356eda14cbcSMatt Macy 
357eda14cbcSMatt Macy static int
_zed_event_add_array_err(uint64_t eid,const char * name)358eda14cbcSMatt Macy _zed_event_add_array_err(uint64_t eid, const char *name)
359eda14cbcSMatt Macy {
360eda14cbcSMatt Macy 	errno = EMSGSIZE;
361eda14cbcSMatt Macy 	zed_log_msg(LOG_WARNING,
362eda14cbcSMatt Macy 	    "Failed to convert nvpair \"%s\" for eid=%llu: "
363eda14cbcSMatt Macy 	    "Exceeded buffer size", name, eid);
364eda14cbcSMatt Macy 	return (-1);
365eda14cbcSMatt Macy }
366eda14cbcSMatt Macy 
367eda14cbcSMatt Macy static int
_zed_event_add_int8_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)368eda14cbcSMatt Macy _zed_event_add_int8_array(uint64_t eid, zed_strings_t *zsp,
369eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
370eda14cbcSMatt Macy {
371eda14cbcSMatt Macy 	char buf[MAXBUF];
372eda14cbcSMatt Macy 	int buflen = sizeof (buf);
373eda14cbcSMatt Macy 	const char *name;
374eda14cbcSMatt Macy 	int8_t *i8p;
375eda14cbcSMatt Macy 	uint_t nelem;
376eda14cbcSMatt Macy 	uint_t i;
377eda14cbcSMatt Macy 	char *p;
378eda14cbcSMatt Macy 	int n;
379eda14cbcSMatt Macy 
380eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT8_ARRAY));
381eda14cbcSMatt Macy 
382eda14cbcSMatt Macy 	name = nvpair_name(nvp);
383eda14cbcSMatt Macy 	(void) nvpair_value_int8_array(nvp, &i8p, &nelem);
384eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
385eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%d ", i8p[i]);
386eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
387eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
388eda14cbcSMatt Macy 		p += n;
389eda14cbcSMatt Macy 		buflen -= n;
390eda14cbcSMatt Macy 	}
391eda14cbcSMatt Macy 	if (nelem > 0)
392eda14cbcSMatt Macy 		*--p = '\0';
393eda14cbcSMatt Macy 
394eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
395eda14cbcSMatt Macy }
396eda14cbcSMatt Macy 
397eda14cbcSMatt Macy static int
_zed_event_add_uint8_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)398eda14cbcSMatt Macy _zed_event_add_uint8_array(uint64_t eid, zed_strings_t *zsp,
399eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
400eda14cbcSMatt Macy {
401eda14cbcSMatt Macy 	char buf[MAXBUF];
402eda14cbcSMatt Macy 	int buflen = sizeof (buf);
403eda14cbcSMatt Macy 	const char *name;
404eda14cbcSMatt Macy 	uint8_t *u8p;
405eda14cbcSMatt Macy 	uint_t nelem;
406eda14cbcSMatt Macy 	uint_t i;
407eda14cbcSMatt Macy 	char *p;
408eda14cbcSMatt Macy 	int n;
409eda14cbcSMatt Macy 
410eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT8_ARRAY));
411eda14cbcSMatt Macy 
412eda14cbcSMatt Macy 	name = nvpair_name(nvp);
413eda14cbcSMatt Macy 	(void) nvpair_value_uint8_array(nvp, &u8p, &nelem);
414eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
415eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%u ", u8p[i]);
416eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
417eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
418eda14cbcSMatt Macy 		p += n;
419eda14cbcSMatt Macy 		buflen -= n;
420eda14cbcSMatt Macy 	}
421eda14cbcSMatt Macy 	if (nelem > 0)
422eda14cbcSMatt Macy 		*--p = '\0';
423eda14cbcSMatt Macy 
424eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
425eda14cbcSMatt Macy }
426eda14cbcSMatt Macy 
427eda14cbcSMatt Macy static int
_zed_event_add_int16_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)428eda14cbcSMatt Macy _zed_event_add_int16_array(uint64_t eid, zed_strings_t *zsp,
429eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
430eda14cbcSMatt Macy {
431eda14cbcSMatt Macy 	char buf[MAXBUF];
432eda14cbcSMatt Macy 	int buflen = sizeof (buf);
433eda14cbcSMatt Macy 	const char *name;
434eda14cbcSMatt Macy 	int16_t *i16p;
435eda14cbcSMatt Macy 	uint_t nelem;
436eda14cbcSMatt Macy 	uint_t i;
437eda14cbcSMatt Macy 	char *p;
438eda14cbcSMatt Macy 	int n;
439eda14cbcSMatt Macy 
440eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT16_ARRAY));
441eda14cbcSMatt Macy 
442eda14cbcSMatt Macy 	name = nvpair_name(nvp);
443eda14cbcSMatt Macy 	(void) nvpair_value_int16_array(nvp, &i16p, &nelem);
444eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
445eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%d ", i16p[i]);
446eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
447eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
448eda14cbcSMatt Macy 		p += n;
449eda14cbcSMatt Macy 		buflen -= n;
450eda14cbcSMatt Macy 	}
451eda14cbcSMatt Macy 	if (nelem > 0)
452eda14cbcSMatt Macy 		*--p = '\0';
453eda14cbcSMatt Macy 
454eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
455eda14cbcSMatt Macy }
456eda14cbcSMatt Macy 
457eda14cbcSMatt Macy static int
_zed_event_add_uint16_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)458eda14cbcSMatt Macy _zed_event_add_uint16_array(uint64_t eid, zed_strings_t *zsp,
459eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
460eda14cbcSMatt Macy {
461eda14cbcSMatt Macy 	char buf[MAXBUF];
462eda14cbcSMatt Macy 	int buflen = sizeof (buf);
463eda14cbcSMatt Macy 	const char *name;
464eda14cbcSMatt Macy 	uint16_t *u16p;
465eda14cbcSMatt Macy 	uint_t nelem;
466eda14cbcSMatt Macy 	uint_t i;
467eda14cbcSMatt Macy 	char *p;
468eda14cbcSMatt Macy 	int n;
469eda14cbcSMatt Macy 
470eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY));
471eda14cbcSMatt Macy 
472eda14cbcSMatt Macy 	name = nvpair_name(nvp);
473eda14cbcSMatt Macy 	(void) nvpair_value_uint16_array(nvp, &u16p, &nelem);
474eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
475eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%u ", u16p[i]);
476eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
477eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
478eda14cbcSMatt Macy 		p += n;
479eda14cbcSMatt Macy 		buflen -= n;
480eda14cbcSMatt Macy 	}
481eda14cbcSMatt Macy 	if (nelem > 0)
482eda14cbcSMatt Macy 		*--p = '\0';
483eda14cbcSMatt Macy 
484eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
485eda14cbcSMatt Macy }
486eda14cbcSMatt Macy 
487eda14cbcSMatt Macy static int
_zed_event_add_int32_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)488eda14cbcSMatt Macy _zed_event_add_int32_array(uint64_t eid, zed_strings_t *zsp,
489eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
490eda14cbcSMatt Macy {
491eda14cbcSMatt Macy 	char buf[MAXBUF];
492eda14cbcSMatt Macy 	int buflen = sizeof (buf);
493eda14cbcSMatt Macy 	const char *name;
494eda14cbcSMatt Macy 	int32_t *i32p;
495eda14cbcSMatt Macy 	uint_t nelem;
496eda14cbcSMatt Macy 	uint_t i;
497eda14cbcSMatt Macy 	char *p;
498eda14cbcSMatt Macy 	int n;
499eda14cbcSMatt Macy 
500eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT32_ARRAY));
501eda14cbcSMatt Macy 
502eda14cbcSMatt Macy 	name = nvpair_name(nvp);
503eda14cbcSMatt Macy 	(void) nvpair_value_int32_array(nvp, &i32p, &nelem);
504eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
505eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%d ", i32p[i]);
506eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
507eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
508eda14cbcSMatt Macy 		p += n;
509eda14cbcSMatt Macy 		buflen -= n;
510eda14cbcSMatt Macy 	}
511eda14cbcSMatt Macy 	if (nelem > 0)
512eda14cbcSMatt Macy 		*--p = '\0';
513eda14cbcSMatt Macy 
514eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
515eda14cbcSMatt Macy }
516eda14cbcSMatt Macy 
517eda14cbcSMatt Macy static int
_zed_event_add_uint32_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)518eda14cbcSMatt Macy _zed_event_add_uint32_array(uint64_t eid, zed_strings_t *zsp,
519eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
520eda14cbcSMatt Macy {
521eda14cbcSMatt Macy 	char buf[MAXBUF];
522eda14cbcSMatt Macy 	int buflen = sizeof (buf);
523eda14cbcSMatt Macy 	const char *name;
524eda14cbcSMatt Macy 	uint32_t *u32p;
525eda14cbcSMatt Macy 	uint_t nelem;
526eda14cbcSMatt Macy 	uint_t i;
527eda14cbcSMatt Macy 	char *p;
528eda14cbcSMatt Macy 	int n;
529eda14cbcSMatt Macy 
530eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT32_ARRAY));
531eda14cbcSMatt Macy 
532eda14cbcSMatt Macy 	name = nvpair_name(nvp);
533eda14cbcSMatt Macy 	(void) nvpair_value_uint32_array(nvp, &u32p, &nelem);
534eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
535eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%u ", u32p[i]);
536eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
537eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
538eda14cbcSMatt Macy 		p += n;
539eda14cbcSMatt Macy 		buflen -= n;
540eda14cbcSMatt Macy 	}
541eda14cbcSMatt Macy 	if (nelem > 0)
542eda14cbcSMatt Macy 		*--p = '\0';
543eda14cbcSMatt Macy 
544eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
545eda14cbcSMatt Macy }
546eda14cbcSMatt Macy 
547eda14cbcSMatt Macy static int
_zed_event_add_int64_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)548eda14cbcSMatt Macy _zed_event_add_int64_array(uint64_t eid, zed_strings_t *zsp,
549eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
550eda14cbcSMatt Macy {
551eda14cbcSMatt Macy 	char buf[MAXBUF];
552eda14cbcSMatt Macy 	int buflen = sizeof (buf);
553eda14cbcSMatt Macy 	const char *name;
554eda14cbcSMatt Macy 	int64_t *i64p;
555eda14cbcSMatt Macy 	uint_t nelem;
556eda14cbcSMatt Macy 	uint_t i;
557eda14cbcSMatt Macy 	char *p;
558eda14cbcSMatt Macy 	int n;
559eda14cbcSMatt Macy 
560eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT64_ARRAY));
561eda14cbcSMatt Macy 
562eda14cbcSMatt Macy 	name = nvpair_name(nvp);
563eda14cbcSMatt Macy 	(void) nvpair_value_int64_array(nvp, &i64p, &nelem);
564eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
565eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%lld ", (u_longlong_t)i64p[i]);
566eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
567eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
568eda14cbcSMatt Macy 		p += n;
569eda14cbcSMatt Macy 		buflen -= n;
570eda14cbcSMatt Macy 	}
571eda14cbcSMatt Macy 	if (nelem > 0)
572eda14cbcSMatt Macy 		*--p = '\0';
573eda14cbcSMatt Macy 
574eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
575eda14cbcSMatt Macy }
576eda14cbcSMatt Macy 
577eda14cbcSMatt Macy static int
_zed_event_add_uint64_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)578eda14cbcSMatt Macy _zed_event_add_uint64_array(uint64_t eid, zed_strings_t *zsp,
579eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
580eda14cbcSMatt Macy {
581eda14cbcSMatt Macy 	char buf[MAXBUF];
582eda14cbcSMatt Macy 	int buflen = sizeof (buf);
583eda14cbcSMatt Macy 	const char *name;
584eda14cbcSMatt Macy 	const char *fmt;
585eda14cbcSMatt Macy 	uint64_t *u64p;
586eda14cbcSMatt Macy 	uint_t nelem;
587eda14cbcSMatt Macy 	uint_t i;
588eda14cbcSMatt Macy 	char *p;
589eda14cbcSMatt Macy 	int n;
590eda14cbcSMatt Macy 
591eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY));
592eda14cbcSMatt Macy 
593eda14cbcSMatt Macy 	name = nvpair_name(nvp);
594eda14cbcSMatt Macy 	fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu ";
595eda14cbcSMatt Macy 	(void) nvpair_value_uint64_array(nvp, &u64p, &nelem);
596eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
597eda14cbcSMatt Macy 		n = snprintf(p, buflen, fmt, (u_longlong_t)u64p[i]);
598eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
599eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
600eda14cbcSMatt Macy 		p += n;
601eda14cbcSMatt Macy 		buflen -= n;
602eda14cbcSMatt Macy 	}
603eda14cbcSMatt Macy 	if (nelem > 0)
604eda14cbcSMatt Macy 		*--p = '\0';
605eda14cbcSMatt Macy 
606eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
607eda14cbcSMatt Macy }
608eda14cbcSMatt Macy 
609eda14cbcSMatt Macy static int
_zed_event_add_string_array(uint64_t eid,zed_strings_t * zsp,const char * prefix,nvpair_t * nvp)610eda14cbcSMatt Macy _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
611eda14cbcSMatt Macy     const char *prefix, nvpair_t *nvp)
612eda14cbcSMatt Macy {
613eda14cbcSMatt Macy 	char buf[MAXBUF];
614eda14cbcSMatt Macy 	int buflen = sizeof (buf);
615eda14cbcSMatt Macy 	const char *name;
6162a58b312SMartin Matuska 	const char **strp;
617eda14cbcSMatt Macy 	uint_t nelem;
618eda14cbcSMatt Macy 	uint_t i;
619eda14cbcSMatt Macy 	char *p;
620eda14cbcSMatt Macy 	int n;
621eda14cbcSMatt Macy 
622eda14cbcSMatt Macy 	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY));
623eda14cbcSMatt Macy 
624eda14cbcSMatt Macy 	name = nvpair_name(nvp);
625eda14cbcSMatt Macy 	(void) nvpair_value_string_array(nvp, &strp, &nelem);
626eda14cbcSMatt Macy 	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
627eda14cbcSMatt Macy 		n = snprintf(p, buflen, "%s ", strp[i] ? strp[i] : "<NULL>");
628eda14cbcSMatt Macy 		if ((n < 0) || (n >= buflen))
629eda14cbcSMatt Macy 			return (_zed_event_add_array_err(eid, name));
630eda14cbcSMatt Macy 		p += n;
631eda14cbcSMatt Macy 		buflen -= n;
632eda14cbcSMatt Macy 	}
633eda14cbcSMatt Macy 	if (nelem > 0)
634eda14cbcSMatt Macy 		*--p = '\0';
635eda14cbcSMatt Macy 
636eda14cbcSMatt Macy 	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
637eda14cbcSMatt Macy }
638eda14cbcSMatt Macy 
639eda14cbcSMatt Macy /*
640eda14cbcSMatt Macy  * Convert the nvpair [nvp] to a string which is added to the environment
641eda14cbcSMatt Macy  * of the child process.
642eda14cbcSMatt Macy  * Return 0 on success, -1 on error.
643eda14cbcSMatt Macy  */
644eda14cbcSMatt Macy static void
_zed_event_add_nvpair(uint64_t eid,zed_strings_t * zsp,nvpair_t * nvp)645eda14cbcSMatt Macy _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
646eda14cbcSMatt Macy {
647eda14cbcSMatt Macy 	const char *name;
648eda14cbcSMatt Macy 	data_type_t type;
649eda14cbcSMatt Macy 	const char *prefix = ZEVENT_VAR_PREFIX;
650eda14cbcSMatt Macy 	boolean_t b;
651eda14cbcSMatt Macy 	double d;
652eda14cbcSMatt Macy 	uint8_t i8;
653eda14cbcSMatt Macy 	uint16_t i16;
654eda14cbcSMatt Macy 	uint32_t i32;
655eda14cbcSMatt Macy 	uint64_t i64;
6562a58b312SMartin Matuska 	const char *str;
657eda14cbcSMatt Macy 
658eda14cbcSMatt Macy 	assert(zsp != NULL);
659eda14cbcSMatt Macy 	assert(nvp != NULL);
660eda14cbcSMatt Macy 
661eda14cbcSMatt Macy 	name = nvpair_name(nvp);
662eda14cbcSMatt Macy 	type = nvpair_type(nvp);
663eda14cbcSMatt Macy 
664eda14cbcSMatt Macy 	switch (type) {
665eda14cbcSMatt Macy 	case DATA_TYPE_BOOLEAN:
666eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%s", "1");
667eda14cbcSMatt Macy 		break;
668eda14cbcSMatt Macy 	case DATA_TYPE_BOOLEAN_VALUE:
669eda14cbcSMatt Macy 		(void) nvpair_value_boolean_value(nvp, &b);
670eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0");
671eda14cbcSMatt Macy 		break;
672eda14cbcSMatt Macy 	case DATA_TYPE_BYTE:
673eda14cbcSMatt Macy 		(void) nvpair_value_byte(nvp, &i8);
674eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
675eda14cbcSMatt Macy 		break;
676eda14cbcSMatt Macy 	case DATA_TYPE_INT8:
677eda14cbcSMatt Macy 		(void) nvpair_value_int8(nvp, (int8_t *)&i8);
678eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
679eda14cbcSMatt Macy 		break;
680eda14cbcSMatt Macy 	case DATA_TYPE_UINT8:
681eda14cbcSMatt Macy 		(void) nvpair_value_uint8(nvp, &i8);
682eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%u", i8);
683eda14cbcSMatt Macy 		break;
684eda14cbcSMatt Macy 	case DATA_TYPE_INT16:
685eda14cbcSMatt Macy 		(void) nvpair_value_int16(nvp, (int16_t *)&i16);
686eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%d", i16);
687eda14cbcSMatt Macy 		break;
688eda14cbcSMatt Macy 	case DATA_TYPE_UINT16:
689eda14cbcSMatt Macy 		(void) nvpair_value_uint16(nvp, &i16);
690eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%u", i16);
691eda14cbcSMatt Macy 		break;
692eda14cbcSMatt Macy 	case DATA_TYPE_INT32:
693eda14cbcSMatt Macy 		(void) nvpair_value_int32(nvp, (int32_t *)&i32);
694eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%d", i32);
695eda14cbcSMatt Macy 		break;
696eda14cbcSMatt Macy 	case DATA_TYPE_UINT32:
697eda14cbcSMatt Macy 		(void) nvpair_value_uint32(nvp, &i32);
698eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%u", i32);
699eda14cbcSMatt Macy 		break;
700eda14cbcSMatt Macy 	case DATA_TYPE_INT64:
701eda14cbcSMatt Macy 		(void) nvpair_value_int64(nvp, (int64_t *)&i64);
702eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name,
703eda14cbcSMatt Macy 		    "%lld", (longlong_t)i64);
704eda14cbcSMatt Macy 		break;
705eda14cbcSMatt Macy 	case DATA_TYPE_UINT64:
706eda14cbcSMatt Macy 		(void) nvpair_value_uint64(nvp, &i64);
707eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name,
708eda14cbcSMatt Macy 		    (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"),
709eda14cbcSMatt Macy 		    (u_longlong_t)i64);
710eda14cbcSMatt Macy 		/*
711eda14cbcSMatt Macy 		 * shadow readable strings for vdev state pairs
712eda14cbcSMatt Macy 		 */
713eda14cbcSMatt Macy 		if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
714eda14cbcSMatt Macy 		    strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
715eda14cbcSMatt Macy 			char alt[32];
716eda14cbcSMatt Macy 
717eda14cbcSMatt Macy 			(void) snprintf(alt, sizeof (alt), "%s_str", name);
718eda14cbcSMatt Macy 			_zed_event_add_var(eid, zsp, prefix, alt, "%s",
719eda14cbcSMatt Macy 			    zpool_state_to_name(i64, VDEV_AUX_NONE));
720eda14cbcSMatt Macy 		} else
721eda14cbcSMatt Macy 		/*
722eda14cbcSMatt Macy 		 * shadow readable strings for pool state
723eda14cbcSMatt Macy 		 */
724eda14cbcSMatt Macy 		if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_POOL_STATE) == 0) {
725eda14cbcSMatt Macy 			char alt[32];
726eda14cbcSMatt Macy 
727eda14cbcSMatt Macy 			(void) snprintf(alt, sizeof (alt), "%s_str", name);
728eda14cbcSMatt Macy 			_zed_event_add_var(eid, zsp, prefix, alt, "%s",
729eda14cbcSMatt Macy 			    zpool_pool_state_to_name(i64));
730eda14cbcSMatt Macy 		}
731eda14cbcSMatt Macy 		break;
732eda14cbcSMatt Macy 	case DATA_TYPE_DOUBLE:
733eda14cbcSMatt Macy 		(void) nvpair_value_double(nvp, &d);
734eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name, "%g", d);
735eda14cbcSMatt Macy 		break;
736eda14cbcSMatt Macy 	case DATA_TYPE_HRTIME:
737eda14cbcSMatt Macy 		(void) nvpair_value_hrtime(nvp, (hrtime_t *)&i64);
738eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name,
739eda14cbcSMatt Macy 		    "%llu", (u_longlong_t)i64);
740eda14cbcSMatt Macy 		break;
741eda14cbcSMatt Macy 	case DATA_TYPE_STRING:
742eda14cbcSMatt Macy 		(void) nvpair_value_string(nvp, &str);
743eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, prefix, name,
744eda14cbcSMatt Macy 		    "%s", (str ? str : "<NULL>"));
745eda14cbcSMatt Macy 		break;
746eda14cbcSMatt Macy 	case DATA_TYPE_INT8_ARRAY:
747eda14cbcSMatt Macy 		_zed_event_add_int8_array(eid, zsp, prefix, nvp);
748eda14cbcSMatt Macy 		break;
749eda14cbcSMatt Macy 	case DATA_TYPE_UINT8_ARRAY:
750eda14cbcSMatt Macy 		_zed_event_add_uint8_array(eid, zsp, prefix, nvp);
751eda14cbcSMatt Macy 		break;
752eda14cbcSMatt Macy 	case DATA_TYPE_INT16_ARRAY:
753eda14cbcSMatt Macy 		_zed_event_add_int16_array(eid, zsp, prefix, nvp);
754eda14cbcSMatt Macy 		break;
755eda14cbcSMatt Macy 	case DATA_TYPE_UINT16_ARRAY:
756eda14cbcSMatt Macy 		_zed_event_add_uint16_array(eid, zsp, prefix, nvp);
757eda14cbcSMatt Macy 		break;
758eda14cbcSMatt Macy 	case DATA_TYPE_INT32_ARRAY:
759eda14cbcSMatt Macy 		_zed_event_add_int32_array(eid, zsp, prefix, nvp);
760eda14cbcSMatt Macy 		break;
761eda14cbcSMatt Macy 	case DATA_TYPE_UINT32_ARRAY:
762eda14cbcSMatt Macy 		_zed_event_add_uint32_array(eid, zsp, prefix, nvp);
763eda14cbcSMatt Macy 		break;
764eda14cbcSMatt Macy 	case DATA_TYPE_INT64_ARRAY:
765eda14cbcSMatt Macy 		_zed_event_add_int64_array(eid, zsp, prefix, nvp);
766eda14cbcSMatt Macy 		break;
767eda14cbcSMatt Macy 	case DATA_TYPE_UINT64_ARRAY:
768eda14cbcSMatt Macy 		_zed_event_add_uint64_array(eid, zsp, prefix, nvp);
769eda14cbcSMatt Macy 		break;
770eda14cbcSMatt Macy 	case DATA_TYPE_STRING_ARRAY:
771eda14cbcSMatt Macy 		_zed_event_add_string_array(eid, zsp, prefix, nvp);
772eda14cbcSMatt Macy 		break;
77316038816SMartin Matuska 	case DATA_TYPE_NVLIST:
77416038816SMartin Matuska 	case DATA_TYPE_BOOLEAN_ARRAY:
77516038816SMartin Matuska 	case DATA_TYPE_BYTE_ARRAY:
776eda14cbcSMatt Macy 	case DATA_TYPE_NVLIST_ARRAY:
77716038816SMartin Matuska 		_zed_event_add_var(eid, zsp, prefix, name, "_NOT_IMPLEMENTED_");
778eda14cbcSMatt Macy 		break;
779eda14cbcSMatt Macy 	default:
780eda14cbcSMatt Macy 		errno = EINVAL;
781eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
782eda14cbcSMatt Macy 		    "Failed to convert nvpair \"%s\" for eid=%llu: "
783eda14cbcSMatt Macy 		    "Unrecognized type=%u", name, eid, (unsigned int) type);
784eda14cbcSMatt Macy 		break;
785eda14cbcSMatt Macy 	}
786eda14cbcSMatt Macy }
787eda14cbcSMatt Macy 
788eda14cbcSMatt Macy /*
789eda14cbcSMatt Macy  * Restrict various environment variables to safe and sane values
790eda14cbcSMatt Macy  * when constructing the environment for the child process, unless
791eda14cbcSMatt Macy  * we're running with a custom $PATH (like under the ZFS test suite).
792eda14cbcSMatt Macy  *
793eda14cbcSMatt Macy  * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
794eda14cbcSMatt Macy  */
795eda14cbcSMatt Macy static void
_zed_event_add_env_restrict(uint64_t eid,zed_strings_t * zsp,const char * path)796eda14cbcSMatt Macy _zed_event_add_env_restrict(uint64_t eid, zed_strings_t *zsp,
797eda14cbcSMatt Macy     const char *path)
798eda14cbcSMatt Macy {
799eda14cbcSMatt Macy 	const char *env_restrict[][2] = {
800eda14cbcSMatt Macy 		{ "IFS",		" \t\n" },
801eda14cbcSMatt Macy 		{ "PATH",		_PATH_STDPATH },
802eda14cbcSMatt Macy 		{ "ZDB",		SBINDIR "/zdb" },
803eda14cbcSMatt Macy 		{ "ZED",		SBINDIR "/zed" },
804eda14cbcSMatt Macy 		{ "ZFS",		SBINDIR "/zfs" },
805eda14cbcSMatt Macy 		{ "ZINJECT",		SBINDIR "/zinject" },
806eda14cbcSMatt Macy 		{ "ZPOOL",		SBINDIR "/zpool" },
807eda14cbcSMatt Macy 		{ "ZFS_ALIAS",		ZFS_META_ALIAS },
808eda14cbcSMatt Macy 		{ "ZFS_VERSION",	ZFS_META_VERSION },
809eda14cbcSMatt Macy 		{ "ZFS_RELEASE",	ZFS_META_RELEASE },
810eda14cbcSMatt Macy 		{ NULL,			NULL }
811eda14cbcSMatt Macy 	};
812eda14cbcSMatt Macy 
813eda14cbcSMatt Macy 	/*
814eda14cbcSMatt Macy 	 * If we have a custom $PATH, use the default ZFS binary locations
815eda14cbcSMatt Macy 	 * instead of the hard-coded ones.
816eda14cbcSMatt Macy 	 */
817eda14cbcSMatt Macy 	const char *env_path[][2] = {
818eda14cbcSMatt Macy 		{ "IFS",		" \t\n" },
819eda14cbcSMatt Macy 		{ "PATH",		NULL }, /* $PATH copied in later on */
820eda14cbcSMatt Macy 		{ "ZDB",		"zdb" },
821eda14cbcSMatt Macy 		{ "ZED",		"zed" },
822eda14cbcSMatt Macy 		{ "ZFS",		"zfs" },
823eda14cbcSMatt Macy 		{ "ZINJECT",		"zinject" },
824eda14cbcSMatt Macy 		{ "ZPOOL",		"zpool" },
825eda14cbcSMatt Macy 		{ "ZFS_ALIAS",		ZFS_META_ALIAS },
826eda14cbcSMatt Macy 		{ "ZFS_VERSION",	ZFS_META_VERSION },
827eda14cbcSMatt Macy 		{ "ZFS_RELEASE",	ZFS_META_RELEASE },
828eda14cbcSMatt Macy 		{ NULL,			NULL }
829eda14cbcSMatt Macy 	};
830eda14cbcSMatt Macy 	const char *(*pa)[2];
831eda14cbcSMatt Macy 
832eda14cbcSMatt Macy 	assert(zsp != NULL);
833eda14cbcSMatt Macy 
834eda14cbcSMatt Macy 	pa = path != NULL ? env_path : env_restrict;
835eda14cbcSMatt Macy 
836eda14cbcSMatt Macy 	for (; *(*pa); pa++) {
837eda14cbcSMatt Macy 		/* Use our custom $PATH if we have one */
838eda14cbcSMatt Macy 		if (path != NULL && strcmp((*pa)[0], "PATH") == 0)
839eda14cbcSMatt Macy 			(*pa)[1] = path;
840eda14cbcSMatt Macy 
841eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, NULL, (*pa)[0], "%s", (*pa)[1]);
842eda14cbcSMatt Macy 	}
843eda14cbcSMatt Macy }
844eda14cbcSMatt Macy 
845eda14cbcSMatt Macy /*
846eda14cbcSMatt Macy  * Preserve specified variables from the parent environment
847eda14cbcSMatt Macy  * when constructing the environment for the child process.
848eda14cbcSMatt Macy  *
849eda14cbcSMatt Macy  * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
850eda14cbcSMatt Macy  */
851eda14cbcSMatt Macy static void
_zed_event_add_env_preserve(uint64_t eid,zed_strings_t * zsp)852eda14cbcSMatt Macy _zed_event_add_env_preserve(uint64_t eid, zed_strings_t *zsp)
853eda14cbcSMatt Macy {
854eda14cbcSMatt Macy 	const char *env_preserve[] = {
855eda14cbcSMatt Macy 		"TZ",
856eda14cbcSMatt Macy 		NULL
857eda14cbcSMatt Macy 	};
858eda14cbcSMatt Macy 	const char **keyp;
859eda14cbcSMatt Macy 	const char *val;
860eda14cbcSMatt Macy 
861eda14cbcSMatt Macy 	assert(zsp != NULL);
862eda14cbcSMatt Macy 
863eda14cbcSMatt Macy 	for (keyp = env_preserve; *keyp; keyp++) {
864eda14cbcSMatt Macy 		if ((val = getenv(*keyp)))
865eda14cbcSMatt Macy 			_zed_event_add_var(eid, zsp, NULL, *keyp, "%s", val);
866eda14cbcSMatt Macy 	}
867eda14cbcSMatt Macy }
868eda14cbcSMatt Macy 
869eda14cbcSMatt Macy /*
870eda14cbcSMatt Macy  * Compute the "subclass" by removing the first 3 components of [class]
871eda14cbcSMatt Macy  * (which will always be of the form "*.fs.zfs").  Return a pointer inside
872eda14cbcSMatt Macy  * the string [class], or NULL if insufficient components exist.
873eda14cbcSMatt Macy  */
874eda14cbcSMatt Macy static const char *
_zed_event_get_subclass(const char * class)875eda14cbcSMatt Macy _zed_event_get_subclass(const char *class)
876eda14cbcSMatt Macy {
877eda14cbcSMatt Macy 	const char *p;
878eda14cbcSMatt Macy 	int i;
879eda14cbcSMatt Macy 
880eda14cbcSMatt Macy 	if (!class)
881eda14cbcSMatt Macy 		return (NULL);
882eda14cbcSMatt Macy 
883eda14cbcSMatt Macy 	p = class;
884eda14cbcSMatt Macy 	for (i = 0; i < 3; i++) {
885eda14cbcSMatt Macy 		p = strchr(p, '.');
886eda14cbcSMatt Macy 		if (!p)
887eda14cbcSMatt Macy 			break;
888eda14cbcSMatt Macy 		p++;
889eda14cbcSMatt Macy 	}
890eda14cbcSMatt Macy 	return (p);
891eda14cbcSMatt Macy }
892eda14cbcSMatt Macy 
893eda14cbcSMatt Macy /*
894eda14cbcSMatt Macy  * Convert the zevent time from a 2-element array of 64b integers
895eda14cbcSMatt Macy  * into a more convenient form:
896eda14cbcSMatt Macy  * - TIME_SECS is the second component of the time.
897eda14cbcSMatt Macy  * - TIME_NSECS is the nanosecond component of the time.
898eda14cbcSMatt Macy  * - TIME_STRING is an almost-RFC3339-compliant string representation.
899eda14cbcSMatt Macy  */
900eda14cbcSMatt Macy static void
_zed_event_add_time_strings(uint64_t eid,zed_strings_t * zsp,int64_t etime[])901eda14cbcSMatt Macy _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
902eda14cbcSMatt Macy {
903716fd348SMartin Matuska 	struct tm stp;
904eda14cbcSMatt Macy 	char buf[32];
905eda14cbcSMatt Macy 
906eda14cbcSMatt Macy 	assert(zsp != NULL);
907eda14cbcSMatt Macy 	assert(etime != NULL);
908eda14cbcSMatt Macy 
909eda14cbcSMatt Macy 	_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
910716fd348SMartin Matuska 	    "%" PRId64, etime[0]);
911eda14cbcSMatt Macy 	_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
912716fd348SMartin Matuska 	    "%" PRId64, etime[1]);
913eda14cbcSMatt Macy 
914716fd348SMartin Matuska 	if (!localtime_r((const time_t *) &etime[0], &stp)) {
915eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
916eda14cbcSMatt Macy 		    ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
917716fd348SMartin Matuska 	} else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", &stp)) {
918eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
919eda14cbcSMatt Macy 		    ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
920eda14cbcSMatt Macy 	} else {
921eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_STRING",
922eda14cbcSMatt Macy 		    "%s", buf);
923eda14cbcSMatt Macy 	}
924eda14cbcSMatt Macy }
925eda14cbcSMatt Macy 
926*14c2e0a0SMartin Matuska 
927*14c2e0a0SMartin Matuska static void
_zed_event_update_enc_sysfs_path(nvlist_t * nvl)928*14c2e0a0SMartin Matuska _zed_event_update_enc_sysfs_path(nvlist_t *nvl)
929*14c2e0a0SMartin Matuska {
930*14c2e0a0SMartin Matuska 	const char *vdev_path;
931*14c2e0a0SMartin Matuska 
932*14c2e0a0SMartin Matuska 	if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH,
933*14c2e0a0SMartin Matuska 	    &vdev_path) != 0) {
934*14c2e0a0SMartin Matuska 		return; /* some other kind of event, ignore it */
935*14c2e0a0SMartin Matuska 	}
936*14c2e0a0SMartin Matuska 
937*14c2e0a0SMartin Matuska 	if (vdev_path == NULL) {
938*14c2e0a0SMartin Matuska 		return;
939*14c2e0a0SMartin Matuska 	}
940*14c2e0a0SMartin Matuska 
941*14c2e0a0SMartin Matuska 	update_vdev_config_dev_sysfs_path(nvl, vdev_path,
942*14c2e0a0SMartin Matuska 	    FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH);
943*14c2e0a0SMartin Matuska }
944*14c2e0a0SMartin Matuska 
945eda14cbcSMatt Macy /*
946eda14cbcSMatt Macy  * Service the next zevent, blocking until one is available.
947eda14cbcSMatt Macy  */
948eda14cbcSMatt Macy int
zed_event_service(struct zed_conf * zcp)949eda14cbcSMatt Macy zed_event_service(struct zed_conf *zcp)
950eda14cbcSMatt Macy {
951eda14cbcSMatt Macy 	nvlist_t *nvl;
952eda14cbcSMatt Macy 	nvpair_t *nvp;
953eda14cbcSMatt Macy 	int n_dropped;
954eda14cbcSMatt Macy 	zed_strings_t *zsp;
955eda14cbcSMatt Macy 	uint64_t eid;
956eda14cbcSMatt Macy 	int64_t *etime;
957eda14cbcSMatt Macy 	uint_t nelem;
9582a58b312SMartin Matuska 	const char *class;
959eda14cbcSMatt Macy 	const char *subclass;
960eda14cbcSMatt Macy 	int rv;
961eda14cbcSMatt Macy 
962eda14cbcSMatt Macy 	if (!zcp) {
963eda14cbcSMatt Macy 		errno = EINVAL;
964eda14cbcSMatt Macy 		zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
965eda14cbcSMatt Macy 		    strerror(errno));
966eda14cbcSMatt Macy 		return (EINVAL);
967eda14cbcSMatt Macy 	}
968eda14cbcSMatt Macy 	rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
969eda14cbcSMatt Macy 	    zcp->zevent_fd);
970eda14cbcSMatt Macy 
971eda14cbcSMatt Macy 	if ((rv != 0) || !nvl)
972eda14cbcSMatt Macy 		return (errno);
973eda14cbcSMatt Macy 
974eda14cbcSMatt Macy 	if (n_dropped > 0) {
975eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
97616038816SMartin Matuska 		_bump_event_queue_length();
977eda14cbcSMatt Macy 	}
978eda14cbcSMatt Macy 	if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
979eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
980eda14cbcSMatt Macy 	} else if (nvlist_lookup_int64_array(
981eda14cbcSMatt Macy 	    nvl, "time", &etime, &nelem) != 0) {
982eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
983eda14cbcSMatt Macy 		    "Failed to lookup zevent time (eid=%llu)", eid);
984eda14cbcSMatt Macy 	} else if (nelem != 2) {
985eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
986eda14cbcSMatt Macy 		    "Failed to lookup zevent time (eid=%llu, nelem=%u)",
987eda14cbcSMatt Macy 		    eid, nelem);
988eda14cbcSMatt Macy 	} else if (nvlist_lookup_string(nvl, "class", &class) != 0) {
989eda14cbcSMatt Macy 		zed_log_msg(LOG_WARNING,
990eda14cbcSMatt Macy 		    "Failed to lookup zevent class (eid=%llu)", eid);
991eda14cbcSMatt Macy 	} else {
992*14c2e0a0SMartin Matuska 		/*
993*14c2e0a0SMartin Matuska 		 * Special case: If we can dynamically detect an enclosure sysfs
994*14c2e0a0SMartin Matuska 		 * path, then use that value rather than the one stored in the
995*14c2e0a0SMartin Matuska 		 * vd->vdev_enc_sysfs_path.  There have been rare cases where
996*14c2e0a0SMartin Matuska 		 * vd->vdev_enc_sysfs_path becomes outdated.  However, there
997*14c2e0a0SMartin Matuska 		 * will be other times when we can not dynamically detect the
998*14c2e0a0SMartin Matuska 		 * sysfs path (like if a disk disappears) and have to rely on
999*14c2e0a0SMartin Matuska 		 * the old value for things like turning on the fault LED.
1000*14c2e0a0SMartin Matuska 		 */
1001*14c2e0a0SMartin Matuska 		_zed_event_update_enc_sysfs_path(nvl);
1002*14c2e0a0SMartin Matuska 
1003eda14cbcSMatt Macy 		/* let internal modules see this event first */
1004eda14cbcSMatt Macy 		zfs_agent_post_event(class, NULL, nvl);
1005eda14cbcSMatt Macy 
1006eda14cbcSMatt Macy 		zsp = zed_strings_create();
1007eda14cbcSMatt Macy 
1008eda14cbcSMatt Macy 		nvp = NULL;
1009eda14cbcSMatt Macy 		while ((nvp = nvlist_next_nvpair(nvl, nvp)))
1010eda14cbcSMatt Macy 			_zed_event_add_nvpair(eid, zsp, nvp);
1011eda14cbcSMatt Macy 
1012eda14cbcSMatt Macy 		_zed_event_add_env_restrict(eid, zsp, zcp->path);
1013eda14cbcSMatt Macy 		_zed_event_add_env_preserve(eid, zsp);
1014eda14cbcSMatt Macy 
1015eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "PID",
1016eda14cbcSMatt Macy 		    "%d", (int)getpid());
1017eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "ZEDLET_DIR",
1018eda14cbcSMatt Macy 		    "%s", zcp->zedlet_dir);
1019eda14cbcSMatt Macy 		subclass = _zed_event_get_subclass(class);
1020eda14cbcSMatt Macy 		_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "SUBCLASS",
1021eda14cbcSMatt Macy 		    "%s", (subclass ? subclass : class));
1022eda14cbcSMatt Macy 
1023eda14cbcSMatt Macy 		_zed_event_add_time_strings(eid, zsp, etime);
1024eda14cbcSMatt Macy 
102516038816SMartin Matuska 		zed_exec_process(eid, class, subclass, zcp, zsp);
1026eda14cbcSMatt Macy 
1027eda14cbcSMatt Macy 		zed_conf_write_state(zcp, eid, etime);
1028eda14cbcSMatt Macy 
1029eda14cbcSMatt Macy 		zed_strings_destroy(zsp);
1030eda14cbcSMatt Macy 	}
1031eda14cbcSMatt Macy 	nvlist_free(nvl);
1032eda14cbcSMatt Macy 	return (0);
1033eda14cbcSMatt Macy }
1034