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/types.h>
29 #include <sys/param.h>
30 #include <sys/kernel.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
37 #include <sys/nvpair.h>
38 #include <sys/sunddi.h>
39 #include <sys/sysevent.h>
40 #include <sys/fm/protocol.h>
41 #include <sys/fm/util.h>
45 log_sysevent(nvlist_t
*event
)
50 nvpair_t
*elem
= NULL
;
57 while ((elem
= nvlist_next_nvpair(event
, elem
)) != NULL
) {
58 switch (nvpair_type(elem
)) {
59 case DATA_TYPE_BOOLEAN
:
63 (void) nvpair_value_boolean_value(elem
, &value
);
64 sbuf_printf(sb
, " %s=%s", nvpair_name(elem
),
65 value
? "true" : "false");
72 (void) nvpair_value_uint8(elem
, &value
);
73 sbuf_printf(sb
, " %s=%hhu", nvpair_name(elem
), value
);
80 (void) nvpair_value_int32(elem
, &value
);
81 sbuf_printf(sb
, " %s=%jd", nvpair_name(elem
),
85 case DATA_TYPE_UINT32
:
89 (void) nvpair_value_uint32(elem
, &value
);
90 sbuf_printf(sb
, " %s=%ju", nvpair_name(elem
),
98 (void) nvpair_value_int64(elem
, &value
);
99 sbuf_printf(sb
, " %s=%jd", nvpair_name(elem
),
103 case DATA_TYPE_UINT64
:
107 (void) nvpair_value_uint64(elem
, &value
);
108 sbuf_printf(sb
, " %s=%ju", nvpair_name(elem
),
112 case DATA_TYPE_STRING
:
116 (void) nvpair_value_string(elem
, &value
);
117 sbuf_printf(sb
, " %s=%s", nvpair_name(elem
), value
);
118 if (strcmp(FM_CLASS
, nvpair_name(elem
)) == 0)
122 case DATA_TYPE_UINT8_ARRAY
:
127 (void) nvpair_value_uint8_array(elem
, &value
, &nelem
);
128 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
129 for (ii
= 0; ii
< nelem
; ii
++)
130 sbuf_printf(sb
, "%02hhx", value
[ii
]);
133 case DATA_TYPE_UINT16_ARRAY
:
138 (void) nvpair_value_uint16_array(elem
, &value
, &nelem
);
139 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
140 for (ii
= 0; ii
< nelem
; ii
++)
141 sbuf_printf(sb
, "%04hx", value
[ii
]);
144 case DATA_TYPE_UINT32_ARRAY
:
149 (void) nvpair_value_uint32_array(elem
, &value
, &nelem
);
150 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
151 for (ii
= 0; ii
< nelem
; ii
++)
152 sbuf_printf(sb
, "%08jx", (uintmax_t)value
[ii
]);
155 case DATA_TYPE_INT64_ARRAY
:
160 (void) nvpair_value_int64_array(elem
, &value
, &nelem
);
161 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
162 for (ii
= 0; ii
< nelem
; ii
++)
163 sbuf_printf(sb
, "%016lld",
164 (long long)value
[ii
]);
167 case DATA_TYPE_UINT64_ARRAY
:
172 (void) nvpair_value_uint64_array(elem
, &value
, &nelem
);
173 sbuf_printf(sb
, " %s=", nvpair_name(elem
));
174 for (ii
= 0; ii
< nelem
; ii
++)
175 sbuf_printf(sb
, "%016jx", (uintmax_t)value
[ii
]);
178 case DATA_TYPE_STRING_ARRAY
:
183 (void) nvpair_value_string_array(elem
, &strarr
, &nelem
);
185 for (ii
= 0; ii
< nelem
; ii
++) {
186 if (strarr
[ii
] == NULL
) {
187 sbuf_printf(sb
, " <NULL>");
191 sbuf_printf(sb
, " %s", strarr
[ii
]);
192 if (strcmp(FM_CLASS
, strarr
[ii
]) == 0)
197 case DATA_TYPE_NVLIST
:
198 /* XXX - requires recursing in log_sysevent */
201 printf("%s: type %d is not implemented\n", __func__
,
207 if (sbuf_finish(sb
) != 0) {
214 if (strncmp(type
, "ESC_ZFS_", 8) == 0) {
215 snprintf(typestr
, sizeof (typestr
), "misc.fs.zfs.%s", type
+ 8);
218 devctl_notify("ZFS", "ZFS", type
, sbuf_data(sb
));
225 sysevent_worker(void *arg __unused
)
229 uint64_t dropped
= 0;
233 zfs_zevent_init(&ze
);
238 error
= zfs_zevent_next(ze
, &event
,
239 &dst_size
, &dropped
);
241 error
= zfs_zevent_wait(ze
);
242 if (error
== ESHUTDOWN
)
245 VERIFY3P(event
, !=, NULL
);
252 * We avoid zfs_zevent_destroy() here because we're otherwise racing
253 * against fm_fini() destroying the zevent_lock. zfs_zevent_destroy()
254 * will currently only clear `ze->ze_zevent` from an event list then
255 * free `ze`, so just inline the free() here -- events have already
258 VERIFY3P(ze
->ze_zevent
, ==, NULL
);
259 kmem_free(ze
, sizeof (zfs_zevent_t
));
265 ddi_sysevent_init(void)
267 kproc_kthread_add(sysevent_worker
, NULL
, &system_proc
, NULL
, 0, 0,
268 "zfskern", "sysevent");