1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <fcntl.h> 5 #include <stropts.h> 6 #include <poll.h> 7 #include <string.h> 8 #include <sys/fs/zev.h> 9 #include <errno.h> 10 #include <sys/sysmacros.h> 11 #include <stdarg.h> 12 #include <sys/avl.h> 13 #include <sys/stat.h> 14 15 #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 16 17 #if !defined(offsetof) 18 #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) 19 #endif 20 21 static char *zev_device = ZEV_DEVICE; 22 23 static char *zev_op_name[] = { 24 "ERROR", 25 "MARK", 26 "ZFS_MOUNT", 27 "ZFS_UMOUNT", 28 "ZVOL_WRITE", 29 "ZVOL_TRUNCATE", 30 "ZNODE_CLOSE_AFTER_UPDATE", 31 "ZNODE_CREATE", 32 "ZNODE_MKDIR", 33 "ZNODE_MAKE_XATTR_DIR", 34 "ZNODE_REMOVE", 35 "ZNODE_RMDIR", 36 "ZNODE_LINK", 37 "ZNODE_SYMLINK", 38 "ZNODE_RENAME", 39 "ZNODE_WRITE", 40 "ZNODE_TRUNCATE", 41 "ZNODE_SETATTR", 42 "ZNODE_ACL", 43 NULL 44 }; 45 46 #define MD_STATISTICS 1 47 #define MD_POLL_EVENTS 2 48 #define MD_CHECKSUMS 3 49 #define MD_DEBUG_INFO 4 50 #define MD_LIST_QUEUES 5 51 #define MD_SET_GLOBAL_MAX_QUEUE_LEN 6 52 #define MD_SET_MAX_QUEUE_LEN 7 53 #define MD_SET_POLL_WAKEUP_QUEUE_LEN 8 54 #define MD_MUTE_POOL 9 55 #define MD_UNMUTE_POOL 10 56 #define MD_MARK 11 57 #define MD_ADD_QUEUE 12 58 #define MD_ADD_BLOCKING_QUEUE 13 59 #define MD_REMOVE_QUEUE 14 60 #define MD_QUEUE_BLOCKING 15 61 #define MD_QUEUE_NONBLOCKING 16 62 #define MD_QUEUE_PROPERTIES 17 63 #define MD_ZEVSTAT 18 64 #define MD_ZEV_REPORT 19 65 66 static int verbose = 0; 67 static int grep_friendly = 0; 68 69 static void 70 zpf(char *fmt, ...) 71 { 72 va_list ap; 73 74 va_start(ap, fmt); 75 vprintf(fmt, ap); 76 va_end(ap); 77 if (grep_friendly) { 78 printf(" "); 79 } else { 80 printf("\n"); 81 } 82 } 83 84 static void 85 znl(void) 86 { 87 if (grep_friendly) 88 printf("\n"); 89 } 90 91 static void 92 sig2hex_direct(const uint8_t *sig, char *hex) 93 { 94 int i; 95 96 for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 97 sprintf(hex + 2 * i, "%02x", sig[i]); 98 } 99 hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 100 } 101 102 static int 103 zev_statistics(int fd) 104 { 105 zev_statistics_t zs; 106 if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 107 perror("getting statistics data failed"); 108 return (EXIT_FAILURE); 109 } 110 printf("ZEV module state:\n"); 111 112 printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 113 printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 114 printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 115 printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 116 117 printf(" discarded events : %lu\n", 118 zs.zev_cnt_discarded_events); 119 printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 120 121 printf("ZFS event statistics:\n"); 122 123 printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 124 printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 125 printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 126 printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 127 printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 128 printf(" ZNODE close after update: %lu\n", 129 zs.zev_cnt_znode_close_after_update); 130 printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 131 printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 132 printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 133 printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 134 printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 135 printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 136 printf(" ZNODE truncate : %lu\n", 137 zs.zev_cnt_znode_truncate); 138 printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 139 printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 140 return EXIT_SUCCESS; 141 } 142 143 static void 144 zev_print_inode_info(char *name, zev_inode_info_t *info) 145 { 146 zpf(" %s.inode: %llu", name, info->ino); 147 zpf(" %s.gen: %llu", name, info->gen); 148 zpf(" %s.mtime: %llu", name, info->mtime); 149 zpf(" %s.ctime: %llu", name, info->ctime); 150 zpf(" %s.size: %llu", name, info->size); 151 zpf(" %s.mode: %llo", name, info->mode); 152 zpf(" %s.links: %llu", name, info->links); 153 zpf(" %s.type: %lu", name, info->type); 154 zpf(" %s.flags: %lu", name, info->flags); 155 } 156 157 static void 158 zev_print_mark_payload(zev_mark_t *rec) 159 { 160 int i; 161 int j; 162 uint8_t *p; 163 char c; 164 165 zpf(" payload:"); 166 p = (uint8_t *)ZEV_PAYLOAD(rec); 167 for (i=0; i<rec->payload_len; i+=16) { 168 printf(" "); 169 for (j=i; j<rec->payload_len && j<i+16; j++) { 170 printf("%02x ", p[j]); 171 if (j == i + 7) 172 printf(" "); 173 } 174 if (grep_friendly) 175 continue; 176 for (; j<i+16; j++) { 177 printf(" "); 178 if (j == i + 7) 179 printf(" "); 180 } 181 printf(" "); 182 for (j=i; j<rec->payload_len && j<i+16; j++) { 183 c = '.'; 184 if (p[j] >= ' ' && p[j] <= '~') 185 c = p[j]; 186 printf("%c", c); 187 if (j == i + 7) 188 printf(" "); 189 } 190 printf("\n"); 191 } 192 } 193 194 static void 195 zev_print_error(char *buf) 196 { 197 zev_error_t *rec = (zev_error_t *)buf; 198 time_t op_time = rec->op_time; 199 char *ct = ctime(&op_time); ct[24] = '\0'; 200 201 if (verbose) { 202 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 203 zpf(" guid: %llu", rec->guid); 204 zpf(" failed.op: %s", 205 zev_op_name[rec->failed_op - ZEV_OP_MIN]); 206 zpf(" message: %s", ZEV_ERRSTR(rec)); 207 znl(); 208 } else { 209 printf("%s %s: failed_op=%s msg=%s\n", 210 ct, zev_op_name[rec->op - ZEV_OP_MIN], 211 zev_op_name[rec->failed_op - ZEV_OP_MIN], 212 ZEV_ERRSTR(rec)); 213 } 214 } 215 216 static void 217 zev_print_mark(char *buf) 218 { 219 zev_mark_t *rec = (zev_mark_t *)buf; 220 time_t op_time = rec->op_time; 221 char *ct = ctime(&op_time); ct[24] = '\0'; 222 223 if (verbose) { 224 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 225 zpf(" guid: %llu", rec->guid); 226 zpf(" mark.id: %llu", rec->mark_id); 227 zpf(" payload.len: %llu", rec->payload_len); 228 if (rec->payload_len) 229 zev_print_mark_payload(rec); 230 znl(); 231 } else { 232 printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 233 ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 234 rec->mark_id, rec->payload_len); 235 } 236 } 237 238 static void 239 zev_print_zfs_mount(char *buf) 240 { 241 zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 242 time_t op_time = rec->op_time; 243 char *ct = ctime(&op_time); ct[24] = '\0'; 244 245 if (verbose) { 246 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 247 zpf(" guid: %llu", rec->guid); 248 zpf(" dataset: %s", ZEV_DATASET(rec)); 249 zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 250 zpf(" remount: %s", rec->remount ? "true" : "false"); 251 zev_print_inode_info("root", &rec->root); 252 znl(); 253 } else { 254 printf("%s %s: guid=%llu remount=%s dataset='%s' " 255 "mountpoint='%s'\n", 256 ct, zev_op_name[rec->op - ZEV_OP_MIN], 257 rec->guid, 258 rec->remount ? "true" : "false", 259 ZEV_DATASET(rec), 260 ZEV_MOUNTPOINT(rec)); 261 } 262 } 263 264 static void 265 zev_print_zfs_umount(char *buf) 266 { 267 zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 268 time_t op_time = rec->op_time; 269 char *ct = ctime(&op_time); ct[24] = '\0'; 270 271 if (verbose) { 272 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 273 zpf(" guid: %llu", rec->guid); 274 zev_print_inode_info("covered", &rec->covered); 275 znl(); 276 } else { 277 printf("%s %s: guid=%llu\n", 278 ct, zev_op_name[rec->op - ZEV_OP_MIN], 279 rec->guid); 280 } 281 } 282 283 static void 284 zev_print_zvol_truncate(char *buf) 285 { 286 zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 287 time_t op_time = rec->op_time; 288 char *ct = ctime(&op_time); ct[24] = '\0'; 289 290 if (verbose) { 291 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 292 zpf(" guid: %llu", rec->guid); 293 zpf(" txg: %llu", rec->txg); 294 zpf(" offset: %llu", rec->offset); 295 zpf(" length: %llu", rec->length); 296 znl(); 297 } else { 298 printf("%s %s: guid=%llu offset=%llu length=%llu\n", 299 ct, zev_op_name[rec->op - ZEV_OP_MIN], 300 rec->guid, 301 rec->offset, 302 rec->length); 303 } 304 } 305 306 static void 307 zev_print_zvol_write(char *buf) 308 { 309 zev_print_zvol_truncate(buf); 310 } 311 312 static void 313 zev_print_znode_close_after_update(char *buf) 314 { 315 zev_znode_close_after_update_t *rec = 316 (zev_znode_close_after_update_t *)buf; 317 time_t op_time = rec->op_time; 318 char *ct = ctime(&op_time); ct[24] = '\0'; 319 320 if (verbose) { 321 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 322 zpf(" guid: %llu", rec->guid); 323 zev_print_inode_info("file", &rec->file); 324 znl(); 325 } else { 326 printf("%s %s: guid=%llu file=%llu.%llu\n", 327 ct, zev_op_name[rec->op - ZEV_OP_MIN], 328 rec->guid, 329 rec->file.ino, rec->file.gen); 330 } 331 } 332 333 static void 334 zev_print_znode_create(char *buf) 335 { 336 zev_znode_create_t *rec = (zev_znode_create_t *)buf; 337 time_t op_time = rec->op_time; 338 char *ct = ctime(&op_time); ct[24] = '\0'; 339 zev_sig_t *sig; 340 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 341 342 if (verbose) { 343 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 344 zpf(" guid: %llu", rec->guid); 345 zpf(" txg: %llu", rec->txg); 346 zpf(" name: '%s'", ZEV_NAME(rec)); 347 sig = &rec->signature; 348 sig2hex_direct(sig->value, sigval); 349 zpf(" sig: level %d, offset %llu, value %s", 350 sig->level, sig->block_offset, sigval); 351 zev_print_inode_info("file", &rec->file); 352 zev_print_inode_info("parent", &rec->parent); 353 znl(); 354 } else { 355 printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 356 "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 357 ct, zev_op_name[rec->op - ZEV_OP_MIN], 358 rec->guid, 359 rec->parent.ino, rec->parent.gen, 360 rec->file.ino, rec->file.gen, 361 rec->file.mtime, rec->parent.mtime, 362 ZEV_NAME(rec)); 363 } 364 } 365 366 static void 367 zev_print_znode_mkdir(char *buf) 368 { 369 zev_print_znode_create(buf); 370 } 371 372 static void 373 zev_print_znode_make_xattr_dir(char *buf) 374 { 375 zev_print_znode_create(buf); 376 } 377 378 static void 379 zev_print_znode_remove(char *buf) 380 { 381 zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 382 time_t op_time = rec->op_time; 383 char *ct = ctime(&op_time); ct[24] = '\0'; 384 385 if (verbose) { 386 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 387 zpf(" guid: %llu", rec->guid); 388 zpf(" txg: %llu", rec->txg); 389 zpf(" file.name: '%s'", ZEV_NAME(rec)); 390 zev_print_inode_info("file", &rec->file); 391 zev_print_inode_info("parent", &rec->parent); 392 znl(); 393 } else { 394 printf("%s %s: guid=%llu parent=%llu.%llu " 395 "file.mtime=%llu name='%s'\n", 396 ct, zev_op_name[rec->op - ZEV_OP_MIN], 397 rec->guid, 398 rec->parent.ino, rec->parent.gen, 399 rec->file.mtime, 400 ZEV_NAME(rec)); 401 } 402 } 403 404 static void 405 zev_print_znode_rmdir(char *buf) 406 { 407 zev_print_znode_remove(buf); 408 } 409 410 static void 411 zev_print_znode_link(char *buf) 412 { 413 zev_znode_link_t *rec = (zev_znode_link_t *)buf; 414 time_t op_time = rec->op_time; 415 char *ct = ctime(&op_time); ct[24] = '\0'; 416 417 if (verbose) { 418 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 419 zpf(" guid: %llu", rec->guid); 420 zpf(" txg: %llu", rec->txg); 421 zpf(" link.name: '%s'", ZEV_NAME(rec)); 422 zev_print_inode_info("file", &rec->file); 423 zev_print_inode_info("parent", &rec->parent); 424 znl(); 425 } else { 426 printf("%s %s: parent=%llu.%llu file=%llu.%llu " 427 "file.ctime=%llu parent.ctime=%llu name='%s'\n", 428 ct, zev_op_name[rec->op - ZEV_OP_MIN], 429 rec->parent.ino, rec->parent.gen, 430 rec->file.ino, rec->file.gen, 431 rec->file.ctime, rec->parent.ctime, 432 ZEV_NAME(rec)); 433 } 434 } 435 436 static void 437 zev_print_znode_symlink(char *buf) 438 { 439 zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 440 time_t op_time = rec->op_time; 441 char *ct = ctime(&op_time); ct[24] = '\0'; 442 zev_sig_t *sig; 443 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 444 445 if (verbose) { 446 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 447 zpf(" guid: %llu", rec->guid); 448 zpf(" txg: %llu", rec->txg); 449 zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 450 zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 451 sig = &rec->signature; 452 sig2hex_direct(sig->value, sigval); 453 zpf(" sig: level %d, offset %llu, value %s", 454 sig->level, sig->block_offset, sigval); 455 zev_print_inode_info("file", &rec->file); 456 zev_print_inode_info("parent", &rec->parent); 457 znl(); 458 } else { 459 printf("%s %s: parent=%llu.%llu file=%llu.%llu " 460 "name='%s' link='%s'\n", 461 ct, zev_op_name[rec->op - ZEV_OP_MIN], 462 rec->parent.ino, rec->parent.gen, 463 rec->file.ino, rec->file.gen, 464 ZEV_NAME(rec), 465 ZEV_LINK(rec)); 466 } 467 } 468 469 static void 470 zev_print_znode_rename(char *buf) 471 { 472 zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 473 time_t op_time = rec->op_time; 474 char *ct = ctime(&op_time); ct[24] = '\0'; 475 476 if (verbose) { 477 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 478 zpf(" guid: %llu", rec->guid); 479 zpf(" txg: %llu", rec->txg); 480 zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 481 zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 482 zev_print_inode_info("file", &rec->file); 483 if (rec->clobbered_file.ino) 484 zev_print_inode_info("clobbered_file", 485 &rec->clobbered_file); 486 zev_print_inode_info("srcdir", &rec->srcdir); 487 zev_print_inode_info("dstdir", &rec->dstdir); 488 znl(); 489 } else { 490 printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 491 "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 492 "srcdir.mtime=%llu, srcdir.ctime=%llu, " 493 "dstdir.mtime=%llu, dstdir.ctime=%llu, " 494 "srcname='%s' dstname='%s'\n", 495 ct, zev_op_name[rec->op - ZEV_OP_MIN], 496 rec->srcdir.ino, rec->srcdir.gen, 497 rec->dstdir.ino, rec->dstdir.gen, 498 rec->file.ino, rec->file.gen, 499 rec->file.mtime, rec->file.ctime, 500 rec->srcdir.mtime, rec->srcdir.ctime, 501 rec->dstdir.mtime, rec->dstdir.ctime, 502 ZEV_SRCNAME(rec), 503 ZEV_DSTNAME(rec)); 504 } 505 } 506 507 static void 508 zev_print_znode_write(char *buf) 509 { 510 zev_znode_write_t *rec = (zev_znode_write_t *)buf; 511 time_t op_time = rec->op_time; 512 char *ct = ctime(&op_time); ct[24] = '\0'; 513 zev_sig_t *sig; 514 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 515 int i; 516 517 if (verbose) { 518 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 519 zpf(" guid: %llu", rec->guid); 520 zpf(" txg: %llu", rec->txg); 521 zpf(" offset: %llu", rec->offset); 522 zpf(" length: %llu", rec->length); 523 zev_print_inode_info("file", &rec->file); 524 znl(); 525 for (i=0; i<rec->signature_cnt; i++) { 526 sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 527 sig += i; 528 sig2hex_direct(sig->value, sigval); 529 zpf(" sig: level %d, offset %llu, value %s", 530 sig->level, sig->block_offset, sigval); 531 } 532 } else { 533 printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 534 ct, zev_op_name[rec->op - ZEV_OP_MIN], 535 rec->file.ino, rec->file.gen, 536 rec->offset, rec->length); 537 } 538 } 539 540 static void 541 zev_print_znode_truncate(char *buf) 542 { 543 zev_print_znode_write(buf); 544 } 545 546 static void 547 zev_print_znode_setattr(char *buf) 548 { 549 zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 550 time_t op_time = rec->op_time; 551 char *ct = ctime(&op_time); ct[24] = '\0'; 552 553 if (verbose) { 554 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 555 zpf(" guid: %llu", rec->guid); 556 zpf(" txg: %llu", rec->txg); 557 zev_print_inode_info("file", &rec->file); 558 znl(); 559 } else { 560 printf("%s %s: file=%llu.%llu mtime=%llu\n", 561 ct, zev_op_name[rec->op - ZEV_OP_MIN], 562 rec->file.ino, rec->file.gen, rec->file.mtime); 563 } 564 } 565 566 static void 567 zev_print_znode_acl(char *buf) 568 { 569 zev_print_znode_setattr(buf); 570 } 571 572 static void 573 zev_print_event(char *buf, int len) 574 { 575 int record_len; 576 int op; 577 578 record_len = *(uint32_t *)buf; 579 if (record_len != len) { 580 fprintf(stderr, "record length mismatch: got %d, expected %d\n", 581 record_len, len); 582 exit(1); 583 } 584 op = *((uint32_t *)buf + 1); 585 if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 586 fprintf(stderr, "unknown op code: %d\n", op); 587 exit(1); 588 } 589 switch (op) { 590 case ZEV_OP_ERROR: 591 zev_print_error(buf); 592 break; 593 case ZEV_OP_MARK: 594 zev_print_mark(buf); 595 break; 596 case ZEV_OP_ZFS_MOUNT: 597 zev_print_zfs_mount(buf); 598 break; 599 case ZEV_OP_ZFS_UMOUNT: 600 zev_print_zfs_umount(buf); 601 break; 602 case ZEV_OP_ZVOL_TRUNCATE: 603 zev_print_zvol_truncate(buf); 604 break; 605 case ZEV_OP_ZVOL_WRITE: 606 zev_print_zvol_write(buf); 607 break; 608 case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 609 zev_print_znode_close_after_update(buf); 610 break; 611 case ZEV_OP_ZNODE_CREATE: 612 zev_print_znode_create(buf); 613 break; 614 case ZEV_OP_ZNODE_MKDIR: 615 zev_print_znode_mkdir(buf); 616 break; 617 case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 618 zev_print_znode_make_xattr_dir(buf); 619 break; 620 case ZEV_OP_ZNODE_REMOVE: 621 zev_print_znode_remove(buf); 622 break; 623 case ZEV_OP_ZNODE_RMDIR: 624 zev_print_znode_rmdir(buf); 625 break; 626 case ZEV_OP_ZNODE_LINK: 627 zev_print_znode_link(buf); 628 break; 629 case ZEV_OP_ZNODE_SYMLINK: 630 zev_print_znode_symlink(buf); 631 break; 632 case ZEV_OP_ZNODE_RENAME: 633 zev_print_znode_rename(buf); 634 break; 635 case ZEV_OP_ZNODE_WRITE: 636 zev_print_znode_write(buf); 637 break; 638 case ZEV_OP_ZNODE_TRUNCATE: 639 zev_print_znode_truncate(buf); 640 break; 641 case ZEV_OP_ZNODE_SETATTR: 642 zev_print_znode_setattr(buf); 643 break; 644 case ZEV_OP_ZNODE_ACL: 645 zev_print_znode_acl(buf); 646 break; 647 default: 648 fprintf(stderr, "unhandled op code: %d\n", op); 649 exit(1); 650 } 651 } 652 653 static int 654 zev_poll_events(int fd, int create_tmp_queue) 655 { 656 struct pollfd pfd[1]; 657 int ret; 658 char buf[4096]; 659 zev_event_t *ev; 660 int off = 0; 661 zev_ioctl_add_queue_t aq; 662 int q_fd; 663 664 if (create_tmp_queue) { 665 aq.zev_max_queue_len = 0; 666 aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 667 snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 668 "zevadm.%ld.%ld", time(NULL), getpid()); 669 aq.zev_namelen = strlen(aq.zev_name); 670 671 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 672 perror("adding temporary queue failed"); 673 return (EXIT_FAILURE); 674 } 675 676 snprintf(buf, sizeof(buf), 677 "/devices/pseudo/zev@0:%s", aq.zev_name); 678 q_fd = open(buf, O_RDONLY); 679 if (q_fd < 0) { 680 perror("opening queue device failed"); 681 return (EXIT_FAILURE); 682 } 683 } else { 684 q_fd = fd; 685 } 686 687 while (1) { 688 pfd[0].fd = q_fd; 689 pfd[0].events = POLLIN; 690 ret = poll(pfd, 1, 1000); 691 if (ret < 0) { 692 perror("poll failed"); 693 close(q_fd); 694 return(EXIT_FAILURE); 695 } 696 if (!(pfd[0].revents & POLLIN)) 697 continue; 698 /* data available */ 699 ret = read(q_fd, buf, sizeof(buf)); 700 if (ret < 0) { 701 perror("read failed"); 702 close(q_fd); 703 return(EXIT_FAILURE); 704 } 705 if (ret == 0) 706 continue; 707 while (ret > off) { 708 ev = (zev_event_t *)(buf + off); 709 zev_print_event(buf + off, ev->header.record_len); 710 off += ev->header.record_len; 711 } 712 off = 0; 713 } 714 if (create_tmp_queue) 715 close(q_fd); 716 return EXIT_SUCCESS; 717 } 718 719 static void 720 usage(char *progname) 721 { 722 fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 723 fprintf(stderr, "\n"); 724 fprintf(stderr, " Status information:\n"); 725 fprintf(stderr, " -s show zev statistics\n"); 726 fprintf(stderr, " -p poll for ZFS events\n"); 727 fprintf(stderr, " -D print zev module debug " 728 "information\n"); 729 fprintf(stderr, " -T <interval> <cnt> zevstat mode\n"); 730 fprintf(stderr, " -R <base filename> zevreport mode\n"); 731 fprintf(stderr, "\n"); 732 fprintf(stderr, " Tune zev module settings:\n"); 733 fprintf(stderr, " -Q <bytes> set maximum event queue " 734 "length\n"); 735 fprintf(stderr, " -m <pool> mute pool, no events for " 736 "this pool\n"); 737 fprintf(stderr, " -M <pool> unmute pool\n"); 738 fprintf(stderr, "\n"); 739 fprintf(stderr, " Queue management:\n"); 740 fprintf(stderr, " -l list queues\n"); 741 fprintf(stderr, " -a <name> add non-blocking queue\n"); 742 fprintf(stderr, " -A <name> add blocking queue\n"); 743 fprintf(stderr, " -r <name> remove queue\n"); 744 fprintf(stderr, " -b <name> make queue non-blocking " 745 "(default)\n"); 746 fprintf(stderr, " -B <name> make queue block when full\n"); 747 fprintf(stderr, " -P <name> display queue properties\n"); 748 fprintf(stderr, " -L <name> <bytes> set maximum event queue " 749 "length\n"); 750 fprintf(stderr, " -t <name> <bytes> set queue length poll " 751 "throttle\n"); 752 fprintf(stderr, "\n"); 753 fprintf(stderr, " Other options:\n"); 754 fprintf(stderr, " -d <dev> non-default device file. " 755 "('%s')\n", ZEV_DEVICE); 756 fprintf(stderr, " -q <name> use device file for this " 757 "queue name\n"); 758 fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 759 fprintf(stderr, " -c <filename> list file's content " 760 "checksums\n"); 761 fprintf(stderr, " -v verbose: additional output " 762 "for some operations\n"); 763 fprintf(stderr, " -g grep-friendly event output, " 764 "one event per line\n"); 765 exit (EXIT_FAILURE); 766 } 767 768 static void 769 zevstat_usage(char *progname) 770 { 771 fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname); 772 fprintf(stderr, " -v verbose, show counters for all event types\n"); 773 exit (EXIT_FAILURE); 774 } 775 776 static void 777 zevreport_usage(char *progname) 778 { 779 fprintf(stderr, "usage: %s <output base filename>\n", progname); 780 exit (EXIT_FAILURE); 781 } 782 783 static int 784 zev_add_queue(int fd, char *arg, int blocking) 785 { 786 zev_ioctl_add_queue_t aq; 787 int namelen; 788 789 namelen = strlen(arg); 790 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 791 fprintf(stderr, "queue name too long: %s\n", arg); 792 return (EXIT_FAILURE); 793 } 794 795 aq.zev_namelen = namelen; 796 strcpy(aq.zev_name, arg); 797 aq.zev_flags = ZEV_FL_PERSISTENT | ZEV_FL_INITIALLY_EMPTY; 798 if (blocking) { 799 aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 800 aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 801 } else { 802 aq.zev_max_queue_len = (1024 * 1024); 803 } 804 805 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 806 perror("adding queue failed"); 807 return (EXIT_FAILURE); 808 } 809 return (0); 810 } 811 812 static int 813 zev_remove_queue(int fd, char *arg) 814 { 815 zev_ioctl_remove_queue_t aq; 816 int namelen; 817 818 namelen = strlen(arg); 819 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 820 fprintf(stderr, "queue name too long: %s\n", arg); 821 return (EXIT_FAILURE); 822 } 823 824 aq.zev_queue_name.zev_namelen = namelen; 825 strcpy(aq.zev_queue_name.zev_name, arg); 826 827 if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 828 perror("removing queue failed"); 829 return (EXIT_FAILURE); 830 } 831 return (0); 832 } 833 834 static int 835 zev_set_global_max_queue_len(int fd, char *arg) 836 { 837 uint64_t maxqueuelen; 838 839 if (!arg) { 840 fprintf(stderr, "missing queue length parameter\n"); 841 return (EXIT_FAILURE); 842 } 843 844 errno = 0; 845 maxqueuelen = strtol(arg, (char **)NULL, 10); 846 if (errno) { 847 fprintf(stderr, "invalid queue length parameter: %s\n", arg); 848 return (EXIT_FAILURE); 849 } 850 if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 851 perror("setting max queue length failed"); 852 return (EXIT_FAILURE); 853 } 854 return (0); 855 } 856 857 static int 858 zev_mute_unmute_impl(int fd, char *poolname, int mute) 859 { 860 zev_ioctl_poolarg_t pa; 861 int len; 862 int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 863 len = strlen(poolname); 864 if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 865 fprintf(stderr, "invalid poolname: %s\n", poolname); 866 return (EXIT_FAILURE); 867 } 868 strcpy(pa.zev_poolname, poolname); 869 pa.zev_poolname_len = len; 870 if (ioctl(fd, op, &pa)) { 871 perror("muting pool data failed"); 872 return (EXIT_FAILURE); 873 } 874 return (0); 875 } 876 877 int 878 zev_mute_pool(int fd, char *poolname) 879 { 880 return zev_mute_unmute_impl(fd, poolname, 1); 881 } 882 883 int 884 zev_unmute_pool(int fd, char *poolname) 885 { 886 return zev_mute_unmute_impl(fd, poolname, 0); 887 } 888 889 static int 890 zev_debug_info(int fd) 891 { 892 zev_ioctl_debug_info_t di; 893 894 if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 895 perror("getting zev debug info failed"); 896 return (EXIT_FAILURE); 897 } 898 899 printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 900 printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 901 printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 902 printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 903 return 0; 904 } 905 906 static int 907 zev_mark(int fd, char *arg) 908 { 909 zev_ioctl_mark_t *mark; 910 uint64_t guid; 911 int len; 912 char *p; 913 914 p = strchr(arg, ':'); 915 if (!p) { 916 fprintf(stderr, "expected value is <guid>:<payload>, " 917 "e.g. '123:hello'\n"); 918 exit (EXIT_FAILURE); 919 } 920 *p = '\n'; 921 p++; 922 923 errno = 0; 924 guid = strtoll(arg, (char **)NULL, 10); 925 if (errno) { 926 fprintf(stderr, "guid must be a number.\n"); 927 exit (EXIT_FAILURE); 928 } 929 930 len = strlen(p); 931 932 mark = malloc(sizeof(*mark) + len + 1); 933 if (!mark) { 934 fprintf(stderr, "can't allocate mark structure: %s\n", 935 strerror(errno)); 936 exit (EXIT_FAILURE); 937 } 938 mark->zev_guid = guid; 939 mark->zev_mark_id = 0; 940 mark->zev_payload_len = len; 941 strcpy(ZEV_PAYLOAD(mark), p); 942 943 if (ioctl(fd, ZEV_IOC_MARK, mark)) { 944 perror("queueing mark failed"); 945 return (EXIT_FAILURE); 946 } 947 948 printf("mark id: %lu\n", mark->zev_mark_id); 949 return (0); 950 } 951 952 static int 953 zev_queue_blocking(int fd, char *arg, int block) 954 { 955 zev_ioctl_get_queue_properties_t gqp; 956 957 gqp.zev_queue_name.zev_namelen = strlen(arg); 958 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 959 fprintf(stderr, "queue name too long.\n"); 960 return EXIT_FAILURE; 961 } 962 strcpy(gqp.zev_queue_name.zev_name, arg); 963 964 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 965 perror("getting queue properties failed"); 966 return (EXIT_FAILURE); 967 } 968 if (block) { 969 gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 970 } else { 971 gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 972 } 973 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 974 perror("setting queue properties failed"); 975 return (EXIT_FAILURE); 976 } 977 return (0); 978 } 979 980 static int 981 zev_set_max_queue_len(int fd, char *arg, char *len) 982 { 983 zev_ioctl_get_queue_properties_t gqp; 984 985 if (!len) { 986 fprintf(stderr, "queue size parameter missing.\n"); 987 return EXIT_FAILURE; 988 } 989 990 gqp.zev_queue_name.zev_namelen = strlen(arg); 991 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 992 fprintf(stderr, "queue name too long.\n"); 993 return EXIT_FAILURE; 994 } 995 strcpy(gqp.zev_queue_name.zev_name, arg); 996 997 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 998 perror("getting queue properties failed"); 999 return (EXIT_FAILURE); 1000 } 1001 gqp.zev_max_queue_len = atol(len); 1002 if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 1003 fprintf(stderr, "queue size parameter garbled.\n"); 1004 return (EXIT_FAILURE); 1005 } 1006 if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 1007 fprintf(stderr, "queue size parameter out of bounds.\n"); 1008 return (EXIT_FAILURE); 1009 } 1010 1011 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 1012 perror("setting queue properties failed"); 1013 return (EXIT_FAILURE); 1014 } 1015 return (0); 1016 } 1017 1018 static int 1019 zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 1020 { 1021 zev_ioctl_get_queue_properties_t gqp; 1022 1023 if (!len) { 1024 fprintf(stderr, "poll throttle parameter missing.\n"); 1025 return EXIT_FAILURE; 1026 } 1027 1028 gqp.zev_queue_name.zev_namelen = strlen(arg); 1029 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1030 fprintf(stderr, "queue name too long.\n"); 1031 return EXIT_FAILURE; 1032 } 1033 strcpy(gqp.zev_queue_name.zev_name, arg); 1034 1035 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1036 perror("getting queue properties failed"); 1037 return (EXIT_FAILURE); 1038 } 1039 gqp.zev_poll_wakeup_threshold = atol(len); 1040 if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 1041 fprintf(stderr, "poll throttle parameter garbled.\n"); 1042 return (EXIT_FAILURE); 1043 } 1044 if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 1045 fprintf(stderr, "poll throttle parameter out of bounds.\n"); 1046 return (EXIT_FAILURE); 1047 } 1048 1049 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 1050 perror("setting queue properties failed"); 1051 return (EXIT_FAILURE); 1052 } 1053 return (0); 1054 } 1055 1056 static int 1057 zev_queue_properties(int fd, char *arg) 1058 { 1059 zev_ioctl_get_queue_properties_t gqp; 1060 1061 gqp.zev_queue_name.zev_namelen = strlen(arg); 1062 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1063 fprintf(stderr, "queue name too long.\n"); 1064 return EXIT_FAILURE; 1065 } 1066 strcpy(gqp.zev_queue_name.zev_name, arg); 1067 1068 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1069 perror("getting queue properties failed"); 1070 return (EXIT_FAILURE); 1071 } 1072 1073 printf("queue : %s\n", arg); 1074 printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1075 printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1076 printf("persistent : %s\n", 1077 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1078 printf("blocking : %s\n", 1079 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1080 1081 return (0); 1082 } 1083 1084 static int 1085 zev_list_queues(int fd) 1086 { 1087 zev_ioctl_get_queue_properties_t gqp; 1088 zev_ioctl_get_queue_list_t gql; 1089 zev_ioctl_get_queue_statistics_t gs; 1090 uint64_t i; 1091 char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1092 1093 if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1094 perror("getting queue list failed"); 1095 return (EXIT_FAILURE); 1096 } 1097 1098 printf("Name Size " 1099 "Max Size Wakeup Per Block\n"); 1100 1101 for (i=0; i<gql.zev_n_queues; i++) { 1102 strncpy(name, gql.zev_queue_name[i].zev_name, 1103 ZEV_MAX_QUEUE_NAME_LEN); 1104 name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1105 1106 memcpy(gqp.zev_queue_name.zev_name, 1107 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1108 gqp.zev_queue_name.zev_namelen = 1109 gql.zev_queue_name[i].zev_namelen; 1110 1111 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1112 if (errno == ENOENT) 1113 continue; 1114 perror("getting queue properties failed"); 1115 return (EXIT_FAILURE); 1116 } 1117 1118 memcpy(gs.zev_queue_name.zev_name, 1119 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1120 gs.zev_queue_name.zev_namelen = 1121 gql.zev_queue_name[i].zev_namelen; 1122 1123 if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1124 if (errno == ENOENT) 1125 continue; 1126 perror("getting statistics data failed"); 1127 return (EXIT_FAILURE); 1128 } 1129 1130 printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1131 " %-3s %-3s\n", 1132 name, 1133 gs.zev_statistics.zev_queue_len, 1134 gqp.zev_max_queue_len, 1135 gqp.zev_poll_wakeup_threshold, 1136 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1137 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1138 "yes" : "no"); 1139 } 1140 1141 return (0); 1142 } 1143 1144 static int 1145 zev_checksum(int dev_fd, char *filename) 1146 { 1147 int fd; 1148 offset_t off; 1149 offset_t data; 1150 zev_sig_t *sig; 1151 char *buf; 1152 zev_ioctl_get_signatures_t *gs; 1153 int i; 1154 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 1155 int buf_size; 1156 1157 /* control struct, one lv1 signature and up to 256 lv0 signatures */ 1158 buf_size = (1 + 256) * sizeof(zev_sig_t); 1159 buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 1160 if (!buf) { 1161 perror("can't allocate checksum buffer"); 1162 return (EXIT_FAILURE); 1163 } 1164 1165 fd = open(filename, O_RDONLY); 1166 if (fd < 0) { 1167 perror("can't open file"); 1168 return (EXIT_FAILURE); 1169 } 1170 1171 gs = (zev_ioctl_get_signatures_t *)buf; 1172 gs->zev_fd = fd; 1173 gs->zev_bufsize = buf_size; 1174 1175 off = 0; 1176 data = 0; 1177 while (1) { 1178 errno = 0; 1179 data = llseek(fd, off, SEEK_DATA); 1180 if (data < 0) { 1181 if (errno == ENXIO) /* no more data */ 1182 break; 1183 perror("llseek failed"); 1184 goto err; 1185 } 1186 data = P2ALIGN(data, ZEV_L1_SIZE); 1187 off = data + ZEV_L1_SIZE; 1188 1189 gs->zev_offset = data; 1190 gs->zev_len = ZEV_L1_SIZE; 1191 1192 if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 1193 perror("ioctl to get signatures failed"); 1194 goto err; 1195 } 1196 1197 for (i=0; i<gs->zev_signature_cnt; i++) { 1198 sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 1199 sig += i; 1200 sig2hex_direct(sig->value, sigval); 1201 printf("level %d, offset %llu, value %s\n", 1202 sig->level, sig->block_offset, sigval); 1203 } 1204 } 1205 1206 free(buf); 1207 close(fd); 1208 return 0; 1209 err: 1210 free(buf); 1211 close(fd); 1212 return (EXIT_FAILURE); 1213 } 1214 1215 typedef struct zevstat { 1216 uint64_t ns_start; 1217 uint64_t events[ZEV_OP_MIN + ZEV_OP_MAX]; 1218 uint64_t guids; 1219 uint64_t total_events; 1220 uint64_t total_guids; 1221 avl_tree_t guids_interval; 1222 avl_tree_t guids_runtime; 1223 } zevstat_t; 1224 1225 typedef struct zev_guidtrack_t { 1226 uint64_t guid; 1227 avl_node_t avl_interval; 1228 avl_node_t avl_runtime; 1229 } zev_guidtrack_t; 1230 1231 zevstat_t zevstat; 1232 1233 static void 1234 zev_eventstat(char *buf, int len) 1235 { 1236 zev_header_t *rec = (zev_header_t *)buf; 1237 zev_guidtrack_t *gt; 1238 zev_guidtrack_t *gt_int; 1239 zev_guidtrack_t to_find; 1240 avl_index_t where; 1241 1242 zevstat.total_events++; 1243 zevstat.events[rec->op]++; 1244 1245 to_find.guid = rec->guid; 1246 gt = avl_find(&zevstat.guids_runtime, &to_find, &where); 1247 if (!gt) { 1248 gt = malloc(sizeof(*gt)); 1249 if (!gt) { 1250 perror("can't get guid tracking record"); 1251 exit (EXIT_FAILURE); 1252 } 1253 gt->guid = rec->guid; 1254 avl_insert(&zevstat.guids_runtime, gt, where); 1255 } 1256 gt_int = avl_find(&zevstat.guids_interval, &to_find, &where); 1257 if (!gt_int) 1258 avl_insert(&zevstat.guids_interval, gt, where); 1259 } 1260 1261 static void 1262 zev_eventstat_interval(FILE *out) 1263 { 1264 uint64_t events; 1265 int i; 1266 zev_guidtrack_t *gt; 1267 1268 events = 0; 1269 for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) { 1270 events += zevstat.events[i]; 1271 } 1272 1273 if (verbose) { 1274 fprintf(out, "%u %6llu %6llu %6llu %6llu ", 1275 time(NULL), 1276 events, 1277 zevstat.total_events, 1278 avl_numnodes(&zevstat.guids_interval), 1279 avl_numnodes(&zevstat.guids_runtime)); 1280 for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) 1281 fprintf(out, "%6llu ", zevstat.events[i]); 1282 fprintf(out, "\n"); 1283 } else { 1284 fprintf(out, "%u %6llu %6llu %6llu %6llu\n", 1285 time(NULL), 1286 events, 1287 zevstat.total_events, 1288 avl_numnodes(&zevstat.guids_interval), 1289 avl_numnodes(&zevstat.guids_runtime)); 1290 } 1291 memset(&zevstat.events, 0, sizeof(zevstat.events)); 1292 zevstat.guids = 0; 1293 while (gt = avl_first(&zevstat.guids_interval)) 1294 avl_remove(&zevstat.guids_interval, gt); 1295 fflush(out); 1296 } 1297 1298 static int 1299 zev_evcompar(const void *a, const void *b) 1300 { 1301 const zev_guidtrack_t *ga = a; 1302 const zev_guidtrack_t *gb = b; 1303 1304 if (ga->guid > gb->guid) 1305 return 1; 1306 if (ga->guid < gb->guid) 1307 return -1; 1308 return 0; 1309 } 1310 1311 static int 1312 zev_zevstat(int fd, char *s_interval, char *s_count, char *outfile) 1313 { 1314 uint64_t interval = 1000; 1315 uint64_t ms; 1316 uint64_t t_until; 1317 uint64_t t_now; 1318 int cnt = -1; 1319 struct pollfd pfd[1]; 1320 int ret; 1321 char buf[4096]; 1322 zev_event_t *ev; 1323 int off = 0; 1324 zev_ioctl_add_queue_t aq; 1325 int q_fd; 1326 zev_guidtrack_t *gt; 1327 FILE *out = stdout; 1328 struct stat st; 1329 char filename[MAXPATHLEN]; 1330 int retry; 1331 1332 if (outfile) { 1333 retry = 0; 1334 strncpy(filename, outfile, sizeof(filename)); 1335 while (stat(filename, &st) == 0) { 1336 /* file exists */ 1337 snprintf(filename, sizeof(filename), 1338 "%s.%d", outfile, retry); 1339 retry++; 1340 } 1341 out = fopen(filename, "wb+"); 1342 if (!out) { 1343 perror("opening output file failed"); 1344 return (EXIT_FAILURE); 1345 } 1346 } 1347 1348 memset(&zevstat, 0, sizeof(zevstat)); 1349 avl_create(&zevstat.guids_runtime, zev_evcompar, 1350 sizeof(zev_guidtrack_t), 1351 offsetof(zev_guidtrack_t, avl_runtime)); 1352 avl_create(&zevstat.guids_interval, zev_evcompar, 1353 sizeof(zev_guidtrack_t), 1354 offsetof(zev_guidtrack_t, avl_interval)); 1355 1356 if (s_interval) { 1357 interval = atol(s_interval); 1358 if (interval == 0) { 1359 fprintf(stderr, "invalid interval.\n"); 1360 return (EXIT_FAILURE); 1361 } 1362 interval *= 1000; 1363 } 1364 if (s_count) { 1365 cnt = atol(s_count); 1366 if (interval == 0) { 1367 fprintf(stderr, "invalid count.\n"); 1368 return (EXIT_FAILURE); 1369 } 1370 } 1371 1372 aq.zev_max_queue_len = 1024 * 1024; 1373 aq.zev_flags = ZEV_FL_INITIALLY_EMPTY; 1374 snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 1375 "zevstat.%ld.%ld", time(NULL), getpid()); 1376 aq.zev_namelen = strlen(aq.zev_name); 1377 1378 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 1379 perror("adding temporary queue failed"); 1380 return (EXIT_FAILURE); 1381 } 1382 1383 snprintf(buf, sizeof(buf), 1384 "/devices/pseudo/zev@0:%s", aq.zev_name); 1385 q_fd = open(buf, O_RDONLY); 1386 if (q_fd < 0) { 1387 perror("opening queue device failed"); 1388 return (EXIT_FAILURE); 1389 } 1390 1391 pfd[0].fd = q_fd; 1392 pfd[0].events = POLLIN; 1393 1394 /* drain queue */ 1395 while ((ret = poll(pfd, 1, 0)) > 0) { 1396 if (read(q_fd, buf, sizeof(buf)) < 0) { 1397 perror("read failed"); 1398 close(q_fd); 1399 return(EXIT_FAILURE); 1400 } 1401 } 1402 if (ret < 0) { 1403 perror("poll failed"); 1404 close(q_fd); 1405 return(EXIT_FAILURE); 1406 } 1407 1408 fprintf(out, "timestamp events tevents guids tguids"); 1409 if (verbose) { 1410 fprintf(out, " error mark mount umount zvol_w "); 1411 fprintf(out, "zvol_t close create mkdir mxattr "); 1412 fprintf(out, "remove rmdir link symlnk rename "); 1413 fprintf(out, "write trunc setatt acl"); 1414 } 1415 fprintf(out, "\n"); 1416 while (cnt) { 1417 t_until = gethrtime() + (interval * 1000000); 1418 ms = interval; 1419 do { 1420 ret = poll(pfd, 1, ms); 1421 t_now = gethrtime(); 1422 if (t_now < t_until) { 1423 ms = t_until - t_now; 1424 ms /= 1000000ull; 1425 } 1426 if (ret < 0) { 1427 perror("poll failed"); 1428 close(q_fd); 1429 return(EXIT_FAILURE); 1430 } 1431 if (!(pfd[0].revents & POLLIN)) 1432 continue; 1433 /* data available */ 1434 ret = read(q_fd, buf, sizeof(buf)); 1435 if (ret < 0) { 1436 perror("read failed"); 1437 close(q_fd); 1438 return(EXIT_FAILURE); 1439 } 1440 if (ret == 0) 1441 continue; 1442 while (ret > off) { 1443 ev = (zev_event_t *)(buf + off); 1444 zev_eventstat(buf + off, ev->header.record_len); 1445 off += ev->header.record_len; 1446 } 1447 off = 0; 1448 } while ((t_now) < t_until && (ms > 0)); 1449 zev_eventstat_interval(out); 1450 if (cnt > 0) 1451 cnt--; 1452 } 1453 close(q_fd); 1454 if (outfile) 1455 fclose(out); 1456 while (gt = avl_first(&zevstat.guids_interval)) 1457 avl_remove(&zevstat.guids_interval, gt); 1458 while (gt = avl_first(&zevstat.guids_runtime)) { 1459 avl_remove(&zevstat.guids_runtime, gt); 1460 free(gt); 1461 } 1462 return EXIT_SUCCESS; 1463 } 1464 1465 static int 1466 zev_report(int fd, char *basename) 1467 { 1468 char filename[MAXPATHLEN]; 1469 char count[10]; 1470 time_t now; 1471 time_t midnight; 1472 struct tm tm; 1473 int minutes; 1474 int ret; 1475 1476 verbose++; 1477 while (1) { 1478 now = time(NULL); 1479 localtime_r(&now, &tm); 1480 snprintf(filename, sizeof(filename), "%s.%04d-%02d-%02d", 1481 basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 1482 tm.tm_sec = 0; 1483 tm.tm_min = 0; 1484 tm.tm_hour = 0; 1485 tm.tm_mday++; /* works for Jan 32nd, Feb 30th, etc. */ 1486 midnight = mktime(&tm); 1487 if (now % 60) 1488 sleep(60 - (now % 60)); 1489 minutes = (midnight - time(NULL)) / 60; 1490 snprintf(count, sizeof(count), "%d", minutes); 1491 ret = zev_zevstat(fd, "60", count, filename); 1492 if (ret) 1493 return EXIT_FAILURE; 1494 } 1495 return EXIT_SUCCESS; /* never reached */ 1496 } 1497 1498 static void 1499 zev_sigint(int sig) 1500 { 1501 fflush(stdout); 1502 } 1503 1504 int 1505 main(int argc, char **argv) 1506 { 1507 int fd; 1508 int c; 1509 extern char *optarg; 1510 int create_tmp_queue = 1; 1511 char buf[MAXPATHLEN]; 1512 int mode = 0; 1513 char *arg = NULL; 1514 char *arg2 = NULL; 1515 char *p; 1516 1517 sigset(SIGINT, zev_sigint); 1518 1519 /* open device */ 1520 fd = open(zev_device, O_RDONLY); 1521 if (fd < 0) { 1522 perror("opening zev device failed"); 1523 return EXIT_FAILURE; 1524 } 1525 1526 p = strrchr(argv[0], '/'); 1527 if (!p) { 1528 p = argv[0]; 1529 } else { 1530 p++; 1531 } 1532 if (!strcmp(p, "zevstat")) { 1533 mode = MD_ZEVSTAT; 1534 if (argc < 2) 1535 zevstat_usage(argv[0]); 1536 if (!strcmp(argv[1], "-v")) { 1537 if (argc < 3) 1538 zevstat_usage(argv[0]); 1539 verbose++; 1540 arg = argv[2]; 1541 arg2 = argv[3]; 1542 } else { 1543 arg = argv[1]; 1544 arg2 = argv[2]; 1545 } 1546 return zev_zevstat(fd, arg, arg2, NULL); 1547 } else if(!strcmp(p, "zevreport")) { 1548 mode = MD_ZEV_REPORT; 1549 if (argc != 2) 1550 zevreport_usage(argv[0]); 1551 return zev_report(fd, argv[1]); 1552 } 1553 1554 while ((c = getopt(argc, argv, 1555 "gvspc:d:Dlk:L:q:Q:t:m:M:a:A:r:P:b:B:T:R:h?")) != -1){ 1556 switch(c) { 1557 case 'g': 1558 grep_friendly++; 1559 verbose++; 1560 break; 1561 case 'v': 1562 verbose++; 1563 break; 1564 case 's': 1565 mode = MD_STATISTICS; 1566 break; 1567 case 'p': 1568 mode = MD_POLL_EVENTS; 1569 break; 1570 case 'c': 1571 mode = MD_CHECKSUMS; 1572 arg = optarg; 1573 break; 1574 case 'D': 1575 mode = MD_DEBUG_INFO; 1576 break; 1577 case 'd': 1578 close(fd); 1579 zev_device = optarg; 1580 fd = open(zev_device, O_RDONLY); 1581 if (fd < 0) { 1582 perror("opening zev device failed"); 1583 return EXIT_FAILURE; 1584 } 1585 create_tmp_queue = 0; 1586 break; 1587 case 'q': 1588 snprintf(buf, sizeof(buf), 1589 "/devices/pseudo/zev@0:%s", optarg); 1590 close(fd); 1591 zev_device = buf; 1592 fd = open(zev_device, O_RDONLY); 1593 if (fd < 0) { 1594 perror("opening zev device failed"); 1595 return EXIT_FAILURE; 1596 } 1597 create_tmp_queue = 0; 1598 break; 1599 case 'l': 1600 mode = MD_LIST_QUEUES; 1601 break; 1602 case 'Q': 1603 mode = MD_SET_GLOBAL_MAX_QUEUE_LEN; 1604 arg = optarg; 1605 break; 1606 case 'L': 1607 mode = MD_SET_MAX_QUEUE_LEN; 1608 arg = optarg; 1609 arg2 = argv[optind]; 1610 break; 1611 case 'T': 1612 mode = MD_ZEVSTAT; 1613 arg = optarg; 1614 arg2 = argv[optind]; 1615 break; 1616 case 'R': 1617 mode = MD_ZEV_REPORT; 1618 arg = optarg; 1619 break; 1620 case 't': 1621 mode = MD_SET_POLL_WAKEUP_QUEUE_LEN; 1622 arg = optarg; 1623 arg2 = argv[optind]; 1624 break; 1625 case 'm': 1626 mode = MD_MUTE_POOL; 1627 arg = optarg; 1628 break; 1629 case 'M': 1630 mode = MD_UNMUTE_POOL; 1631 arg = optarg; 1632 break; 1633 case 'k': 1634 mode = MD_MARK; 1635 arg = optarg; 1636 break; 1637 case 'a': 1638 mode = MD_ADD_QUEUE; 1639 arg = optarg; 1640 break; 1641 case 'A': 1642 mode = MD_ADD_BLOCKING_QUEUE; 1643 arg = optarg; 1644 break; 1645 case 'r': 1646 mode = MD_REMOVE_QUEUE; 1647 arg = optarg; 1648 break; 1649 case 'b': 1650 mode = MD_QUEUE_BLOCKING; 1651 arg = optarg; 1652 break; 1653 case 'B': 1654 mode = MD_QUEUE_NONBLOCKING; 1655 arg = optarg; 1656 break; 1657 case 'P': 1658 mode = MD_QUEUE_PROPERTIES; 1659 arg = optarg; 1660 break; 1661 case 'h': 1662 case '?': 1663 default: 1664 usage(argv[0]); 1665 } 1666 } 1667 1668 switch (mode) { 1669 case MD_STATISTICS: 1670 return zev_statistics(fd); 1671 case MD_POLL_EVENTS: 1672 return zev_poll_events(fd, create_tmp_queue); 1673 case MD_CHECKSUMS: 1674 return zev_checksum(fd, arg); 1675 case MD_DEBUG_INFO: 1676 return zev_debug_info(fd); 1677 case MD_LIST_QUEUES: 1678 return zev_list_queues(fd); 1679 case MD_SET_GLOBAL_MAX_QUEUE_LEN: 1680 return zev_set_global_max_queue_len(fd, arg); 1681 case MD_SET_MAX_QUEUE_LEN: 1682 return zev_set_max_queue_len(fd, arg, arg2); 1683 case MD_SET_POLL_WAKEUP_QUEUE_LEN: 1684 return zev_set_poll_wakeup_queue_len(fd, arg, arg2); 1685 case MD_ZEVSTAT: 1686 return zev_zevstat(fd, arg, arg2, NULL); 1687 case MD_ZEV_REPORT: 1688 return zev_report(fd, arg); 1689 case MD_MUTE_POOL: 1690 return zev_mute_pool(fd, arg); 1691 case MD_UNMUTE_POOL: 1692 return zev_unmute_pool(fd, arg); 1693 case MD_MARK: 1694 return zev_mark(fd, arg); 1695 case MD_ADD_QUEUE: 1696 return zev_add_queue(fd, arg, 0); 1697 case MD_ADD_BLOCKING_QUEUE: 1698 return zev_add_queue(fd, arg, 1); 1699 case MD_REMOVE_QUEUE: 1700 return zev_remove_queue(fd, arg); 1701 case MD_QUEUE_BLOCKING: 1702 return zev_queue_blocking(fd, arg, 0); 1703 case MD_QUEUE_NONBLOCKING: 1704 return zev_queue_blocking(fd, arg, 1); 1705 case MD_QUEUE_PROPERTIES: 1706 return zev_queue_properties(fd, arg); 1707 default: 1708 close(fd); 1709 usage(argv[0]); 1710 return EXIT_FAILURE; 1711 }; 1712 } 1713 1714