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