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