2 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * Copyright (c) 2020 iXsystems, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
40 #include <sys/nvpair.h>
41 #include <sys/sunddi.h>
42 #include <sys/sysevent.h>
43 #include <sys/fm/protocol.h>
44 #include <sys/fm/util.h>
48 log_sysevent(nvlist_t
*event
)
53 nvpair_t
*elem
= NULL
;
60 while ((elem
= nvlist_next_nvpair(event
, elem
)) != NULL
) {
61 switch (nvpair_type(elem
)) {
62 case DATA_TYPE_BOOLEAN
:
66 (void) nvpair_value_boolean_value(elem
, &value
);
67 sbuf_printf(sb
, " %s=%s", nvpair_name(elem
),
68 value
? "true" : "false");
75 (void) nvpair_value_uint8(elem
, &value
);
76 sbuf_printf(sb
, " %s=%hhu", nvpair_name(elem
), value
);
83 (void) nvpair_value_int32(elem
, &value
);
84 sbuf_printf(sb
, " %s=%jd", nvpair_name(elem
),
88 case DATA_TYPE_UINT32
:
92 (void) nvpair_value_uint32(elem
, &value
);
93 sbuf_printf(sb
, " %s=%ju", nvpair_name(elem
),
101 (void) nvpair_value_int64(elem
, &value
);
102 sbuf_printf(sb
, " %s=%jd", nvpair_name(elem
),
106 case DATA_TYPE_UINT64
:
110 (void) nvpair_value_uint64(elem
, &value
);
111 sbuf_printf(sb
, " %s=%ju", nvpair_name(elem
),
115 case DATA_TYPE_STRING
:
119 (void) nvpair_value_string(elem
, &value
);
120 sbuf_printf(sb
, " %s=%s", nvpair_name(elem
), value
);
121 if (strcmp(FM_CLASS
, nvpair_name(elem
)) == 0)
125 case DATA_TYPE_UINT8_ARRAY
:
130 (void) nvpair_value_uint8_array(elem
, &value
, &nelem
);
131 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
132 for (ii
= 0; ii
< nelem
; ii
++)
133 sbuf_printf(sb
, "%02hhx", value
[ii
]);
136 case DATA_TYPE_UINT16_ARRAY
:
141 (void) nvpair_value_uint16_array(elem
, &value
, &nelem
);
142 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
143 for (ii
= 0; ii
< nelem
; ii
++)
144 sbuf_printf(sb
, "%04hx", value
[ii
]);
147 case DATA_TYPE_UINT32_ARRAY
:
152 (void) nvpair_value_uint32_array(elem
, &value
, &nelem
);
153 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
154 for (ii
= 0; ii
< nelem
; ii
++)
155 sbuf_printf(sb
, "%08jx", (uintmax_t)value
[ii
]);
158 case DATA_TYPE_INT64_ARRAY
:
163 (void) nvpair_value_int64_array(elem
, &value
, &nelem
);
164 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
165 for (ii
= 0; ii
< nelem
; ii
++)
166 sbuf_printf(sb
, "%016lld",
167 (long long)value
[ii
]);
170 case DATA_TYPE_UINT64_ARRAY
:
175 (void) nvpair_value_uint64_array(elem
, &value
, &nelem
);
176 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
177 for (ii
= 0; ii
< nelem
; ii
++)
178 sbuf_printf(sb
, "%016jx", (uintmax_t)value
[ii
]);
181 case DATA_TYPE_STRING_ARRAY
:
186 (void) nvpair_value_string_array(elem
, &strarr
, &nelem
);
188 for (ii
= 0; ii
< nelem
; ii
++) {
189 if (strarr
[ii
] == NULL
) {
190 sbuf_printf(sb
, " <NULL>");
194 sbuf_printf(sb
, " %s", strarr
[ii
]);
195 if (strcmp(FM_CLASS
, strarr
[ii
]) == 0)
200 case DATA_TYPE_NVLIST
:
201 /* XXX - requires recursing in log_sysevent */
204 printf("%s: type %d is not implemented\n", __func__
,
210 if (sbuf_finish(sb
) != 0) {
217 if (strncmp(type
, "ESC_ZFS_", 8) == 0) {
218 snprintf(typestr
, sizeof (typestr
), "misc.fs.zfs.%s", type
+ 8);
221 devctl_notify("ZFS", "ZFS", type
, sbuf_data(sb
));
228 sysevent_worker(void *arg __unused
)
232 uint64_t dropped
= 0;
236 zfs_zevent_init(&ze
);
241 error
= zfs_zevent_next(ze
, &event
,
242 &dst_size
, &dropped
);
244 error
= zfs_zevent_wait(ze
);
245 if (error
== ESHUTDOWN
)
248 VERIFY3P(event
, !=, NULL
);
255 * We avoid zfs_zevent_destroy() here because we're otherwise racing
256 * against fm_fini() destroying the zevent_lock. zfs_zevent_destroy()
257 * will currently only clear `ze->ze_zevent` from an event list then
258 * free `ze`, so just inline the free() here -- events have already
261 VERIFY3P(ze
->ze_zevent
, ==, NULL
);
262 kmem_free(ze
, sizeof (zfs_zevent_t
));
268 ddi_sysevent_init(void)
270 kproc_kthread_add(sysevent_worker
, NULL
, &system_proc
, NULL
, 0, 0,
271 "zfskern", "sysevent");