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