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