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 13 #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 14 15 static char *zev_device = ZEV_DEVICE; 16 17 static char *zev_op_name[] = { 18 "ERROR", 19 "MARK", 20 "ZFS_MOUNT", 21 "ZFS_UMOUNT", 22 "ZVOL_WRITE", 23 "ZVOL_TRUNCATE", 24 "ZNODE_CLOSE_AFTER_UPDATE", 25 "ZNODE_CREATE", 26 "ZNODE_MKDIR", 27 "ZNODE_MAKE_XATTR_DIR", 28 "ZNODE_REMOVE", 29 "ZNODE_RMDIR", 30 "ZNODE_LINK", 31 "ZNODE_SYMLINK", 32 "ZNODE_RENAME", 33 "ZNODE_WRITE", 34 "ZNODE_TRUNCATE", 35 "ZNODE_SETATTR", 36 "ZNODE_ACL", 37 NULL 38 }; 39 40 static int verbose = 0; 41 static int grep_friendly = 0; 42 43 static void 44 zpf(char *fmt, ...) 45 { 46 va_list ap; 47 48 va_start(ap, fmt); 49 vprintf(fmt, ap); 50 va_end(ap); 51 if (grep_friendly) { 52 printf(" "); 53 } else { 54 printf("\n"); 55 } 56 } 57 58 static void 59 znl(void) 60 { 61 if (grep_friendly) 62 printf("\n"); 63 } 64 65 static int 66 zev_statistics(int fd) 67 { 68 zev_statistics_t zs; 69 if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 70 perror("getting statistics data failed"); 71 return (EXIT_FAILURE); 72 } 73 printf("ZEV module state:\n"); 74 75 printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 76 printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 77 printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 78 printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 79 80 printf(" discarded events : %lu\n", 81 zs.zev_cnt_discarded_events); 82 printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 83 84 printf("ZFS event statistics:\n"); 85 86 printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 87 printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 88 printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 89 printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 90 printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 91 printf(" ZNODE close after update: %lu\n", 92 zs.zev_cnt_znode_close_after_update); 93 printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 94 printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 95 printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 96 printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 97 printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 98 printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 99 printf(" ZNODE truncate : %lu\n", 100 zs.zev_cnt_znode_truncate); 101 printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 102 printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 103 return EXIT_SUCCESS; 104 } 105 106 static void 107 zev_print_inode_info(char *name, zev_inode_info_t *info) 108 { 109 zpf(" %s.inode: %llu", name, info->ino); 110 zpf(" %s.gen: %llu", name, info->gen); 111 zpf(" %s.mtime: %llu", name, info->mtime); 112 zpf(" %s.ctime: %llu", name, info->ctime); 113 zpf(" %s.size: %llu", name, info->size); 114 zpf(" %s.mode: %llo", name, info->mode); 115 zpf(" %s.links: %llu", name, info->links); 116 zpf(" %s.type: %lu", name, info->type); 117 zpf(" %s.flags: %lu", name, info->flags); 118 } 119 120 static void 121 zev_print_mark_payload(zev_mark_t *rec) 122 { 123 int i; 124 int j; 125 uint8_t *p; 126 char c; 127 128 zpf(" payload:"); 129 p = (uint8_t *)ZEV_PAYLOAD(rec); 130 for (i=0; i<rec->payload_len; i+=16) { 131 printf(" "); 132 for (j=i; j<rec->payload_len && j<i+16; j++) { 133 printf("%02x ", p[j]); 134 if (j == i + 7) 135 printf(" "); 136 } 137 if (grep_friendly) 138 continue; 139 for (; j<i+16; j++) { 140 printf(" "); 141 if (j == i + 7) 142 printf(" "); 143 } 144 printf(" "); 145 for (j=i; j<rec->payload_len && j<i+16; j++) { 146 c = '.'; 147 if (p[j] >= ' ' && p[j] <= '~') 148 c = p[j]; 149 printf("%c", c); 150 if (j == i + 7) 151 printf(" "); 152 } 153 printf("\n"); 154 } 155 } 156 157 static void 158 zev_print_error(char *buf) 159 { 160 zev_error_t *rec = (zev_error_t *)buf; 161 time_t op_time = rec->op_time; 162 char *ct = ctime(&op_time); ct[24] = '\0'; 163 164 if (verbose) { 165 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 166 zpf(" guid: %llu", rec->guid); 167 zpf(" failed.op: %s", 168 zev_op_name[rec->failed_op - ZEV_OP_MIN]); 169 zpf(" message: %s", ZEV_ERRSTR(rec)); 170 znl(); 171 } else { 172 printf("%s %s: failed_op=%s msg=%s\n", 173 ct, zev_op_name[rec->op - ZEV_OP_MIN], 174 zev_op_name[rec->failed_op - ZEV_OP_MIN], 175 ZEV_ERRSTR(rec)); 176 } 177 } 178 179 static void 180 zev_print_mark(char *buf) 181 { 182 zev_mark_t *rec = (zev_mark_t *)buf; 183 time_t op_time = rec->op_time; 184 char *ct = ctime(&op_time); ct[24] = '\0'; 185 186 if (verbose) { 187 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 188 zpf(" guid: %llu", rec->guid); 189 zpf(" mark.id: %llu", rec->mark_id); 190 zpf(" payload.len: %llu", rec->payload_len); 191 if (rec->payload_len) 192 zev_print_mark_payload(rec); 193 znl(); 194 } else { 195 printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 196 ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 197 rec->mark_id, rec->payload_len); 198 } 199 } 200 201 static void 202 zev_print_zfs_mount(char *buf) 203 { 204 zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 205 time_t op_time = rec->op_time; 206 char *ct = ctime(&op_time); ct[24] = '\0'; 207 208 if (verbose) { 209 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 210 zpf(" guid: %llu", rec->guid); 211 zpf(" dataset: %s", ZEV_DATASET(rec)); 212 zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 213 zpf(" remount: %s", rec->remount ? "true" : "false"); 214 zev_print_inode_info("root", &rec->root); 215 znl(); 216 } else { 217 printf("%s %s: guid=%llu remount=%s dataset='%s' " 218 "mountpoint='%s'\n", 219 ct, zev_op_name[rec->op - ZEV_OP_MIN], 220 rec->guid, 221 rec->remount ? "true" : "false", 222 ZEV_DATASET(rec), 223 ZEV_MOUNTPOINT(rec)); 224 } 225 } 226 227 static void 228 zev_print_zfs_umount(char *buf) 229 { 230 zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 231 time_t op_time = rec->op_time; 232 char *ct = ctime(&op_time); ct[24] = '\0'; 233 234 if (verbose) { 235 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 236 zpf(" guid: %llu", rec->guid); 237 znl(); 238 } else { 239 printf("%s %s: guid=%llu\n", 240 ct, zev_op_name[rec->op - ZEV_OP_MIN], 241 rec->guid); 242 } 243 } 244 245 static void 246 zev_print_zvol_truncate(char *buf) 247 { 248 zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 249 time_t op_time = rec->op_time; 250 char *ct = ctime(&op_time); ct[24] = '\0'; 251 252 if (verbose) { 253 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 254 zpf(" guid: %llu", rec->guid); 255 zpf(" txg: %llu", rec->txg); 256 zpf(" offset: %llu", rec->offset); 257 zpf(" length: %llu", rec->length); 258 znl(); 259 } else { 260 printf("%s %s: guid=%llu offset=%llu length=%llu\n", 261 ct, zev_op_name[rec->op - ZEV_OP_MIN], 262 rec->guid, 263 rec->offset, 264 rec->length); 265 } 266 } 267 268 static void 269 zev_print_zvol_write(char *buf) 270 { 271 zev_print_zvol_truncate(buf); 272 } 273 274 static void 275 zev_print_znode_close_after_update(char *buf) 276 { 277 zev_znode_close_after_update_t *rec = 278 (zev_znode_close_after_update_t *)buf; 279 time_t op_time = rec->op_time; 280 char *ct = ctime(&op_time); ct[24] = '\0'; 281 282 if (verbose) { 283 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 284 zpf(" guid: %llu", rec->guid); 285 zev_print_inode_info("file", &rec->file); 286 znl(); 287 } else { 288 printf("%s %s: guid=%llu file=%llu.%llu\n", 289 ct, zev_op_name[rec->op - ZEV_OP_MIN], 290 rec->guid, 291 rec->file.ino, rec->file.gen); 292 } 293 } 294 295 static void 296 zev_print_znode_create(char *buf) 297 { 298 zev_znode_create_t *rec = (zev_znode_create_t *)buf; 299 time_t op_time = rec->op_time; 300 char *ct = ctime(&op_time); ct[24] = '\0'; 301 302 if (verbose) { 303 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 304 zpf(" guid: %llu", rec->guid); 305 zpf(" txg: %llu", rec->txg); 306 zpf(" name: '%s'", ZEV_NAME(rec)); 307 zev_print_inode_info("file", &rec->file); 308 zev_print_inode_info("parent", &rec->parent); 309 znl(); 310 } else { 311 printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 312 "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 313 ct, zev_op_name[rec->op - ZEV_OP_MIN], 314 rec->guid, 315 rec->parent.ino, rec->parent.gen, 316 rec->file.ino, rec->file.gen, 317 rec->file.mtime, rec->parent.mtime, 318 ZEV_NAME(rec)); 319 } 320 } 321 322 static void 323 zev_print_znode_mkdir(char *buf) 324 { 325 zev_print_znode_create(buf); 326 } 327 328 static void 329 zev_print_znode_make_xattr_dir(char *buf) 330 { 331 zev_print_znode_create(buf); 332 } 333 334 static void 335 zev_print_znode_remove(char *buf) 336 { 337 zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 338 time_t op_time = rec->op_time; 339 char *ct = ctime(&op_time); ct[24] = '\0'; 340 341 if (verbose) { 342 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 343 zpf(" guid: %llu", rec->guid); 344 zpf(" txg: %llu", rec->txg); 345 zpf(" file.name: '%s'", ZEV_NAME(rec)); 346 zev_print_inode_info("file", &rec->file); 347 zev_print_inode_info("parent", &rec->parent); 348 znl(); 349 } else { 350 printf("%s %s: guid=%llu parent=%llu.%llu " 351 "file.mtime=%llu name='%s'\n", 352 ct, zev_op_name[rec->op - ZEV_OP_MIN], 353 rec->guid, 354 rec->parent.ino, rec->parent.gen, 355 rec->file.mtime, 356 ZEV_NAME(rec)); 357 } 358 } 359 360 static void 361 zev_print_znode_rmdir(char *buf) 362 { 363 zev_print_znode_remove(buf); 364 } 365 366 static void 367 zev_print_znode_link(char *buf) 368 { 369 zev_znode_link_t *rec = (zev_znode_link_t *)buf; 370 time_t op_time = rec->op_time; 371 char *ct = ctime(&op_time); ct[24] = '\0'; 372 373 if (verbose) { 374 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 375 zpf(" guid: %llu", rec->guid); 376 zpf(" txg: %llu", rec->txg); 377 zpf(" link.name: '%s'", ZEV_NAME(rec)); 378 zev_print_inode_info("file", &rec->file); 379 zev_print_inode_info("parent", &rec->parent); 380 znl(); 381 } else { 382 printf("%s %s: parent=%llu.%llu file=%llu.%llu " 383 "file.ctime=%llu parent.ctime=%llu name='%s'\n", 384 ct, zev_op_name[rec->op - ZEV_OP_MIN], 385 rec->parent.ino, rec->parent.gen, 386 rec->file.ino, rec->file.gen, 387 rec->file.ctime, rec->parent.ctime, 388 ZEV_NAME(rec)); 389 } 390 } 391 392 static void 393 zev_print_znode_symlink(char *buf) 394 { 395 zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 396 time_t op_time = rec->op_time; 397 char *ct = ctime(&op_time); ct[24] = '\0'; 398 399 if (verbose) { 400 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 401 zpf(" guid: %llu", rec->guid); 402 zpf(" txg: %llu", rec->txg); 403 zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 404 zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 405 zev_print_inode_info("file", &rec->file); 406 zev_print_inode_info("parent", &rec->parent); 407 znl(); 408 } else { 409 printf("%s %s: parent=%llu.%llu file=%llu.%llu " 410 "name='%s' link='%s'\n", 411 ct, zev_op_name[rec->op - ZEV_OP_MIN], 412 rec->parent.ino, rec->parent.gen, 413 rec->file.ino, rec->file.gen, 414 ZEV_NAME(rec), 415 ZEV_LINK(rec)); 416 } 417 } 418 419 static void 420 zev_print_znode_rename(char *buf) 421 { 422 zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 423 time_t op_time = rec->op_time; 424 char *ct = ctime(&op_time); ct[24] = '\0'; 425 426 if (verbose) { 427 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 428 zpf(" guid: %llu", rec->guid); 429 zpf(" txg: %llu", rec->txg); 430 zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 431 zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 432 zev_print_inode_info("file", &rec->file); 433 zev_print_inode_info("srcdir", &rec->srcdir); 434 zev_print_inode_info("dstdir", &rec->dstdir); 435 znl(); 436 } else { 437 printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 438 "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 439 "srcdir.mtime=%llu, srcdir.ctime=%llu, " 440 "dstdir.mtime=%llu, dstdir.ctime=%llu, " 441 "srcname='%s' dstname='%s'\n", 442 ct, zev_op_name[rec->op - ZEV_OP_MIN], 443 rec->srcdir.ino, rec->srcdir.gen, 444 rec->dstdir.ino, rec->dstdir.gen, 445 rec->file.ino, rec->file.gen, 446 rec->file.mtime, rec->file.ctime, 447 rec->srcdir.mtime, rec->srcdir.ctime, 448 rec->dstdir.mtime, rec->dstdir.ctime, 449 ZEV_SRCNAME(rec), 450 ZEV_DSTNAME(rec)); 451 } 452 } 453 454 static void 455 sig2hex_direct(const uint8_t *sig, char *hex) 456 { 457 int i; 458 459 for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 460 sprintf(hex + 2 * i, "%02x", sig[i]); 461 } 462 hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 463 } 464 465 static void 466 zev_print_znode_write(char *buf) 467 { 468 zev_znode_write_t *rec = (zev_znode_write_t *)buf; 469 time_t op_time = rec->op_time; 470 char *ct = ctime(&op_time); ct[24] = '\0'; 471 zev_sig_t *sig; 472 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 473 int i; 474 475 if (verbose) { 476 zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 477 zpf(" guid: %llu", rec->guid); 478 zpf(" txg: %llu", rec->txg); 479 zpf(" offset: %llu", rec->offset); 480 zpf(" length: %llu", rec->length); 481 zev_print_inode_info("file", &rec->file); 482 znl(); 483 for (i=0; i<rec->signature_cnt; i++) { 484 sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 485 sig += i; 486 sig2hex_direct(sig->value, sigval); 487 printf(" sig: level %d, offset %llu, value %s\n", 488 sig->level, sig->block_offset, sigval); 489 } 490 } else { 491 printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 492 ct, zev_op_name[rec->op - ZEV_OP_MIN], 493 rec->file.ino, rec->file.gen, 494 rec->offset, rec->length); 495 } 496 } 497 498 static void 499 zev_print_znode_truncate(char *buf) 500 { 501 zev_print_znode_write(buf); 502 } 503 504 static void 505 zev_print_znode_setattr(char *buf) 506 { 507 zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 508 time_t op_time = rec->op_time; 509 char *ct = ctime(&op_time); ct[24] = '\0'; 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 zev_print_inode_info("file", &rec->file); 516 znl(); 517 } else { 518 printf("%s %s: file=%llu.%llu mtime=%llu\n", 519 ct, zev_op_name[rec->op - ZEV_OP_MIN], 520 rec->file.ino, rec->file.gen, rec->file.mtime); 521 } 522 } 523 524 static void 525 zev_print_znode_acl(char *buf) 526 { 527 zev_print_znode_setattr(buf); 528 } 529 530 static void 531 zev_print_event(char *buf, int len) 532 { 533 int record_len; 534 int op; 535 536 record_len = *(uint32_t *)buf; 537 if (record_len != len) { 538 fprintf(stderr, "record length mismatch: got %d, expected %d\n", 539 record_len, len); 540 exit(1); 541 } 542 op = *((uint32_t *)buf + 1); 543 if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 544 fprintf(stderr, "unknown op code: %d\n", op); 545 exit(1); 546 } 547 switch (op) { 548 case ZEV_OP_ERROR: 549 zev_print_error(buf); 550 break; 551 case ZEV_OP_MARK: 552 zev_print_mark(buf); 553 break; 554 case ZEV_OP_ZFS_MOUNT: 555 zev_print_zfs_mount(buf); 556 break; 557 case ZEV_OP_ZFS_UMOUNT: 558 zev_print_zfs_umount(buf); 559 break; 560 case ZEV_OP_ZVOL_TRUNCATE: 561 zev_print_zvol_truncate(buf); 562 break; 563 case ZEV_OP_ZVOL_WRITE: 564 zev_print_zvol_write(buf); 565 break; 566 case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 567 zev_print_znode_close_after_update(buf); 568 break; 569 case ZEV_OP_ZNODE_CREATE: 570 zev_print_znode_create(buf); 571 break; 572 case ZEV_OP_ZNODE_MKDIR: 573 zev_print_znode_mkdir(buf); 574 break; 575 case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 576 zev_print_znode_make_xattr_dir(buf); 577 break; 578 case ZEV_OP_ZNODE_REMOVE: 579 zev_print_znode_remove(buf); 580 break; 581 case ZEV_OP_ZNODE_RMDIR: 582 zev_print_znode_rmdir(buf); 583 break; 584 case ZEV_OP_ZNODE_LINK: 585 zev_print_znode_link(buf); 586 break; 587 case ZEV_OP_ZNODE_SYMLINK: 588 zev_print_znode_symlink(buf); 589 break; 590 case ZEV_OP_ZNODE_RENAME: 591 zev_print_znode_rename(buf); 592 break; 593 case ZEV_OP_ZNODE_WRITE: 594 zev_print_znode_write(buf); 595 break; 596 case ZEV_OP_ZNODE_TRUNCATE: 597 zev_print_znode_truncate(buf); 598 break; 599 case ZEV_OP_ZNODE_SETATTR: 600 zev_print_znode_setattr(buf); 601 break; 602 case ZEV_OP_ZNODE_ACL: 603 zev_print_znode_acl(buf); 604 break; 605 default: 606 fprintf(stderr, "unhandled op code: %d\n", op); 607 exit(1); 608 } 609 } 610 611 static int 612 zev_poll_events(int fd, int create_tmp_queue) 613 { 614 struct pollfd pfd[1]; 615 int ret; 616 char buf[4096]; 617 zev_event_t *ev; 618 int off = 0; 619 zev_ioctl_add_queue_t aq; 620 int q_fd; 621 622 if (create_tmp_queue) { 623 aq.zev_max_queue_len = 0; 624 aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 625 snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 626 "zevadm.%ld.%ld", time(NULL), getpid()); 627 aq.zev_namelen = strlen(aq.zev_name); 628 629 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 630 perror("adding temporary queue failed"); 631 return (EXIT_FAILURE); 632 } 633 634 snprintf(buf, sizeof(buf), 635 "/devices/pseudo/zev@0:%s", aq.zev_name); 636 q_fd = open(buf, O_RDONLY); 637 if (q_fd < 0) { 638 perror("opening queue device failed"); 639 return (EXIT_FAILURE); 640 } 641 } else { 642 q_fd = fd; 643 } 644 645 while (1) { 646 pfd[0].fd = q_fd; 647 pfd[0].events = POLLIN; 648 ret = poll(pfd, 1, 1000); 649 if (ret < 0) { 650 perror("poll failed"); 651 close(q_fd); 652 return(EXIT_FAILURE); 653 } 654 if (!(pfd[0].revents & POLLIN)) 655 continue; 656 /* data available */ 657 ret = read(q_fd, buf, sizeof(buf)); 658 if (ret < 0) { 659 perror("read failed"); 660 close(q_fd); 661 return(EXIT_FAILURE); 662 } 663 if (ret == 0) 664 continue; 665 while (ret > off) { 666 ev = (zev_event_t *)(buf + off); 667 zev_print_event(buf + off, ev->header.record_len); 668 off += ev->header.record_len; 669 } 670 off = 0; 671 } 672 if (create_tmp_queue) 673 close(q_fd); 674 return EXIT_SUCCESS; 675 } 676 677 static void 678 usage(char *progname) 679 { 680 fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 681 fprintf(stderr, "\n"); 682 fprintf(stderr, " Status information:\n"); 683 fprintf(stderr, " -s show zev statistics\n"); 684 fprintf(stderr, " -p poll for ZFS events\n"); 685 fprintf(stderr, " -D print zev module debug " 686 "information\n"); 687 fprintf(stderr, "\n"); 688 fprintf(stderr, " Tune zev module settings:\n"); 689 fprintf(stderr, " -Q <bytes> set maximum event queue " 690 "length\n"); 691 fprintf(stderr, " -m <pool> mute pool, no events for " 692 "this pool\n"); 693 fprintf(stderr, " -M <pool> unmute pool\n"); 694 fprintf(stderr, "\n"); 695 fprintf(stderr, " Queue management:\n"); 696 fprintf(stderr, " -l list queues\n"); 697 fprintf(stderr, " -a <name> add non-blocking queue\n"); 698 fprintf(stderr, " -A <name> add blocking queue\n"); 699 fprintf(stderr, " -r <name> remove queue\n"); 700 fprintf(stderr, " -b <name> make queue non-blocking " 701 "(default)\n"); 702 fprintf(stderr, " -B <name> make queue block when full\n"); 703 fprintf(stderr, " -P <name> display queue properties\n"); 704 fprintf(stderr, " -L <name> <bytes> set maximum event queue " 705 "length\n"); 706 fprintf(stderr, " -t <name> <bytes> set queue length poll " 707 "throttle\n"); 708 fprintf(stderr, "\n"); 709 fprintf(stderr, " Other options:\n"); 710 fprintf(stderr, " -d <dev> non-default device file. " 711 "('%s')\n", ZEV_DEVICE); 712 fprintf(stderr, " -q <name> use device file for this " 713 "queue name\n"); 714 fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 715 fprintf(stderr, " -c <filename> list file's content " 716 "checksums\n"); 717 fprintf(stderr, " -v verbose: additional output " 718 "for some operations\n"); 719 fprintf(stderr, " -g grep-friendly event output, " 720 "one event per line\n"); 721 exit (EXIT_FAILURE); 722 } 723 724 static int 725 zev_add_queue(int fd, char *arg, int blocking) 726 { 727 zev_ioctl_add_queue_t aq; 728 int namelen; 729 730 namelen = strlen(arg); 731 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 732 fprintf(stderr, "queue name too long: %s\n", arg); 733 return (EXIT_FAILURE); 734 } 735 736 aq.zev_namelen = namelen; 737 strcpy(aq.zev_name, arg); 738 aq.zev_flags = ZEV_FL_PERSISTENT; 739 if (blocking) { 740 aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 741 aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 742 } else { 743 aq.zev_max_queue_len = (1024 * 1024); 744 } 745 746 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 747 perror("adding queue failed"); 748 return (EXIT_FAILURE); 749 } 750 return (0); 751 } 752 753 static int 754 zev_remove_queue(int fd, char *arg) 755 { 756 zev_ioctl_remove_queue_t aq; 757 int namelen; 758 759 namelen = strlen(arg); 760 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 761 fprintf(stderr, "queue name too long: %s\n", arg); 762 return (EXIT_FAILURE); 763 } 764 765 aq.zev_queue_name.zev_namelen = namelen; 766 strcpy(aq.zev_queue_name.zev_name, arg); 767 768 if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 769 perror("removing queue failed"); 770 return (EXIT_FAILURE); 771 } 772 return (0); 773 } 774 775 static int 776 zev_set_global_max_queue_len(int fd, char *arg) 777 { 778 uint64_t maxqueuelen; 779 780 errno = 0; 781 maxqueuelen = strtol(arg, (char **)NULL, 10); 782 if (errno) { 783 fprintf(stderr, "invalid queue length parameter: %s\n", arg); 784 return (EXIT_FAILURE); 785 } 786 if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 787 perror("setting max queue length failed"); 788 return (EXIT_FAILURE); 789 } 790 return (0); 791 } 792 793 static int 794 zev_mute_unmute_impl(int fd, char *poolname, int mute) 795 { 796 zev_ioctl_poolarg_t pa; 797 int len; 798 int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 799 len = strlen(poolname); 800 if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 801 fprintf(stderr, "invalid poolname: %s\n", poolname); 802 return (EXIT_FAILURE); 803 } 804 strcpy(pa.zev_poolname, poolname); 805 pa.zev_poolname_len = len; 806 if (ioctl(fd, op, &pa)) { 807 perror("muting pool data failed"); 808 return (EXIT_FAILURE); 809 } 810 return (0); 811 } 812 813 int 814 zev_mute_pool(int fd, char *poolname) 815 { 816 return zev_mute_unmute_impl(fd, poolname, 1); 817 } 818 819 int 820 zev_unmute_pool(int fd, char *poolname) 821 { 822 return zev_mute_unmute_impl(fd, poolname, 0); 823 } 824 825 static int 826 zev_debug_info(int fd) 827 { 828 zev_ioctl_debug_info_t di; 829 830 if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 831 perror("getting zev debug info failed"); 832 return (EXIT_FAILURE); 833 } 834 835 printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 836 printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 837 printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 838 printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 839 return 0; 840 } 841 842 static int 843 zev_mark(int fd, char *arg) 844 { 845 zev_ioctl_mark_t *mark; 846 uint64_t guid; 847 int len; 848 char *p; 849 850 p = strchr(arg, ':'); 851 if (!p) { 852 fprintf(stderr, "expected value is <guid>:<payload>, " 853 "e.g. '123:hello'\n"); 854 exit (EXIT_FAILURE); 855 } 856 *p = '\n'; 857 p++; 858 859 errno = 0; 860 guid = strtoll(arg, (char **)NULL, 10); 861 if (errno) { 862 fprintf(stderr, "guid must be a number.\n"); 863 exit (EXIT_FAILURE); 864 } 865 866 len = strlen(p); 867 868 mark = malloc(sizeof(*mark) + len + 1); 869 if (!mark) { 870 fprintf(stderr, "can't allocate mark structure: %s\n", 871 strerror(errno)); 872 exit (EXIT_FAILURE); 873 } 874 mark->zev_guid = guid; 875 mark->zev_mark_id = 0; 876 mark->zev_payload_len = len; 877 strcpy(ZEV_PAYLOAD(mark), p); 878 879 if (ioctl(fd, ZEV_IOC_MARK, mark)) { 880 perror("queueing mark failed"); 881 return (EXIT_FAILURE); 882 } 883 884 printf("mark id: %lu\n", mark->zev_mark_id); 885 return (0); 886 } 887 888 static int 889 zev_queue_blocking(int fd, char *arg, int block) 890 { 891 zev_ioctl_get_queue_properties_t gqp; 892 893 gqp.zev_queue_name.zev_namelen = strlen(arg); 894 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 895 fprintf(stderr, "queue name too long.\n"); 896 return EXIT_FAILURE; 897 } 898 strcpy(gqp.zev_queue_name.zev_name, arg); 899 900 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 901 perror("getting queue properties failed"); 902 return (EXIT_FAILURE); 903 } 904 if (block) { 905 gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 906 } else { 907 gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 908 } 909 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 910 perror("setting queue properties failed"); 911 return (EXIT_FAILURE); 912 } 913 return (0); 914 } 915 916 static int 917 zev_set_max_queue_len(int fd, char *arg, char *len) 918 { 919 zev_ioctl_get_queue_properties_t gqp; 920 921 if (!len) { 922 fprintf(stderr, "queue size parameter missing.\n"); 923 return EXIT_FAILURE; 924 } 925 926 gqp.zev_queue_name.zev_namelen = strlen(arg); 927 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 928 fprintf(stderr, "queue name too long.\n"); 929 return EXIT_FAILURE; 930 } 931 strcpy(gqp.zev_queue_name.zev_name, arg); 932 933 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 934 perror("getting queue properties failed"); 935 return (EXIT_FAILURE); 936 } 937 gqp.zev_max_queue_len = atol(len); 938 if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 939 fprintf(stderr, "queue size parameter garbled.\n"); 940 return (EXIT_FAILURE); 941 } 942 if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 943 fprintf(stderr, "queue size parameter out of bounds.\n"); 944 return (EXIT_FAILURE); 945 } 946 947 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 948 perror("setting queue properties failed"); 949 return (EXIT_FAILURE); 950 } 951 return (0); 952 } 953 954 static int 955 zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 956 { 957 zev_ioctl_get_queue_properties_t gqp; 958 959 if (!len) { 960 fprintf(stderr, "poll throttle parameter missing.\n"); 961 return EXIT_FAILURE; 962 } 963 964 gqp.zev_queue_name.zev_namelen = strlen(arg); 965 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 966 fprintf(stderr, "queue name too long.\n"); 967 return EXIT_FAILURE; 968 } 969 strcpy(gqp.zev_queue_name.zev_name, arg); 970 971 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 972 perror("getting queue properties failed"); 973 return (EXIT_FAILURE); 974 } 975 gqp.zev_poll_wakeup_threshold = atol(len); 976 if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 977 fprintf(stderr, "poll throttle parameter garbled.\n"); 978 return (EXIT_FAILURE); 979 } 980 if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 981 fprintf(stderr, "poll throttle parameter out of bounds.\n"); 982 return (EXIT_FAILURE); 983 } 984 985 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 986 perror("setting queue properties failed"); 987 return (EXIT_FAILURE); 988 } 989 return (0); 990 } 991 992 static int 993 zev_queue_properties(int fd, char *arg) 994 { 995 zev_ioctl_get_queue_properties_t gqp; 996 997 gqp.zev_queue_name.zev_namelen = strlen(arg); 998 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 999 fprintf(stderr, "queue name too long.\n"); 1000 return EXIT_FAILURE; 1001 } 1002 strcpy(gqp.zev_queue_name.zev_name, arg); 1003 1004 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1005 perror("getting queue properties failed"); 1006 return (EXIT_FAILURE); 1007 } 1008 1009 printf("queue : %s\n", arg); 1010 printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1011 printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1012 printf("persistent : %s\n", 1013 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1014 printf("blocking : %s\n", 1015 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1016 1017 return (0); 1018 } 1019 1020 static int 1021 zev_list_queues(int fd) 1022 { 1023 zev_ioctl_get_queue_properties_t gqp; 1024 zev_ioctl_get_queue_list_t gql; 1025 zev_ioctl_get_queue_statistics_t gs; 1026 uint64_t i; 1027 char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1028 1029 if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1030 perror("getting queue list failed"); 1031 return (EXIT_FAILURE); 1032 } 1033 1034 printf("Name Size " 1035 "Max Size Wakeup Per Block\n"); 1036 1037 for (i=0; i<gql.zev_n_queues; i++) { 1038 strncpy(name, gql.zev_queue_name[i].zev_name, 1039 ZEV_MAX_QUEUE_NAME_LEN); 1040 name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1041 1042 memcpy(gqp.zev_queue_name.zev_name, 1043 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1044 gqp.zev_queue_name.zev_namelen = 1045 gql.zev_queue_name[i].zev_namelen; 1046 1047 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1048 if (errno == ENOENT) 1049 continue; 1050 perror("getting queue properties failed"); 1051 return (EXIT_FAILURE); 1052 } 1053 1054 memcpy(gs.zev_queue_name.zev_name, 1055 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 1056 gs.zev_queue_name.zev_namelen = 1057 gql.zev_queue_name[i].zev_namelen; 1058 1059 if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1060 if (errno == ENOENT) 1061 continue; 1062 perror("getting statistics data failed"); 1063 return (EXIT_FAILURE); 1064 } 1065 1066 printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1067 " %-3s %-3s\n", 1068 name, 1069 gs.zev_statistics.zev_queue_len, 1070 gqp.zev_max_queue_len, 1071 gqp.zev_poll_wakeup_threshold, 1072 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1073 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1074 "yes" : "no"); 1075 } 1076 1077 return (0); 1078 } 1079 1080 static int 1081 zev_checksum(int dev_fd, char *filename) 1082 { 1083 int fd; 1084 offset_t off; 1085 offset_t data; 1086 zev_sig_t *sig; 1087 char *buf; 1088 zev_ioctl_get_signatures_t *gs; 1089 int i; 1090 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 1091 int buf_size; 1092 1093 /* control struct, one lv1 signature and up to 256 lv0 signatures */ 1094 buf_size = (1 + 256) * sizeof(zev_sig_t); 1095 buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 1096 if (!buf) { 1097 perror("can't allocate checksum buffer"); 1098 return (EXIT_FAILURE); 1099 } 1100 1101 fd = open(filename, O_RDONLY); 1102 if (fd < 0) { 1103 perror("can't open file"); 1104 return (EXIT_FAILURE); 1105 } 1106 1107 gs = (zev_ioctl_get_signatures_t *)buf; 1108 gs->zev_fd = fd; 1109 gs->zev_bufsize = buf_size; 1110 1111 off = 0; 1112 data = 0; 1113 while (1) { 1114 errno = 0; 1115 data = llseek(fd, off, SEEK_DATA); 1116 if (data < 0) { 1117 if (errno == ENXIO) /* no more data */ 1118 break; 1119 perror("llseek failed"); 1120 goto err; 1121 } 1122 data = P2ALIGN(data, ZEV_L1_SIZE); 1123 off = data + ZEV_L1_SIZE; 1124 1125 gs->zev_offset = data; 1126 gs->zev_len = ZEV_L1_SIZE; 1127 1128 if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 1129 perror("ioctl to get signatures failed"); 1130 goto err; 1131 } 1132 1133 for (i=0; i<gs->zev_signature_cnt; i++) { 1134 sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 1135 sig += i; 1136 sig2hex_direct(sig->value, sigval); 1137 printf("level %d, offset %llu, value %s\n", 1138 sig->level, sig->block_offset, sigval); 1139 } 1140 } 1141 1142 free(buf); 1143 close(fd); 1144 return 0; 1145 err: 1146 free(buf); 1147 close(fd); 1148 return (EXIT_FAILURE); 1149 } 1150 1151 int 1152 main(int argc, char **argv) 1153 { 1154 int fd; 1155 int c; 1156 extern char *optarg; 1157 int create_tmp_queue = 1; 1158 char buf[MAXPATHLEN]; 1159 1160 /* open device */ 1161 fd = open(zev_device, O_RDONLY); 1162 if (fd < 0) { 1163 perror("opening zev device failed"); 1164 return EXIT_FAILURE; 1165 } 1166 while ((c = getopt(argc, argv, 1167 "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 1168 switch(c) { 1169 case 'g': 1170 grep_friendly++; 1171 verbose++; 1172 break; 1173 case 'v': 1174 verbose++; 1175 break; 1176 case 's': 1177 return zev_statistics(fd); 1178 case 'p': 1179 return zev_poll_events(fd, create_tmp_queue); 1180 case 'c': 1181 return zev_checksum(fd, optarg); 1182 case 'D': 1183 return zev_debug_info(fd); 1184 case 'd': 1185 close(fd); 1186 zev_device = optarg; 1187 fd = open(zev_device, O_RDONLY); 1188 if (fd < 0) { 1189 perror("opening zev device failed"); 1190 return EXIT_FAILURE; 1191 } 1192 create_tmp_queue = 0; 1193 break; 1194 case 'q': 1195 snprintf(buf, sizeof(buf), 1196 "/devices/pseudo/zev@0:%s", optarg); 1197 close(fd); 1198 zev_device = buf; 1199 fd = open(zev_device, O_RDONLY); 1200 if (fd < 0) { 1201 perror("opening zev device failed"); 1202 return EXIT_FAILURE; 1203 } 1204 create_tmp_queue = 0; 1205 break; 1206 case 'l': 1207 return zev_list_queues(fd); 1208 case 'Q': 1209 return zev_set_global_max_queue_len(fd, optarg); 1210 case 'L': 1211 return zev_set_max_queue_len(fd, optarg, argv[optind]); 1212 case 't': 1213 return zev_set_poll_wakeup_queue_len(fd, optarg, 1214 argv[optind]); 1215 case 'm': 1216 return zev_mute_pool(fd, optarg); 1217 case 'M': 1218 return zev_unmute_pool(fd, optarg); 1219 case 'k': 1220 return zev_mark(fd, optarg); 1221 case 'a': 1222 return zev_add_queue(fd, optarg, 0); 1223 case 'A': 1224 return zev_add_queue(fd, optarg, 1); 1225 case 'r': 1226 return zev_remove_queue(fd, optarg); 1227 case 'b': 1228 return zev_queue_blocking(fd, optarg, 0); 1229 case 'B': 1230 return zev_queue_blocking(fd, optarg, 1); 1231 case 'P': 1232 return zev_queue_properties(fd, optarg); 1233 case 'h': 1234 case '?': 1235 default: 1236 usage(argv[0]); 1237 } 1238 } 1239 usage(argv[0]); 1240 close(fd); 1241 return EXIT_FAILURE; 1242 } 1243 1244