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