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