1 /* 2 * This file is part of the ZFS Event Daemon (ZED). 3 * 4 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). 5 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. 6 * Refer to the OpenZFS git commit log for authoritative copyright attribution. 7 * 8 * The contents of this file are subject to the terms of the 9 * Common Development and Distribution License Version 1.0 (CDDL-1.0). 10 * You can obtain a copy of the license from the top-level file 11 * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>. 12 * You may not use this file except in compliance with the license. 13 */ 14 15 #include <ctype.h> 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <libzfs_core.h> 19 #include <paths.h> 20 #include <stdarg.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <sys/zfs_ioctl.h> 25 #include <time.h> 26 #include <unistd.h> 27 #include <sys/fm/fs/zfs.h> 28 #include "zed.h" 29 #include "zed_conf.h" 30 #include "zed_disk_event.h" 31 #include "zed_event.h" 32 #include "zed_exec.h" 33 #include "zed_file.h" 34 #include "zed_log.h" 35 #include "zed_strings.h" 36 37 #include "agents/zfs_agents.h" 38 #include <libzutil.h> 39 40 #define MAXBUF 4096 41 42 static int max_zevent_buf_len = 1 << 20; 43 44 /* 45 * Open the libzfs interface. 46 */ 47 int 48 zed_event_init(struct zed_conf *zcp) 49 { 50 if (!zcp) 51 zed_log_die("Failed zed_event_init: %s", strerror(EINVAL)); 52 53 zcp->zfs_hdl = libzfs_init(); 54 if (!zcp->zfs_hdl) { 55 if (zcp->do_idle) 56 return (-1); 57 zed_log_die("Failed to initialize libzfs"); 58 } 59 60 zcp->zevent_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); 61 if (zcp->zevent_fd < 0) { 62 if (zcp->do_idle) 63 return (-1); 64 zed_log_die("Failed to open \"%s\": %s", 65 ZFS_DEV, strerror(errno)); 66 } 67 68 zfs_agent_init(zcp->zfs_hdl); 69 70 if (zed_disk_event_init() != 0) { 71 if (zcp->do_idle) 72 return (-1); 73 zed_log_die("Failed to initialize disk events"); 74 } 75 76 if (zcp->max_zevent_buf_len != 0) 77 max_zevent_buf_len = zcp->max_zevent_buf_len; 78 79 return (0); 80 } 81 82 /* 83 * Close the libzfs interface. 84 */ 85 void 86 zed_event_fini(struct zed_conf *zcp) 87 { 88 if (!zcp) 89 zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL)); 90 91 zed_disk_event_fini(); 92 zfs_agent_fini(); 93 94 if (zcp->zevent_fd >= 0) { 95 if (close(zcp->zevent_fd) < 0) 96 zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s", 97 ZFS_DEV, strerror(errno)); 98 99 zcp->zevent_fd = -1; 100 } 101 if (zcp->zfs_hdl) { 102 libzfs_fini(zcp->zfs_hdl); 103 zcp->zfs_hdl = NULL; 104 } 105 106 zed_exec_fini(); 107 } 108 109 static void 110 _bump_event_queue_length(void) 111 { 112 int zzlm = -1, wr; 113 char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */ 114 long int qlen, orig_qlen; 115 116 zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR); 117 if (zzlm < 0) 118 goto done; 119 120 if (read(zzlm, qlen_buf, sizeof (qlen_buf)) < 0) 121 goto done; 122 qlen_buf[sizeof (qlen_buf) - 1] = '\0'; 123 124 errno = 0; 125 orig_qlen = qlen = strtol(qlen_buf, NULL, 10); 126 if (errno == ERANGE) 127 goto done; 128 129 if (qlen <= 0) 130 qlen = 512; /* default zfs_zevent_len_max value */ 131 else 132 qlen *= 2; 133 134 /* 135 * Don't consume all of kernel memory with event logs if something 136 * goes wrong. 137 */ 138 if (qlen > max_zevent_buf_len) 139 qlen = max_zevent_buf_len; 140 if (qlen == orig_qlen) 141 goto done; 142 wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen); 143 if (wr >= sizeof (qlen_buf)) { 144 wr = sizeof (qlen_buf) - 1; 145 zed_log_msg(LOG_WARNING, "Truncation in %s()", __func__); 146 } 147 148 if (pwrite(zzlm, qlen_buf, wr + 1, 0) < 0) 149 goto done; 150 151 zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen); 152 153 done: 154 if (zzlm > -1) 155 (void) close(zzlm); 156 } 157 158 /* 159 * Seek to the event specified by [saved_eid] and [saved_etime]. 160 * This protects against processing a given event more than once. 161 * Return 0 upon a successful seek to the specified event, or -1 otherwise. 162 * 163 * A zevent is considered to be uniquely specified by its (eid,time) tuple. 164 * The unsigned 64b eid is set to 1 when the kernel module is loaded, and 165 * incremented by 1 for each new event. Since the state file can persist 166 * across a kernel module reload, the time must be checked to ensure a match. 167 */ 168 int 169 zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[]) 170 { 171 uint64_t eid; 172 int found; 173 nvlist_t *nvl; 174 int n_dropped; 175 int64_t *etime; 176 uint_t nelem; 177 int rv; 178 179 if (!zcp) { 180 errno = EINVAL; 181 zed_log_msg(LOG_ERR, "Failed to seek zevent: %s", 182 strerror(errno)); 183 return (-1); 184 } 185 eid = 0; 186 found = 0; 187 while ((eid < saved_eid) && !found) { 188 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, 189 ZEVENT_NONBLOCK, zcp->zevent_fd); 190 191 if ((rv != 0) || !nvl) 192 break; 193 194 if (n_dropped > 0) { 195 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped); 196 _bump_event_queue_length(); 197 } 198 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) { 199 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid"); 200 } else if (nvlist_lookup_int64_array(nvl, "time", 201 &etime, &nelem) != 0) { 202 zed_log_msg(LOG_WARNING, 203 "Failed to lookup zevent time (eid=%llu)", eid); 204 } else if (nelem != 2) { 205 zed_log_msg(LOG_WARNING, 206 "Failed to lookup zevent time (eid=%llu, nelem=%u)", 207 eid, nelem); 208 } else if ((eid != saved_eid) || 209 (etime[0] != saved_etime[0]) || 210 (etime[1] != saved_etime[1])) { 211 /* no-op */ 212 } else { 213 found = 1; 214 } 215 free(nvl); 216 } 217 if (!found && (saved_eid > 0)) { 218 if (zpool_events_seek(zcp->zfs_hdl, ZEVENT_SEEK_START, 219 zcp->zevent_fd) < 0) 220 zed_log_msg(LOG_WARNING, "Failed to seek to eid=0"); 221 else 222 eid = 0; 223 } 224 zed_log_msg(LOG_NOTICE, "Processing events since eid=%llu", eid); 225 return (found ? 0 : -1); 226 } 227 228 /* 229 * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0. 230 */ 231 static int 232 _zed_event_value_is_hex(const char *name) 233 { 234 const char *hex_suffix[] = { 235 "_guid", 236 "_guids", 237 NULL 238 }; 239 const char **pp; 240 char *p; 241 242 if (!name) 243 return (0); 244 245 for (pp = hex_suffix; *pp; pp++) { 246 p = strstr(name, *pp); 247 if (p && strlen(p) == strlen(*pp)) 248 return (1); 249 } 250 return (0); 251 } 252 253 /* 254 * Add an environment variable for [eid] to the container [zsp]. 255 * 256 * The variable name is the concatenation of [prefix] and [name] converted to 257 * uppercase with non-alphanumeric characters converted to underscores; 258 * [prefix] is optional, and [name] must begin with an alphabetic character. 259 * If the converted variable name already exists within the container [zsp], 260 * its existing value will be replaced with the new value. 261 * 262 * The variable value is specified by the format string [fmt]. 263 * 264 * Returns 0 on success, and -1 on error (with errno set). 265 * 266 * All environment variables in [zsp] should be added through this function. 267 */ 268 static __attribute__((format(printf, 5, 6))) int 269 _zed_event_add_var(uint64_t eid, zed_strings_t *zsp, 270 const char *prefix, const char *name, const char *fmt, ...) 271 { 272 char keybuf[MAXBUF]; 273 char valbuf[MAXBUF]; 274 char *dstp; 275 const char *srcp; 276 const char *lastp; 277 int n; 278 int buflen; 279 va_list vargs; 280 281 assert(zsp != NULL); 282 assert(fmt != NULL); 283 284 if (!name) { 285 errno = EINVAL; 286 zed_log_msg(LOG_WARNING, 287 "Failed to add variable for eid=%llu: Name is empty", eid); 288 return (-1); 289 } else if (!isalpha(name[0])) { 290 errno = EINVAL; 291 zed_log_msg(LOG_WARNING, 292 "Failed to add variable for eid=%llu: " 293 "Name \"%s\" is invalid", eid, name); 294 return (-1); 295 } 296 /* 297 * Construct the string key by converting PREFIX (if present) and NAME. 298 */ 299 dstp = keybuf; 300 lastp = keybuf + sizeof (keybuf); 301 if (prefix) { 302 for (srcp = prefix; *srcp && (dstp < lastp); srcp++) 303 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_'; 304 } 305 for (srcp = name; *srcp && (dstp < lastp); srcp++) 306 *dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_'; 307 308 if (dstp == lastp) { 309 errno = ENAMETOOLONG; 310 zed_log_msg(LOG_WARNING, 311 "Failed to add variable for eid=%llu: Name too long", eid); 312 return (-1); 313 } 314 *dstp = '\0'; 315 /* 316 * Construct the string specified by "[PREFIX][NAME]=[FMT]". 317 */ 318 dstp = valbuf; 319 buflen = sizeof (valbuf); 320 n = strlcpy(dstp, keybuf, buflen); 321 if (n >= sizeof (valbuf)) { 322 errno = EMSGSIZE; 323 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s", 324 keybuf, eid, "Exceeded buffer size"); 325 return (-1); 326 } 327 dstp += n; 328 buflen -= n; 329 330 *dstp++ = '='; 331 buflen--; 332 333 if (buflen <= 0) { 334 errno = EMSGSIZE; 335 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s", 336 keybuf, eid, "Exceeded buffer size"); 337 return (-1); 338 } 339 340 va_start(vargs, fmt); 341 n = vsnprintf(dstp, buflen, fmt, vargs); 342 va_end(vargs); 343 344 if ((n < 0) || (n >= buflen)) { 345 errno = EMSGSIZE; 346 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s", 347 keybuf, eid, "Exceeded buffer size"); 348 return (-1); 349 } else if (zed_strings_add(zsp, keybuf, valbuf) < 0) { 350 zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s", 351 keybuf, eid, strerror(errno)); 352 return (-1); 353 } 354 return (0); 355 } 356 357 static int 358 _zed_event_add_array_err(uint64_t eid, const char *name) 359 { 360 errno = EMSGSIZE; 361 zed_log_msg(LOG_WARNING, 362 "Failed to convert nvpair \"%s\" for eid=%llu: " 363 "Exceeded buffer size", name, eid); 364 return (-1); 365 } 366 367 static int 368 _zed_event_add_int8_array(uint64_t eid, zed_strings_t *zsp, 369 const char *prefix, nvpair_t *nvp) 370 { 371 char buf[MAXBUF]; 372 int buflen = sizeof (buf); 373 const char *name; 374 int8_t *i8p; 375 uint_t nelem; 376 uint_t i; 377 char *p; 378 int n; 379 380 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT8_ARRAY)); 381 382 name = nvpair_name(nvp); 383 (void) nvpair_value_int8_array(nvp, &i8p, &nelem); 384 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 385 n = snprintf(p, buflen, "%d ", i8p[i]); 386 if ((n < 0) || (n >= buflen)) 387 return (_zed_event_add_array_err(eid, name)); 388 p += n; 389 buflen -= n; 390 } 391 if (nelem > 0) 392 *--p = '\0'; 393 394 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 395 } 396 397 static int 398 _zed_event_add_uint8_array(uint64_t eid, zed_strings_t *zsp, 399 const char *prefix, nvpair_t *nvp) 400 { 401 char buf[MAXBUF]; 402 int buflen = sizeof (buf); 403 const char *name; 404 uint8_t *u8p; 405 uint_t nelem; 406 uint_t i; 407 char *p; 408 int n; 409 410 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT8_ARRAY)); 411 412 name = nvpair_name(nvp); 413 (void) nvpair_value_uint8_array(nvp, &u8p, &nelem); 414 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 415 n = snprintf(p, buflen, "%u ", u8p[i]); 416 if ((n < 0) || (n >= buflen)) 417 return (_zed_event_add_array_err(eid, name)); 418 p += n; 419 buflen -= n; 420 } 421 if (nelem > 0) 422 *--p = '\0'; 423 424 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 425 } 426 427 static int 428 _zed_event_add_int16_array(uint64_t eid, zed_strings_t *zsp, 429 const char *prefix, nvpair_t *nvp) 430 { 431 char buf[MAXBUF]; 432 int buflen = sizeof (buf); 433 const char *name; 434 int16_t *i16p; 435 uint_t nelem; 436 uint_t i; 437 char *p; 438 int n; 439 440 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT16_ARRAY)); 441 442 name = nvpair_name(nvp); 443 (void) nvpair_value_int16_array(nvp, &i16p, &nelem); 444 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 445 n = snprintf(p, buflen, "%d ", i16p[i]); 446 if ((n < 0) || (n >= buflen)) 447 return (_zed_event_add_array_err(eid, name)); 448 p += n; 449 buflen -= n; 450 } 451 if (nelem > 0) 452 *--p = '\0'; 453 454 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 455 } 456 457 static int 458 _zed_event_add_uint16_array(uint64_t eid, zed_strings_t *zsp, 459 const char *prefix, nvpair_t *nvp) 460 { 461 char buf[MAXBUF]; 462 int buflen = sizeof (buf); 463 const char *name; 464 uint16_t *u16p; 465 uint_t nelem; 466 uint_t i; 467 char *p; 468 int n; 469 470 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY)); 471 472 name = nvpair_name(nvp); 473 (void) nvpair_value_uint16_array(nvp, &u16p, &nelem); 474 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 475 n = snprintf(p, buflen, "%u ", u16p[i]); 476 if ((n < 0) || (n >= buflen)) 477 return (_zed_event_add_array_err(eid, name)); 478 p += n; 479 buflen -= n; 480 } 481 if (nelem > 0) 482 *--p = '\0'; 483 484 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 485 } 486 487 static int 488 _zed_event_add_int32_array(uint64_t eid, zed_strings_t *zsp, 489 const char *prefix, nvpair_t *nvp) 490 { 491 char buf[MAXBUF]; 492 int buflen = sizeof (buf); 493 const char *name; 494 int32_t *i32p; 495 uint_t nelem; 496 uint_t i; 497 char *p; 498 int n; 499 500 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT32_ARRAY)); 501 502 name = nvpair_name(nvp); 503 (void) nvpair_value_int32_array(nvp, &i32p, &nelem); 504 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 505 n = snprintf(p, buflen, "%d ", i32p[i]); 506 if ((n < 0) || (n >= buflen)) 507 return (_zed_event_add_array_err(eid, name)); 508 p += n; 509 buflen -= n; 510 } 511 if (nelem > 0) 512 *--p = '\0'; 513 514 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 515 } 516 517 static int 518 _zed_event_add_uint32_array(uint64_t eid, zed_strings_t *zsp, 519 const char *prefix, nvpair_t *nvp) 520 { 521 char buf[MAXBUF]; 522 int buflen = sizeof (buf); 523 const char *name; 524 uint32_t *u32p; 525 uint_t nelem; 526 uint_t i; 527 char *p; 528 int n; 529 530 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT32_ARRAY)); 531 532 name = nvpair_name(nvp); 533 (void) nvpair_value_uint32_array(nvp, &u32p, &nelem); 534 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 535 n = snprintf(p, buflen, "%u ", u32p[i]); 536 if ((n < 0) || (n >= buflen)) 537 return (_zed_event_add_array_err(eid, name)); 538 p += n; 539 buflen -= n; 540 } 541 if (nelem > 0) 542 *--p = '\0'; 543 544 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 545 } 546 547 static int 548 _zed_event_add_int64_array(uint64_t eid, zed_strings_t *zsp, 549 const char *prefix, nvpair_t *nvp) 550 { 551 char buf[MAXBUF]; 552 int buflen = sizeof (buf); 553 const char *name; 554 int64_t *i64p; 555 uint_t nelem; 556 uint_t i; 557 char *p; 558 int n; 559 560 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT64_ARRAY)); 561 562 name = nvpair_name(nvp); 563 (void) nvpair_value_int64_array(nvp, &i64p, &nelem); 564 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 565 n = snprintf(p, buflen, "%lld ", (u_longlong_t)i64p[i]); 566 if ((n < 0) || (n >= buflen)) 567 return (_zed_event_add_array_err(eid, name)); 568 p += n; 569 buflen -= n; 570 } 571 if (nelem > 0) 572 *--p = '\0'; 573 574 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 575 } 576 577 static int 578 _zed_event_add_uint64_array(uint64_t eid, zed_strings_t *zsp, 579 const char *prefix, nvpair_t *nvp) 580 { 581 char buf[MAXBUF]; 582 int buflen = sizeof (buf); 583 const char *name; 584 const char *fmt; 585 uint64_t *u64p; 586 uint_t nelem; 587 uint_t i; 588 char *p; 589 int n; 590 591 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY)); 592 593 name = nvpair_name(nvp); 594 fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu "; 595 (void) nvpair_value_uint64_array(nvp, &u64p, &nelem); 596 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 597 n = snprintf(p, buflen, fmt, (u_longlong_t)u64p[i]); 598 if ((n < 0) || (n >= buflen)) 599 return (_zed_event_add_array_err(eid, name)); 600 p += n; 601 buflen -= n; 602 } 603 if (nelem > 0) 604 *--p = '\0'; 605 606 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 607 } 608 609 static int 610 _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp, 611 const char *prefix, nvpair_t *nvp) 612 { 613 char buf[MAXBUF]; 614 int buflen = sizeof (buf); 615 const char *name; 616 const char **strp; 617 uint_t nelem; 618 uint_t i; 619 char *p; 620 int n; 621 622 assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY)); 623 624 name = nvpair_name(nvp); 625 (void) nvpair_value_string_array(nvp, &strp, &nelem); 626 for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) { 627 n = snprintf(p, buflen, "%s ", strp[i] ? strp[i] : "<NULL>"); 628 if ((n < 0) || (n >= buflen)) 629 return (_zed_event_add_array_err(eid, name)); 630 p += n; 631 buflen -= n; 632 } 633 if (nelem > 0) 634 *--p = '\0'; 635 636 return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf)); 637 } 638 639 /* 640 * Convert the nvpair [nvp] to a string which is added to the environment 641 * of the child process. 642 * Return 0 on success, -1 on error. 643 */ 644 static void 645 _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp) 646 { 647 const char *name; 648 data_type_t type; 649 const char *prefix = ZEVENT_VAR_PREFIX; 650 boolean_t b; 651 double d; 652 uint8_t i8; 653 uint16_t i16; 654 uint32_t i32; 655 uint64_t i64; 656 const char *str; 657 658 assert(zsp != NULL); 659 assert(nvp != NULL); 660 661 name = nvpair_name(nvp); 662 type = nvpair_type(nvp); 663 664 switch (type) { 665 case DATA_TYPE_BOOLEAN: 666 _zed_event_add_var(eid, zsp, prefix, name, "%s", "1"); 667 break; 668 case DATA_TYPE_BOOLEAN_VALUE: 669 (void) nvpair_value_boolean_value(nvp, &b); 670 _zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0"); 671 break; 672 case DATA_TYPE_BYTE: 673 (void) nvpair_value_byte(nvp, &i8); 674 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); 675 break; 676 case DATA_TYPE_INT8: 677 (void) nvpair_value_int8(nvp, (int8_t *)&i8); 678 _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); 679 break; 680 case DATA_TYPE_UINT8: 681 (void) nvpair_value_uint8(nvp, &i8); 682 _zed_event_add_var(eid, zsp, prefix, name, "%u", i8); 683 break; 684 case DATA_TYPE_INT16: 685 (void) nvpair_value_int16(nvp, (int16_t *)&i16); 686 _zed_event_add_var(eid, zsp, prefix, name, "%d", i16); 687 break; 688 case DATA_TYPE_UINT16: 689 (void) nvpair_value_uint16(nvp, &i16); 690 _zed_event_add_var(eid, zsp, prefix, name, "%u", i16); 691 break; 692 case DATA_TYPE_INT32: 693 (void) nvpair_value_int32(nvp, (int32_t *)&i32); 694 _zed_event_add_var(eid, zsp, prefix, name, "%d", i32); 695 break; 696 case DATA_TYPE_UINT32: 697 (void) nvpair_value_uint32(nvp, &i32); 698 _zed_event_add_var(eid, zsp, prefix, name, "%u", i32); 699 break; 700 case DATA_TYPE_INT64: 701 (void) nvpair_value_int64(nvp, (int64_t *)&i64); 702 _zed_event_add_var(eid, zsp, prefix, name, 703 "%lld", (longlong_t)i64); 704 break; 705 case DATA_TYPE_UINT64: 706 (void) nvpair_value_uint64(nvp, &i64); 707 _zed_event_add_var(eid, zsp, prefix, name, 708 (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"), 709 (u_longlong_t)i64); 710 /* 711 * shadow readable strings for vdev state pairs 712 */ 713 if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 || 714 strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) { 715 char alt[32]; 716 717 (void) snprintf(alt, sizeof (alt), "%s_str", name); 718 _zed_event_add_var(eid, zsp, prefix, alt, "%s", 719 zpool_state_to_name(i64, VDEV_AUX_NONE)); 720 } else 721 /* 722 * shadow readable strings for pool state 723 */ 724 if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_POOL_STATE) == 0) { 725 char alt[32]; 726 727 (void) snprintf(alt, sizeof (alt), "%s_str", name); 728 _zed_event_add_var(eid, zsp, prefix, alt, "%s", 729 zpool_pool_state_to_name(i64)); 730 } 731 break; 732 case DATA_TYPE_DOUBLE: 733 (void) nvpair_value_double(nvp, &d); 734 _zed_event_add_var(eid, zsp, prefix, name, "%g", d); 735 break; 736 case DATA_TYPE_HRTIME: 737 (void) nvpair_value_hrtime(nvp, (hrtime_t *)&i64); 738 _zed_event_add_var(eid, zsp, prefix, name, 739 "%llu", (u_longlong_t)i64); 740 break; 741 case DATA_TYPE_STRING: 742 (void) nvpair_value_string(nvp, &str); 743 _zed_event_add_var(eid, zsp, prefix, name, 744 "%s", (str ? str : "<NULL>")); 745 break; 746 case DATA_TYPE_INT8_ARRAY: 747 _zed_event_add_int8_array(eid, zsp, prefix, nvp); 748 break; 749 case DATA_TYPE_UINT8_ARRAY: 750 _zed_event_add_uint8_array(eid, zsp, prefix, nvp); 751 break; 752 case DATA_TYPE_INT16_ARRAY: 753 _zed_event_add_int16_array(eid, zsp, prefix, nvp); 754 break; 755 case DATA_TYPE_UINT16_ARRAY: 756 _zed_event_add_uint16_array(eid, zsp, prefix, nvp); 757 break; 758 case DATA_TYPE_INT32_ARRAY: 759 _zed_event_add_int32_array(eid, zsp, prefix, nvp); 760 break; 761 case DATA_TYPE_UINT32_ARRAY: 762 _zed_event_add_uint32_array(eid, zsp, prefix, nvp); 763 break; 764 case DATA_TYPE_INT64_ARRAY: 765 _zed_event_add_int64_array(eid, zsp, prefix, nvp); 766 break; 767 case DATA_TYPE_UINT64_ARRAY: 768 _zed_event_add_uint64_array(eid, zsp, prefix, nvp); 769 break; 770 case DATA_TYPE_STRING_ARRAY: 771 _zed_event_add_string_array(eid, zsp, prefix, nvp); 772 break; 773 case DATA_TYPE_NVLIST: 774 case DATA_TYPE_BOOLEAN_ARRAY: 775 case DATA_TYPE_BYTE_ARRAY: 776 case DATA_TYPE_NVLIST_ARRAY: 777 _zed_event_add_var(eid, zsp, prefix, name, "_NOT_IMPLEMENTED_"); 778 break; 779 default: 780 errno = EINVAL; 781 zed_log_msg(LOG_WARNING, 782 "Failed to convert nvpair \"%s\" for eid=%llu: " 783 "Unrecognized type=%u", name, eid, (unsigned int) type); 784 break; 785 } 786 } 787 788 /* 789 * Restrict various environment variables to safe and sane values 790 * when constructing the environment for the child process, unless 791 * we're running with a custom $PATH (like under the ZFS test suite). 792 * 793 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1. 794 */ 795 static void 796 _zed_event_add_env_restrict(uint64_t eid, zed_strings_t *zsp, 797 const char *path) 798 { 799 const char *env_restrict[][2] = { 800 { "IFS", " \t\n" }, 801 { "PATH", _PATH_STDPATH }, 802 { "ZDB", SBINDIR "/zdb" }, 803 { "ZED", SBINDIR "/zed" }, 804 { "ZFS", SBINDIR "/zfs" }, 805 { "ZINJECT", SBINDIR "/zinject" }, 806 { "ZPOOL", SBINDIR "/zpool" }, 807 { "ZFS_ALIAS", ZFS_META_ALIAS }, 808 { "ZFS_VERSION", ZFS_META_VERSION }, 809 { "ZFS_RELEASE", ZFS_META_RELEASE }, 810 { NULL, NULL } 811 }; 812 813 /* 814 * If we have a custom $PATH, use the default ZFS binary locations 815 * instead of the hard-coded ones. 816 */ 817 const char *env_path[][2] = { 818 { "IFS", " \t\n" }, 819 { "PATH", NULL }, /* $PATH copied in later on */ 820 { "ZDB", "zdb" }, 821 { "ZED", "zed" }, 822 { "ZFS", "zfs" }, 823 { "ZINJECT", "zinject" }, 824 { "ZPOOL", "zpool" }, 825 { "ZFS_ALIAS", ZFS_META_ALIAS }, 826 { "ZFS_VERSION", ZFS_META_VERSION }, 827 { "ZFS_RELEASE", ZFS_META_RELEASE }, 828 { NULL, NULL } 829 }; 830 const char *(*pa)[2]; 831 832 assert(zsp != NULL); 833 834 pa = path != NULL ? env_path : env_restrict; 835 836 for (; *(*pa); pa++) { 837 /* Use our custom $PATH if we have one */ 838 if (path != NULL && strcmp((*pa)[0], "PATH") == 0) 839 (*pa)[1] = path; 840 841 _zed_event_add_var(eid, zsp, NULL, (*pa)[0], "%s", (*pa)[1]); 842 } 843 } 844 845 /* 846 * Preserve specified variables from the parent environment 847 * when constructing the environment for the child process. 848 * 849 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1. 850 */ 851 static void 852 _zed_event_add_env_preserve(uint64_t eid, zed_strings_t *zsp) 853 { 854 const char *env_preserve[] = { 855 "TZ", 856 NULL 857 }; 858 const char **keyp; 859 const char *val; 860 861 assert(zsp != NULL); 862 863 for (keyp = env_preserve; *keyp; keyp++) { 864 if ((val = getenv(*keyp))) 865 _zed_event_add_var(eid, zsp, NULL, *keyp, "%s", val); 866 } 867 } 868 869 /* 870 * Compute the "subclass" by removing the first 3 components of [class] 871 * (which will always be of the form "*.fs.zfs"). Return a pointer inside 872 * the string [class], or NULL if insufficient components exist. 873 */ 874 static const char * 875 _zed_event_get_subclass(const char *class) 876 { 877 const char *p; 878 int i; 879 880 if (!class) 881 return (NULL); 882 883 p = class; 884 for (i = 0; i < 3; i++) { 885 p = strchr(p, '.'); 886 if (!p) 887 break; 888 p++; 889 } 890 return (p); 891 } 892 893 /* 894 * Convert the zevent time from a 2-element array of 64b integers 895 * into a more convenient form: 896 * - TIME_SECS is the second component of the time. 897 * - TIME_NSECS is the nanosecond component of the time. 898 * - TIME_STRING is an almost-RFC3339-compliant string representation. 899 */ 900 static void 901 _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[]) 902 { 903 struct tm stp; 904 char buf[32]; 905 906 assert(zsp != NULL); 907 assert(etime != NULL); 908 909 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS", 910 "%" PRId64, etime[0]); 911 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS", 912 "%" PRId64, etime[1]); 913 914 if (!localtime_r((const time_t *) &etime[0], &stp)) { 915 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s", 916 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error"); 917 } else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", &stp)) { 918 zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s", 919 ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error"); 920 } else { 921 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_STRING", 922 "%s", buf); 923 } 924 } 925 926 927 static void 928 _zed_event_update_enc_sysfs_path(nvlist_t *nvl) 929 { 930 const char *vdev_path; 931 932 if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH, 933 &vdev_path) != 0) { 934 return; /* some other kind of event, ignore it */ 935 } 936 937 if (vdev_path == NULL) { 938 return; 939 } 940 941 update_vdev_config_dev_sysfs_path(nvl, vdev_path, 942 FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH); 943 } 944 945 /* 946 * Service the next zevent, blocking until one is available. 947 */ 948 int 949 zed_event_service(struct zed_conf *zcp) 950 { 951 nvlist_t *nvl; 952 nvpair_t *nvp; 953 int n_dropped; 954 zed_strings_t *zsp; 955 uint64_t eid; 956 int64_t *etime; 957 uint_t nelem; 958 const char *class; 959 const char *subclass; 960 int rv; 961 962 if (!zcp) { 963 errno = EINVAL; 964 zed_log_msg(LOG_ERR, "Failed to service zevent: %s", 965 strerror(errno)); 966 return (EINVAL); 967 } 968 rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE, 969 zcp->zevent_fd); 970 971 if ((rv != 0) || !nvl) 972 return (errno); 973 974 if (n_dropped > 0) { 975 zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped); 976 _bump_event_queue_length(); 977 } 978 if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) { 979 zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid"); 980 } else if (nvlist_lookup_int64_array( 981 nvl, "time", &etime, &nelem) != 0) { 982 zed_log_msg(LOG_WARNING, 983 "Failed to lookup zevent time (eid=%llu)", eid); 984 } else if (nelem != 2) { 985 zed_log_msg(LOG_WARNING, 986 "Failed to lookup zevent time (eid=%llu, nelem=%u)", 987 eid, nelem); 988 } else if (nvlist_lookup_string(nvl, "class", &class) != 0) { 989 zed_log_msg(LOG_WARNING, 990 "Failed to lookup zevent class (eid=%llu)", eid); 991 } else { 992 /* 993 * Special case: If we can dynamically detect an enclosure sysfs 994 * path, then use that value rather than the one stored in the 995 * vd->vdev_enc_sysfs_path. There have been rare cases where 996 * vd->vdev_enc_sysfs_path becomes outdated. However, there 997 * will be other times when we can not dynamically detect the 998 * sysfs path (like if a disk disappears) and have to rely on 999 * the old value for things like turning on the fault LED. 1000 */ 1001 _zed_event_update_enc_sysfs_path(nvl); 1002 1003 /* let internal modules see this event first */ 1004 zfs_agent_post_event(class, NULL, nvl); 1005 1006 zsp = zed_strings_create(); 1007 1008 nvp = NULL; 1009 while ((nvp = nvlist_next_nvpair(nvl, nvp))) 1010 _zed_event_add_nvpair(eid, zsp, nvp); 1011 1012 _zed_event_add_env_restrict(eid, zsp, zcp->path); 1013 _zed_event_add_env_preserve(eid, zsp); 1014 1015 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "PID", 1016 "%d", (int)getpid()); 1017 _zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "ZEDLET_DIR", 1018 "%s", zcp->zedlet_dir); 1019 subclass = _zed_event_get_subclass(class); 1020 _zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "SUBCLASS", 1021 "%s", (subclass ? subclass : class)); 1022 1023 _zed_event_add_time_strings(eid, zsp, etime); 1024 1025 zed_exec_process(eid, class, subclass, zcp, zsp); 1026 1027 zed_conf_write_state(zcp, eid, etime); 1028 1029 zed_strings_destroy(zsp); 1030 } 1031 nvlist_free(nvl); 1032 return (0); 1033 } 1034