1*ba2539a9Schs /*-
2*ba2539a9Schs * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3*ba2539a9Schs * All rights reserved.
4*ba2539a9Schs *
5*ba2539a9Schs * Redistribution and use in source and binary forms, with or without
6*ba2539a9Schs * modification, are permitted provided that the following conditions
7*ba2539a9Schs * are met:
8*ba2539a9Schs * 1. Redistributions of source code must retain the above copyright
9*ba2539a9Schs * notice, this list of conditions and the following disclaimer.
10*ba2539a9Schs * 2. Redistributions in binary form must reproduce the above copyright
11*ba2539a9Schs * notice, this list of conditions and the following disclaimer in the
12*ba2539a9Schs * documentation and/or other materials provided with the distribution.
13*ba2539a9Schs *
14*ba2539a9Schs * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15*ba2539a9Schs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*ba2539a9Schs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*ba2539a9Schs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18*ba2539a9Schs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*ba2539a9Schs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*ba2539a9Schs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*ba2539a9Schs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*ba2539a9Schs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*ba2539a9Schs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*ba2539a9Schs * SUCH DAMAGE.
25*ba2539a9Schs */
26*ba2539a9Schs
27*ba2539a9Schs #include <sys/cdefs.h>
28*ba2539a9Schs #ifdef __FreeBSD__
29*ba2539a9Schs __FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_sysevent.c 222343 2011-05-27 08:34:31Z pjd $");
30*ba2539a9Schs #endif
31*ba2539a9Schs
32*ba2539a9Schs #include <sys/param.h>
33*ba2539a9Schs #include <sys/kernel.h>
34*ba2539a9Schs #include <sys/systm.h>
35*ba2539a9Schs #include <sys/kmem.h>
36*ba2539a9Schs #ifdef __FreeBSD__
37*ba2539a9Schs #include <sys/sbuf.h>
38*ba2539a9Schs #endif
39*ba2539a9Schs #include <sys/nvpair.h>
40*ba2539a9Schs #include <sys/sunddi.h>
41*ba2539a9Schs #include <sys/sysevent.h>
42*ba2539a9Schs #include <sys/fm/protocol.h>
43*ba2539a9Schs
44*ba2539a9Schs struct sysevent {
45*ba2539a9Schs nvlist_t *se_nvl;
46*ba2539a9Schs char se_class[128];
47*ba2539a9Schs char se_subclass[128];
48*ba2539a9Schs char se_pub[128];
49*ba2539a9Schs };
50*ba2539a9Schs
51*ba2539a9Schs sysevent_t *
sysevent_alloc(char * class,char * subclass,char * pub,int flag)52*ba2539a9Schs sysevent_alloc(char *class, char *subclass, char *pub, int flag)
53*ba2539a9Schs {
54*ba2539a9Schs struct sysevent *ev;
55*ba2539a9Schs
56*ba2539a9Schs ASSERT(class != NULL);
57*ba2539a9Schs ASSERT(subclass != NULL);
58*ba2539a9Schs ASSERT(pub != NULL);
59*ba2539a9Schs ASSERT(flag == SE_SLEEP);
60*ba2539a9Schs
61*ba2539a9Schs ev = kmem_alloc(sizeof(*ev), KM_SLEEP);
62*ba2539a9Schs ev->se_nvl = NULL;
63*ba2539a9Schs strlcpy(ev->se_class, class, sizeof(ev->se_class));
64*ba2539a9Schs strlcpy(ev->se_subclass, subclass, sizeof(ev->se_subclass));
65*ba2539a9Schs strlcpy(ev->se_pub, pub, sizeof(ev->se_pub));
66*ba2539a9Schs
67*ba2539a9Schs return ((sysevent_t *)ev);
68*ba2539a9Schs }
69*ba2539a9Schs
70*ba2539a9Schs void
sysevent_free(sysevent_t * evp)71*ba2539a9Schs sysevent_free(sysevent_t *evp)
72*ba2539a9Schs {
73*ba2539a9Schs struct sysevent *ev = (struct sysevent *)evp;
74*ba2539a9Schs
75*ba2539a9Schs ASSERT(evp != NULL);
76*ba2539a9Schs
77*ba2539a9Schs if (ev->se_nvl != NULL)
78*ba2539a9Schs sysevent_free_attr(ev->se_nvl);
79*ba2539a9Schs kmem_free(ev, sizeof(*ev));
80*ba2539a9Schs }
81*ba2539a9Schs
82*ba2539a9Schs int
sysevent_add_attr(sysevent_attr_list_t ** ev_attr_list,char * name,sysevent_value_t * se_value,int flag)83*ba2539a9Schs sysevent_add_attr(sysevent_attr_list_t **ev_attr_list, char *name,
84*ba2539a9Schs sysevent_value_t *se_value, int flag)
85*ba2539a9Schs {
86*ba2539a9Schs nvlist_t *nvl;
87*ba2539a9Schs int error;
88*ba2539a9Schs
89*ba2539a9Schs ASSERT(ev_attr_list != NULL);
90*ba2539a9Schs ASSERT(name != NULL);
91*ba2539a9Schs ASSERT(se_value != NULL);
92*ba2539a9Schs ASSERT(flag == SE_SLEEP);
93*ba2539a9Schs
94*ba2539a9Schs if (strlen(name) >= MAX_ATTR_NAME)
95*ba2539a9Schs return (SE_EINVAL);
96*ba2539a9Schs
97*ba2539a9Schs nvl = *ev_attr_list;
98*ba2539a9Schs if (nvl == NULL) {
99*ba2539a9Schs if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, KM_SLEEP) != 0)
100*ba2539a9Schs return (SE_ENOMEM);
101*ba2539a9Schs }
102*ba2539a9Schs
103*ba2539a9Schs error = 0;
104*ba2539a9Schs
105*ba2539a9Schs switch (se_value->value_type) {
106*ba2539a9Schs case SE_DATA_TYPE_UINT64:
107*ba2539a9Schs error = nvlist_add_uint64(nvl, name, se_value->value.sv_uint64);
108*ba2539a9Schs break;
109*ba2539a9Schs case SE_DATA_TYPE_STRING:
110*ba2539a9Schs if (strlen(se_value->value.sv_string) >= MAX_STRING_SZ)
111*ba2539a9Schs error = SE_EINVAL;
112*ba2539a9Schs if (error == 0) {
113*ba2539a9Schs error = nvlist_add_string(nvl, name,
114*ba2539a9Schs se_value->value.sv_string);
115*ba2539a9Schs }
116*ba2539a9Schs break;
117*ba2539a9Schs default:
118*ba2539a9Schs #if 0
119*ba2539a9Schs printf("%s: type %d is not implemented\n", __func__,
120*ba2539a9Schs se_value->value_type);
121*ba2539a9Schs #endif
122*ba2539a9Schs break;
123*ba2539a9Schs }
124*ba2539a9Schs
125*ba2539a9Schs if (error != 0) {
126*ba2539a9Schs nvlist_free(nvl);
127*ba2539a9Schs return (error);
128*ba2539a9Schs }
129*ba2539a9Schs
130*ba2539a9Schs *ev_attr_list = nvl;
131*ba2539a9Schs
132*ba2539a9Schs return (0);
133*ba2539a9Schs }
134*ba2539a9Schs
135*ba2539a9Schs void
sysevent_free_attr(sysevent_attr_list_t * ev_attr_list)136*ba2539a9Schs sysevent_free_attr(sysevent_attr_list_t *ev_attr_list)
137*ba2539a9Schs {
138*ba2539a9Schs
139*ba2539a9Schs nvlist_free(ev_attr_list);
140*ba2539a9Schs }
141*ba2539a9Schs
142*ba2539a9Schs int
sysevent_attach_attributes(sysevent_t * evp,sysevent_attr_list_t * ev_attr_list)143*ba2539a9Schs sysevent_attach_attributes(sysevent_t *evp, sysevent_attr_list_t *ev_attr_list)
144*ba2539a9Schs {
145*ba2539a9Schs struct sysevent *ev = (struct sysevent *)evp;
146*ba2539a9Schs
147*ba2539a9Schs ASSERT(ev->se_nvl == NULL);
148*ba2539a9Schs
149*ba2539a9Schs ev->se_nvl = ev_attr_list;
150*ba2539a9Schs
151*ba2539a9Schs return (0);
152*ba2539a9Schs }
153*ba2539a9Schs
154*ba2539a9Schs void
sysevent_detach_attributes(sysevent_t * evp)155*ba2539a9Schs sysevent_detach_attributes(sysevent_t *evp)
156*ba2539a9Schs {
157*ba2539a9Schs struct sysevent *ev = (struct sysevent *)evp;
158*ba2539a9Schs
159*ba2539a9Schs ASSERT(ev->se_nvl != NULL);
160*ba2539a9Schs
161*ba2539a9Schs ev->se_nvl = NULL;
162*ba2539a9Schs }
163*ba2539a9Schs
164*ba2539a9Schs int
log_sysevent(sysevent_t * evp,int flag,sysevent_id_t * eid)165*ba2539a9Schs log_sysevent(sysevent_t *evp, int flag, sysevent_id_t *eid)
166*ba2539a9Schs {
167*ba2539a9Schs #ifdef __NetBSD__
168*ba2539a9Schs /* XXXNETBSD we ought to do something here */
169*ba2539a9Schs #else
170*ba2539a9Schs struct sysevent *ev = (struct sysevent *)evp;
171*ba2539a9Schs struct sbuf *sb;
172*ba2539a9Schs const char *type;
173*ba2539a9Schs char typestr[128];
174*ba2539a9Schs nvpair_t *elem = NULL;
175*ba2539a9Schs
176*ba2539a9Schs ASSERT(evp != NULL);
177*ba2539a9Schs ASSERT(ev->se_nvl != NULL);
178*ba2539a9Schs ASSERT(flag == SE_SLEEP);
179*ba2539a9Schs ASSERT(eid != NULL);
180*ba2539a9Schs
181*ba2539a9Schs sb = sbuf_new_auto();
182*ba2539a9Schs if (sb == NULL)
183*ba2539a9Schs return (SE_ENOMEM);
184*ba2539a9Schs type = NULL;
185*ba2539a9Schs
186*ba2539a9Schs while ((elem = nvlist_next_nvpair(ev->se_nvl, elem)) != NULL) {
187*ba2539a9Schs switch (nvpair_type(elem)) {
188*ba2539a9Schs case DATA_TYPE_BOOLEAN:
189*ba2539a9Schs {
190*ba2539a9Schs boolean_t value;
191*ba2539a9Schs
192*ba2539a9Schs (void) nvpair_value_boolean_value(elem, &value);
193*ba2539a9Schs sbuf_printf(sb, " %s=%s", nvpair_name(elem),
194*ba2539a9Schs value ? "true" : "false");
195*ba2539a9Schs break;
196*ba2539a9Schs }
197*ba2539a9Schs case DATA_TYPE_UINT8:
198*ba2539a9Schs {
199*ba2539a9Schs uint8_t value;
200*ba2539a9Schs
201*ba2539a9Schs (void) nvpair_value_uint8(elem, &value);
202*ba2539a9Schs sbuf_printf(sb, " %s=%hhu", nvpair_name(elem), value);
203*ba2539a9Schs break;
204*ba2539a9Schs }
205*ba2539a9Schs case DATA_TYPE_INT32:
206*ba2539a9Schs {
207*ba2539a9Schs int32_t value;
208*ba2539a9Schs
209*ba2539a9Schs (void) nvpair_value_int32(elem, &value);
210*ba2539a9Schs sbuf_printf(sb, " %s=%jd", nvpair_name(elem),
211*ba2539a9Schs (intmax_t)value);
212*ba2539a9Schs break;
213*ba2539a9Schs }
214*ba2539a9Schs case DATA_TYPE_UINT32:
215*ba2539a9Schs {
216*ba2539a9Schs uint32_t value;
217*ba2539a9Schs
218*ba2539a9Schs (void) nvpair_value_uint32(elem, &value);
219*ba2539a9Schs sbuf_printf(sb, " %s=%ju", nvpair_name(elem),
220*ba2539a9Schs (uintmax_t)value);
221*ba2539a9Schs break;
222*ba2539a9Schs }
223*ba2539a9Schs case DATA_TYPE_INT64:
224*ba2539a9Schs {
225*ba2539a9Schs int64_t value;
226*ba2539a9Schs
227*ba2539a9Schs (void) nvpair_value_int64(elem, &value);
228*ba2539a9Schs sbuf_printf(sb, " %s=%jd", nvpair_name(elem),
229*ba2539a9Schs (intmax_t)value);
230*ba2539a9Schs break;
231*ba2539a9Schs }
232*ba2539a9Schs case DATA_TYPE_UINT64:
233*ba2539a9Schs {
234*ba2539a9Schs uint64_t value;
235*ba2539a9Schs
236*ba2539a9Schs (void) nvpair_value_uint64(elem, &value);
237*ba2539a9Schs sbuf_printf(sb, " %s=%ju", nvpair_name(elem),
238*ba2539a9Schs (uintmax_t)value);
239*ba2539a9Schs break;
240*ba2539a9Schs }
241*ba2539a9Schs case DATA_TYPE_STRING:
242*ba2539a9Schs {
243*ba2539a9Schs char *value;
244*ba2539a9Schs
245*ba2539a9Schs (void) nvpair_value_string(elem, &value);
246*ba2539a9Schs sbuf_printf(sb, " %s=%s", nvpair_name(elem), value);
247*ba2539a9Schs if (strcmp(FM_CLASS, nvpair_name(elem)) == 0)
248*ba2539a9Schs type = value;
249*ba2539a9Schs break;
250*ba2539a9Schs }
251*ba2539a9Schs case DATA_TYPE_UINT8_ARRAY:
252*ba2539a9Schs {
253*ba2539a9Schs uint8_t *value;
254*ba2539a9Schs uint_t ii, nelem;
255*ba2539a9Schs
256*ba2539a9Schs (void) nvpair_value_uint8_array(elem, &value, &nelem);
257*ba2539a9Schs sbuf_printf(sb, " %s=", nvpair_name(elem));
258*ba2539a9Schs for (ii = 0; ii < nelem; ii++)
259*ba2539a9Schs sbuf_printf(sb, "%02hhx", value[ii]);
260*ba2539a9Schs break;
261*ba2539a9Schs }
262*ba2539a9Schs case DATA_TYPE_UINT16_ARRAY:
263*ba2539a9Schs {
264*ba2539a9Schs uint16_t *value;
265*ba2539a9Schs uint_t ii, nelem;
266*ba2539a9Schs
267*ba2539a9Schs (void) nvpair_value_uint16_array(elem, &value, &nelem);
268*ba2539a9Schs sbuf_printf(sb, " %s=", nvpair_name(elem));
269*ba2539a9Schs for (ii = 0; ii < nelem; ii++)
270*ba2539a9Schs sbuf_printf(sb, "%04hx", value[ii]);
271*ba2539a9Schs break;
272*ba2539a9Schs }
273*ba2539a9Schs case DATA_TYPE_UINT32_ARRAY:
274*ba2539a9Schs {
275*ba2539a9Schs uint32_t *value;
276*ba2539a9Schs uint_t ii, nelem;
277*ba2539a9Schs
278*ba2539a9Schs (void) nvpair_value_uint32_array(elem, &value, &nelem);
279*ba2539a9Schs sbuf_printf(sb, " %s=", nvpair_name(elem));
280*ba2539a9Schs for (ii = 0; ii < nelem; ii++)
281*ba2539a9Schs sbuf_printf(sb, "%08jx", (uintmax_t)value[ii]);
282*ba2539a9Schs break;
283*ba2539a9Schs }
284*ba2539a9Schs case DATA_TYPE_UINT64_ARRAY:
285*ba2539a9Schs {
286*ba2539a9Schs uint64_t *value;
287*ba2539a9Schs uint_t ii, nelem;
288*ba2539a9Schs
289*ba2539a9Schs (void) nvpair_value_uint64_array(elem, &value, &nelem);
290*ba2539a9Schs sbuf_printf(sb, " %s=", nvpair_name(elem));
291*ba2539a9Schs for (ii = 0; ii < nelem; ii++)
292*ba2539a9Schs sbuf_printf(sb, "%016jx", (uintmax_t)value[ii]);
293*ba2539a9Schs break;
294*ba2539a9Schs }
295*ba2539a9Schs default:
296*ba2539a9Schs #if 0
297*ba2539a9Schs printf("%s: type %d is not implemented\n", __func__,
298*ba2539a9Schs nvpair_type(elem));
299*ba2539a9Schs #endif
300*ba2539a9Schs break;
301*ba2539a9Schs }
302*ba2539a9Schs }
303*ba2539a9Schs
304*ba2539a9Schs if (sbuf_finish(sb) != 0) {
305*ba2539a9Schs sbuf_delete(sb);
306*ba2539a9Schs return (SE_ENOMEM);
307*ba2539a9Schs }
308*ba2539a9Schs
309*ba2539a9Schs if (type == NULL)
310*ba2539a9Schs type = ev->se_subclass;
311*ba2539a9Schs if (strncmp(type, "ESC_ZFS_", 8) == 0) {
312*ba2539a9Schs snprintf(typestr, sizeof(typestr), "misc.fs.zfs.%s", type + 8);
313*ba2539a9Schs type = typestr;
314*ba2539a9Schs }
315*ba2539a9Schs devctl_notify("ZFS", "ZFS", type, sbuf_data(sb));
316*ba2539a9Schs sbuf_delete(sb);
317*ba2539a9Schs #endif
318*ba2539a9Schs
319*ba2539a9Schs return (0);
320*ba2539a9Schs }
321*ba2539a9Schs
322*ba2539a9Schs int
_ddi_log_sysevent(char * vendor,char * class,char * subclass,nvlist_t * attr_list,sysevent_id_t * eidp,int flag)323*ba2539a9Schs _ddi_log_sysevent(char *vendor, char *class, char *subclass,
324*ba2539a9Schs nvlist_t *attr_list, sysevent_id_t *eidp, int flag)
325*ba2539a9Schs {
326*ba2539a9Schs sysevent_t *ev;
327*ba2539a9Schs int ret;
328*ba2539a9Schs
329*ba2539a9Schs ASSERT(vendor != NULL);
330*ba2539a9Schs ASSERT(class != NULL);
331*ba2539a9Schs ASSERT(subclass != NULL);
332*ba2539a9Schs ASSERT(attr_list != NULL);
333*ba2539a9Schs ASSERT(eidp != NULL);
334*ba2539a9Schs ASSERT(flag == DDI_SLEEP);
335*ba2539a9Schs
336*ba2539a9Schs ev = sysevent_alloc(class, subclass, vendor, SE_SLEEP);
337*ba2539a9Schs ASSERT(ev != NULL);
338*ba2539a9Schs (void)sysevent_attach_attributes(ev, attr_list);
339*ba2539a9Schs ret = log_sysevent(ev, SE_SLEEP, eidp);
340*ba2539a9Schs sysevent_detach_attributes(ev);
341*ba2539a9Schs sysevent_free(ev);
342*ba2539a9Schs
343*ba2539a9Schs return (ret);
344*ba2539a9Schs }
345