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 int 762 zev_add_queue(int fd, char *arg, int blocking) 763 { 764 zev_ioctl_add_queue_t aq; 765 int namelen; 766 767 namelen = strlen(arg); 768 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 769 fprintf(stderr, "queue name too long: %s\n", arg); 770 return (EXIT_FAILURE); 771 } 772 773 aq.zev_namelen = namelen; 774 strcpy(aq.zev_name, arg); 775 aq.zev_flags = ZEV_FL_PERSISTENT; 776 if (blocking) { 777 aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 778 aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 779 } else { 780 aq.zev_max_queue_len = (1024 * 1024); 781 } 782 783 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 784 perror("adding queue failed"); 785 return (EXIT_FAILURE); 786 } 787 return (0); 788 } 789 790 static int 791 zev_remove_queue(int fd, char *arg) 792 { 793 zev_ioctl_remove_queue_t aq; 794 int namelen; 795 796 namelen = strlen(arg); 797 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 798 fprintf(stderr, "queue name too long: %s\n", arg); 799 return (EXIT_FAILURE); 800 } 801 802 aq.zev_queue_name.zev_namelen = namelen; 803 strcpy(aq.zev_queue_name.zev_name, arg); 804 805 if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 806 perror("removing queue failed"); 807 return (EXIT_FAILURE); 808 } 809 return (0); 810 } 811 812 static int 813 zev_set_global_max_queue_len(int fd, char *arg) 814 { 815 uint64_t maxqueuelen; 816 817 errno = 0; 818 maxqueuelen = strtol(arg, (char **)NULL, 10); 819 if (errno) { 820 fprintf(stderr, "invalid queue length parameter: %s\n", arg); 821 return (EXIT_FAILURE); 822 } 823 if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 824 perror("setting max queue length failed"); 825 return (EXIT_FAILURE); 826 } 827 return (0); 828 } 829 830 static int 831 zev_mute_unmute_impl(int fd, char *poolname, int mute) 832 { 833 zev_ioctl_poolarg_t pa; 834 int len; 835 int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 836 len = strlen(poolname); 837 if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 838 fprintf(stderr, "invalid poolname: %s\n", poolname); 839 return (EXIT_FAILURE); 840 } 841 strcpy(pa.zev_poolname, poolname); 842 pa.zev_poolname_len = len; 843 if (ioctl(fd, op, &pa)) { 844 perror("muting pool data failed"); 845 return (EXIT_FAILURE); 846 } 847 return (0); 848 } 849 850 int 851 zev_mute_pool(int fd, char *poolname) 852 { 853 return zev_mute_unmute_impl(fd, poolname, 1); 854 } 855 856 int 857 zev_unmute_pool(int fd, char *poolname) 858 { 859 return zev_mute_unmute_impl(fd, poolname, 0); 860 } 861 862 static int 863 zev_debug_info(int fd) 864 { 865 zev_ioctl_debug_info_t di; 866 867 if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 868 perror("getting zev debug info failed"); 869 return (EXIT_FAILURE); 870 } 871 872 printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 873 printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 874 printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 875 printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 876 return 0; 877 } 878 879 static int 880 zev_mark(int fd, char *arg) 881 { 882 zev_ioctl_mark_t *mark; 883 uint64_t guid; 884 int len; 885 char *p; 886 887 p = strchr(arg, ':'); 888 if (!p) { 889 fprintf(stderr, "expected value is <guid>:<payload>, " 890 "e.g. '123:hello'\n"); 891 exit (EXIT_FAILURE); 892 } 893 *p = '\n'; 894 p++; 895 896 errno = 0; 897 guid = strtoll(arg, (char **)NULL, 10); 898 if (errno) { 899 fprintf(stderr, "guid must be a number.\n"); 900 exit (EXIT_FAILURE); 901 } 902 903 len = strlen(p); 904 905 mark = malloc(sizeof(*mark) + len + 1); 906 if (!mark) { 907 fprintf(stderr, "can't allocate mark structure: %s\n", 908 strerror(errno)); 909 exit (EXIT_FAILURE); 910 } 911 mark->zev_guid = guid; 912 mark->zev_mark_id = 0; 913 mark->zev_payload_len = len; 914 strcpy(ZEV_PAYLOAD(mark), p); 915 916 if (ioctl(fd, ZEV_IOC_MARK, mark)) { 917 perror("queueing mark failed"); 918 return (EXIT_FAILURE); 919 } 920 921 printf("mark id: %lu\n", mark->zev_mark_id); 922 return (0); 923 } 924 925 static int 926 zev_queue_blocking(int fd, char *arg, int block) 927 { 928 zev_ioctl_get_queue_properties_t gqp; 929 930 gqp.zev_queue_name.zev_namelen = strlen(arg); 931 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 932 fprintf(stderr, "queue name too long.\n"); 933 return EXIT_FAILURE; 934 } 935 strcpy(gqp.zev_queue_name.zev_name, arg); 936 937 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 938 perror("getting queue properties failed"); 939 return (EXIT_FAILURE); 940 } 941 if (block) { 942 gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 943 } else { 944 gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 945 } 946 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 947 perror("setting queue properties failed"); 948 return (EXIT_FAILURE); 949 } 950 return (0); 951 } 952 953 static int 954 zev_set_max_queue_len(int fd, char *arg, char *len) 955 { 956 zev_ioctl_get_queue_properties_t gqp; 957 958 if (!len) { 959 fprintf(stderr, "queue size parameter missing.\n"); 960 return EXIT_FAILURE; 961 } 962 963 gqp.zev_queue_name.zev_namelen = strlen(arg); 964 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 965 fprintf(stderr, "queue name too long.\n"); 966 return EXIT_FAILURE; 967 } 968 strcpy(gqp.zev_queue_name.zev_name, arg); 969 970 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 971 perror("getting queue properties failed"); 972 return (EXIT_FAILURE); 973 } 974 gqp.zev_max_queue_len = atol(len); 975 if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 976 fprintf(stderr, "queue size parameter garbled.\n"); 977 return (EXIT_FAILURE); 978 } 979 if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 980 fprintf(stderr, "queue size parameter out of bounds.\n"); 981 return (EXIT_FAILURE); 982 } 983 984 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 985 perror("setting queue properties failed"); 986 return (EXIT_FAILURE); 987 } 988 return (0); 989 } 990 991 static int 992 zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 993 { 994 zev_ioctl_get_queue_properties_t gqp; 995 996 if (!len) { 997 fprintf(stderr, "poll throttle parameter missing.\n"); 998 return EXIT_FAILURE; 999 } 1000 1001 gqp.zev_queue_name.zev_namelen = strlen(arg); 1002 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1003 fprintf(stderr, "queue name too long.\n"); 1004 return EXIT_FAILURE; 1005 } 1006 strcpy(gqp.zev_queue_name.zev_name, arg); 1007 1008 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1009 perror("getting queue properties failed"); 1010 return (EXIT_FAILURE); 1011 } 1012 gqp.zev_poll_wakeup_threshold = atol(len); 1013 if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 1014 fprintf(stderr, "poll throttle parameter garbled.\n"); 1015 return (EXIT_FAILURE); 1016 } 1017 if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 1018 fprintf(stderr, "poll throttle parameter out of bounds.\n"); 1019 return (EXIT_FAILURE); 1020 } 1021 1022 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 1023 perror("setting queue properties failed"); 1024 return (EXIT_FAILURE); 1025 } 1026 return (0); 1027 } 1028 1029 static int 1030 zev_queue_properties(int fd, char *arg) 1031 { 1032 zev_ioctl_get_queue_properties_t gqp; 1033 1034 gqp.zev_queue_name.zev_namelen = strlen(arg); 1035 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1036 fprintf(stderr, "queue name too long.\n"); 1037 return EXIT_FAILURE; 1038 } 1039 strcpy(gqp.zev_queue_name.zev_name, arg); 1040 1041 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1042 perror("getting queue properties failed"); 1043 return (EXIT_FAILURE); 1044 } 1045 1046 printf("queue : %s\n", arg); 1047 printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1048 printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1049 printf("persistent : %s\n", 1050 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1051 printf("blocking : %s\n", 1052 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1053 1054 return (0); 1055 } 1056 1057 static int 1058 zev_list_queues(int fd) 1059 { 1060 zev_ioctl_get_queue_properties_t gqp; 1061 zev_ioctl_get_queue_list_t gql; 1062 zev_ioctl_get_queue_statistics_t gs; 1063 uint64_t i; 1064 char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1065 1066 if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1067 perror("getting queue list failed"); 1068 return (EXIT_FAILURE); 1069 } 1070 1071 printf("Name Size " 1072 "Max Size Wakeup Per Block\n"); 1073 1074 for (i=0; i<gql.zev_n_queues; i++) { 1075 strncpy(name, gql.zev_queue_name[i].zev_name, 1076 ZEV_MAX_QUEUE_NAME_LEN); 1077 name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1078 1079 memcpy(gqp.zev_queue_name.zev_name, 1080 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1081 gqp.zev_queue_name.zev_namelen = 1082 gql.zev_queue_name[i].zev_namelen; 1083 1084 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1085 if (errno == ENOENT) 1086 continue; 1087 perror("getting queue properties failed"); 1088 return (EXIT_FAILURE); 1089 } 1090 1091 memcpy(gs.zev_queue_name.zev_name, 1092 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1093 gs.zev_queue_name.zev_namelen = 1094 gql.zev_queue_name[i].zev_namelen; 1095 1096 if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1097 if (errno == ENOENT) 1098 continue; 1099 perror("getting statistics data failed"); 1100 return (EXIT_FAILURE); 1101 } 1102 1103 printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1104 " %-3s %-3s\n", 1105 name, 1106 gs.zev_statistics.zev_queue_len, 1107 gqp.zev_max_queue_len, 1108 gqp.zev_poll_wakeup_threshold, 1109 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1110 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1111 "yes" : "no"); 1112 } 1113 1114 return (0); 1115 } 1116 1117 static int 1118 zev_checksum(int dev_fd, char *filename) 1119 { 1120 int fd; 1121 offset_t off; 1122 offset_t data; 1123 zev_sig_t *sig; 1124 char *buf; 1125 zev_ioctl_get_signatures_t *gs; 1126 int i; 1127 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 1128 int buf_size; 1129 1130 /* control struct, one lv1 signature and up to 256 lv0 signatures */ 1131 buf_size = (1 + 256) * sizeof(zev_sig_t); 1132 buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 1133 if (!buf) { 1134 perror("can't allocate checksum buffer"); 1135 return (EXIT_FAILURE); 1136 } 1137 1138 fd = open(filename, O_RDONLY); 1139 if (fd < 0) { 1140 perror("can't open file"); 1141 return (EXIT_FAILURE); 1142 } 1143 1144 gs = (zev_ioctl_get_signatures_t *)buf; 1145 gs->zev_fd = fd; 1146 gs->zev_bufsize = buf_size; 1147 1148 off = 0; 1149 data = 0; 1150 while (1) { 1151 errno = 0; 1152 data = llseek(fd, off, SEEK_DATA); 1153 if (data < 0) { 1154 if (errno == ENXIO) /* no more data */ 1155 break; 1156 perror("llseek failed"); 1157 goto err; 1158 } 1159 data = P2ALIGN(data, ZEV_L1_SIZE); 1160 off = data + ZEV_L1_SIZE; 1161 1162 gs->zev_offset = data; 1163 gs->zev_len = ZEV_L1_SIZE; 1164 1165 if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 1166 perror("ioctl to get signatures failed"); 1167 goto err; 1168 } 1169 1170 for (i=0; i<gs->zev_signature_cnt; i++) { 1171 sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 1172 sig += i; 1173 sig2hex_direct(sig->value, sigval); 1174 printf("level %d, offset %llu, value %s\n", 1175 sig->level, sig->block_offset, sigval); 1176 } 1177 } 1178 1179 free(buf); 1180 close(fd); 1181 return 0; 1182 err: 1183 free(buf); 1184 close(fd); 1185 return (EXIT_FAILURE); 1186 } 1187 1188 typedef struct zevstat { 1189 uint64_t ns_start; 1190 uint64_t events[ZEV_OP_MIN + ZEV_OP_MAX]; 1191 uint64_t guids; 1192 uint64_t total_events; 1193 uint64_t total_guids; 1194 avl_tree_t guids_interval; 1195 avl_tree_t guids_runtime; 1196 } zevstat_t; 1197 1198 typedef struct zev_guidtrack_t { 1199 uint64_t guid; 1200 avl_node_t avl_interval; 1201 avl_node_t avl_runtime; 1202 } zev_guidtrack_t; 1203 1204 zevstat_t zevstat; 1205 1206 static void 1207 zev_eventstat(char *buf, int len) 1208 { 1209 zev_header_t *rec = (zev_header_t *)buf; 1210 zev_guidtrack_t *gt; 1211 zev_guidtrack_t *gt_int; 1212 zev_guidtrack_t to_find; 1213 avl_index_t where; 1214 1215 zevstat.total_events++; 1216 zevstat.events[rec->op]++; 1217 1218 to_find.guid = rec->guid; 1219 gt = avl_find(&zevstat.guids_runtime, &to_find, &where); 1220 if (!gt) { 1221 gt = malloc(sizeof(*gt)); 1222 if (!gt) { 1223 perror("can't get guid tracking record"); 1224 exit (EXIT_FAILURE); 1225 } 1226 gt->guid = rec->guid; 1227 avl_insert(&zevstat.guids_runtime, gt, where); 1228 } 1229 gt_int = avl_find(&zevstat.guids_interval, &to_find, &where); 1230 if (!gt_int) 1231 avl_insert(&zevstat.guids_interval, gt, where); 1232 } 1233 1234 static void 1235 zev_eventstat_interval(void) 1236 { 1237 uint64_t events; 1238 int i; 1239 zev_guidtrack_t *gt; 1240 1241 events = 0; 1242 for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) { 1243 events += zevstat.events[i]; 1244 } 1245 1246 if (verbose) { 1247 printf("%u %6llu %6llu %6llu %6llu ", 1248 time(NULL), 1249 events, 1250 zevstat.total_events, 1251 avl_numnodes(&zevstat.guids_interval), 1252 avl_numnodes(&zevstat.guids_runtime)); 1253 for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) 1254 printf("%6llu ", zevstat.events[i]); 1255 printf("\n"); 1256 } else { 1257 printf("%u %6llu %6llu %6llu %6llu\n", 1258 time(NULL), 1259 events, 1260 zevstat.total_events, 1261 avl_numnodes(&zevstat.guids_interval), 1262 avl_numnodes(&zevstat.guids_runtime)); 1263 } 1264 memset(&zevstat.events, 0, sizeof(zevstat.events)); 1265 zevstat.guids = 0; 1266 while (gt = avl_first(&zevstat.guids_interval)) 1267 avl_remove(&zevstat.guids_interval, gt); 1268 } 1269 1270 static int 1271 zev_evcompar(const void *a, const void *b) 1272 { 1273 const zev_guidtrack_t *ga = a; 1274 const zev_guidtrack_t *gb = b; 1275 1276 if (ga->guid > gb->guid) 1277 return 1; 1278 if (ga->guid < gb->guid) 1279 return -1; 1280 return 0; 1281 } 1282 1283 static int 1284 zev_zevstat(int fd, char *s_interval, char *s_count) 1285 { 1286 uint64_t interval = 1000; 1287 uint64_t ms; 1288 uint64_t t_until; 1289 uint64_t t_now; 1290 int cnt = -1; 1291 struct pollfd pfd[1]; 1292 int ret; 1293 char buf[4096]; 1294 zev_event_t *ev; 1295 int off = 0; 1296 zev_ioctl_add_queue_t aq; 1297 int q_fd; 1298 zev_guidtrack_t *gt; 1299 1300 memset(&zevstat, 0, sizeof(zevstat)); 1301 avl_create(&zevstat.guids_runtime, zev_evcompar, 1302 sizeof(zev_guidtrack_t), 1303 offsetof(zev_guidtrack_t, avl_runtime)); 1304 avl_create(&zevstat.guids_interval, zev_evcompar, 1305 sizeof(zev_guidtrack_t), 1306 offsetof(zev_guidtrack_t, avl_interval)); 1307 1308 interval = atol(s_interval); 1309 if (interval == 0) { 1310 fprintf(stderr, "invalid interval.\n"); 1311 return (EXIT_FAILURE); 1312 } 1313 interval *= 1000; 1314 if (s_count) { 1315 cnt = atol(s_count); 1316 if (interval == 0) { 1317 fprintf(stderr, "invalid count.\n"); 1318 return (EXIT_FAILURE); 1319 } 1320 } 1321 1322 aq.zev_max_queue_len = 1024 * 1024; 1323 aq.zev_flags = 0; 1324 snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 1325 "zevstat.%ld.%ld", time(NULL), getpid()); 1326 aq.zev_namelen = strlen(aq.zev_name); 1327 1328 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 1329 perror("adding temporary queue failed"); 1330 return (EXIT_FAILURE); 1331 } 1332 1333 snprintf(buf, sizeof(buf), 1334 "/devices/pseudo/zev@0:%s", aq.zev_name); 1335 q_fd = open(buf, O_RDONLY); 1336 if (q_fd < 0) { 1337 perror("opening queue device failed"); 1338 return (EXIT_FAILURE); 1339 } 1340 1341 pfd[0].fd = q_fd; 1342 pfd[0].events = POLLIN; 1343 1344 /* drain queue */ 1345 while ((ret = poll(pfd, 1, 1000)) > 0) { 1346 if (read(q_fd, buf, sizeof(buf)) < 0) { 1347 perror("read failed"); 1348 close(q_fd); 1349 return(EXIT_FAILURE); 1350 } 1351 } 1352 if (ret < 0) { 1353 perror("poll failed"); 1354 close(q_fd); 1355 return(EXIT_FAILURE); 1356 } 1357 1358 printf("timestamp events tevents guids tguids"); 1359 if (verbose) { 1360 printf(" error mark mount umount zvol_w zvol_t "); 1361 printf(" close create mkdir mxattr remove rmdir "); 1362 printf(" link symlnk rename write trunc setatt acl"); 1363 } 1364 printf("\n"); 1365 while (cnt) { 1366 t_until = gethrtime() + (interval * 1000000); 1367 ms = interval; 1368 do { 1369 ret = poll(pfd, 1, ms); 1370 t_now = gethrtime(); 1371 if (t_now < t_until) { 1372 ms = t_until - t_now; 1373 ms /= 1000000ull; 1374 } 1375 if (ret < 0) { 1376 perror("poll failed"); 1377 close(q_fd); 1378 return(EXIT_FAILURE); 1379 } 1380 if (!(pfd[0].revents & POLLIN)) 1381 continue; 1382 /* data available */ 1383 ret = read(q_fd, buf, sizeof(buf)); 1384 if (ret < 0) { 1385 perror("read failed"); 1386 close(q_fd); 1387 return(EXIT_FAILURE); 1388 } 1389 if (ret == 0) 1390 continue; 1391 while (ret > off) { 1392 ev = (zev_event_t *)(buf + off); 1393 zev_eventstat(buf + off, ev->header.record_len); 1394 off += ev->header.record_len; 1395 } 1396 off = 0; 1397 } while ((t_now) < t_until && (ms > 0)); 1398 zev_eventstat_interval(); 1399 if (cnt > 0) 1400 cnt--; 1401 } 1402 close(q_fd); 1403 while (gt = avl_first(&zevstat.guids_interval)) 1404 avl_remove(&zevstat.guids_interval, gt); 1405 while (gt = avl_first(&zevstat.guids_runtime)) { 1406 avl_remove(&zevstat.guids_runtime, gt); 1407 free(gt); 1408 } 1409 return EXIT_SUCCESS; 1410 } 1411 1412 int 1413 main(int argc, char **argv) 1414 { 1415 int fd; 1416 int c; 1417 extern char *optarg; 1418 int create_tmp_queue = 1; 1419 char buf[MAXPATHLEN]; 1420 int mode = 0; 1421 char *arg = NULL; 1422 char *arg2 = NULL; 1423 char *p; 1424 1425 p = strrchr(argv[0], '/'); 1426 if (!p) { 1427 p = argv[0]; 1428 } else { 1429 p++; 1430 } 1431 if (!strcmp(p, "zevstat")) { 1432 mode = MD_ZEVSTAT; 1433 } 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 while ((c = getopt(argc, argv, 1442 "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:T:h?")) != -1){ 1443 switch(c) { 1444 case 'g': 1445 grep_friendly++; 1446 verbose++; 1447 break; 1448 case 'v': 1449 verbose++; 1450 break; 1451 case 's': 1452 mode = MD_STATISTICS; 1453 break; 1454 case 'p': 1455 mode = MD_POLL_EVENTS; 1456 break; 1457 case 'c': 1458 mode = MD_CHECKSUMS; 1459 arg = optarg; 1460 break; 1461 case 'D': 1462 mode = MD_DEBUG_INFO; 1463 break; 1464 case 'd': 1465 close(fd); 1466 zev_device = optarg; 1467 fd = open(zev_device, O_RDONLY); 1468 if (fd < 0) { 1469 perror("opening zev device failed"); 1470 return EXIT_FAILURE; 1471 } 1472 create_tmp_queue = 0; 1473 break; 1474 case 'q': 1475 snprintf(buf, sizeof(buf), 1476 "/devices/pseudo/zev@0:%s", optarg); 1477 close(fd); 1478 zev_device = buf; 1479 fd = open(zev_device, O_RDONLY); 1480 if (fd < 0) { 1481 perror("opening zev device failed"); 1482 return EXIT_FAILURE; 1483 } 1484 create_tmp_queue = 0; 1485 break; 1486 case 'l': 1487 mode = MD_LIST_QUEUES; 1488 break; 1489 case 'Q': 1490 mode = MD_SET_GLOBAL_MAX_QUEUE_LEN; 1491 arg = optarg; 1492 break; 1493 case 'L': 1494 mode = MD_SET_MAX_QUEUE_LEN; 1495 arg = optarg; 1496 arg2 = argv[optind]; 1497 break; 1498 case 'T': 1499 mode = MD_ZEVSTAT; 1500 arg = optarg; 1501 arg2 = argv[optind]; 1502 break; 1503 case 't': 1504 mode = MD_SET_POLL_WAKEUP_QUEUE_LEN; 1505 arg = optarg; 1506 arg2 = argv[optind]; 1507 break; 1508 case 'm': 1509 mode = MD_MUTE_POOL; 1510 arg = optarg; 1511 break; 1512 case 'M': 1513 mode = MD_UNMUTE_POOL; 1514 arg = optarg; 1515 break; 1516 case 'k': 1517 mode = MD_MARK; 1518 arg = optarg; 1519 break; 1520 case 'a': 1521 mode = MD_ADD_QUEUE; 1522 arg = optarg; 1523 break; 1524 case 'A': 1525 mode = MD_ADD_BLOCKING_QUEUE; 1526 arg = optarg; 1527 break; 1528 case 'r': 1529 mode = MD_REMOVE_QUEUE; 1530 arg = optarg; 1531 break; 1532 case 'b': 1533 mode = MD_QUEUE_BLOCKING; 1534 arg = optarg; 1535 break; 1536 case 'B': 1537 mode = MD_QUEUE_NONBLOCKING; 1538 arg = optarg; 1539 break; 1540 case 'P': 1541 mode = MD_QUEUE_PROPERTIES; 1542 arg = optarg; 1543 break; 1544 case 'h': 1545 case '?': 1546 default: 1547 usage(argv[0]); 1548 } 1549 } 1550 1551 switch (mode) { 1552 case MD_STATISTICS: 1553 return zev_statistics(fd); 1554 case MD_POLL_EVENTS: 1555 return zev_poll_events(fd, create_tmp_queue); 1556 case MD_CHECKSUMS: 1557 return zev_checksum(fd, arg); 1558 case MD_DEBUG_INFO: 1559 return zev_debug_info(fd); 1560 case MD_LIST_QUEUES: 1561 return zev_list_queues(fd); 1562 case MD_SET_GLOBAL_MAX_QUEUE_LEN: 1563 return zev_set_global_max_queue_len(fd, arg); 1564 case MD_SET_MAX_QUEUE_LEN: 1565 return zev_set_max_queue_len(fd, arg, arg2); 1566 case MD_SET_POLL_WAKEUP_QUEUE_LEN: 1567 return zev_set_poll_wakeup_queue_len(fd, arg, arg2); 1568 case MD_ZEVSTAT: 1569 return zev_zevstat(fd, arg, arg2); 1570 case MD_MUTE_POOL: 1571 return zev_mute_pool(fd, arg); 1572 case MD_UNMUTE_POOL: 1573 return zev_unmute_pool(fd, arg); 1574 case MD_MARK: 1575 return zev_mark(fd, arg); 1576 case MD_ADD_QUEUE: 1577 return zev_add_queue(fd, arg, 0); 1578 case MD_ADD_BLOCKING_QUEUE: 1579 return zev_add_queue(fd, arg, 1); 1580 case MD_REMOVE_QUEUE: 1581 return zev_remove_queue(fd, arg); 1582 case MD_QUEUE_BLOCKING: 1583 return zev_queue_blocking(fd, arg, 0); 1584 case MD_QUEUE_NONBLOCKING: 1585 return zev_queue_blocking(fd, arg, 1); 1586 case MD_QUEUE_PROPERTIES: 1587 return zev_queue_properties(fd, arg); 1588 default: 1589 close(fd); 1590 usage(argv[0]); 1591 return EXIT_FAILURE; 1592 }; 1593 } 1594 1595