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