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