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