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 11 #define OP_STATISTICS (1 << 0) 12 #define OP_POLL_EVENTS (1 << 1) 13 #define OP_MUTE_POOL (1 << 2) 14 #define OP_UNMUTE_POOL (1 << 3) 15 #define OP_SET_MAX_QUEUE_LEN (1 << 4) 16 #define OP_DEBUG_INFO (1 << 5) 17 18 #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 19 20 static char *zev_device = ZEV_DEVICE; 21 22 static char *zev_op_name[] = { 23 "ZEV_OP_ERROR", 24 "ZEV_OP_MARK", 25 "ZEV_OP_ZFS_MOUNT", 26 "ZEV_OP_ZFS_UMOUNT", 27 "ZEV_OP_ZVOL_WRITE", 28 "ZEV_OP_ZVOL_TRUNCATE", 29 "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 30 "ZEV_OP_ZNODE_CREATE", 31 "ZEV_OP_ZNODE_MKDIR", 32 "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 33 "ZEV_OP_ZNODE_REMOVE", 34 "ZEV_OP_ZNODE_RMDIR", 35 "ZEV_OP_ZNODE_LINK", 36 "ZEV_OP_ZNODE_SYMLINK", 37 "ZEV_OP_ZNODE_RENAME", 38 "ZEV_OP_ZNODE_WRITE", 39 "ZEV_OP_ZNODE_TRUNCATE", 40 "ZEV_OP_ZNODE_SETATTR", 41 "ZEV_OP_ZNODE_ACL", 42 NULL 43 }; 44 45 static int verbose = 0; 46 47 static int 48 zev_statistics(int fd) 49 { 50 zev_statistics_t zs; 51 if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 52 perror("getting statistics data failed"); 53 return (EXIT_FAILURE); 54 } 55 printf("ZEV module state:\n"); 56 57 printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 58 printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 59 printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 60 printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 61 62 printf(" discarded events : %lu\n", 63 zs.zev_cnt_discarded_events); 64 printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 65 66 printf("ZFS event statistics:\n"); 67 68 printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 69 printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 70 printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 71 printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 72 printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 73 printf(" ZNODE close after update: %lu\n", 74 zs.zev_cnt_znode_close_after_update); 75 printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 76 printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 77 printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 78 printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 79 printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 80 printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 81 printf(" ZNODE truncate : %lu\n", 82 zs.zev_cnt_znode_truncate); 83 printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 84 printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 85 return EXIT_SUCCESS; 86 } 87 88 static void 89 zev_print_error(char *buf) 90 { 91 zev_error_t *rec = (zev_error_t *)buf; 92 time_t op_time = rec->op_time; 93 char *ct = ctime(&op_time); ct[24] = '\0'; 94 95 printf("%s %s: failed_op=%s msg=%s\n", 96 ct, zev_op_name[rec->op - ZEV_OP_MIN], 97 zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 98 } 99 100 static void 101 zev_print_mark(char *buf) 102 { 103 zev_mark_t *rec = (zev_mark_t *)buf; 104 time_t op_time = rec->op_time; 105 char *ct = ctime(&op_time); ct[24] = '\0'; 106 107 printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 108 ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id, 109 rec->payload_len); 110 } 111 112 static void 113 zev_print_zfs_mount(char *buf) 114 { 115 zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 116 time_t op_time = rec->op_time; 117 char *ct = ctime(&op_time); ct[24] = '\0'; 118 119 printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 120 ct, zev_op_name[rec->op - ZEV_OP_MIN], 121 rec->guid, 122 rec->remount ? "true" : "false", 123 ZEV_DATASET(rec), 124 ZEV_MOUNTPOINT(rec)); 125 } 126 127 static void 128 zev_print_zfs_umount(char *buf) 129 { 130 zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 131 time_t op_time = rec->op_time; 132 char *ct = ctime(&op_time); ct[24] = '\0'; 133 134 printf("%s %s: guid=%llu\n", 135 ct, zev_op_name[rec->op - ZEV_OP_MIN], 136 rec->guid); 137 } 138 139 static void 140 zev_print_zvol_truncate(char *buf) 141 { 142 zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 143 time_t op_time = rec->op_time; 144 char *ct = ctime(&op_time); ct[24] = '\0'; 145 146 printf("%s %s: guid=%llu offset=%llu length=%llu\n", 147 ct, zev_op_name[rec->op - ZEV_OP_MIN], 148 rec->guid, 149 rec->offset, 150 rec->length); 151 } 152 153 static void 154 zev_print_zvol_write(char *buf) 155 { 156 zev_print_zvol_truncate(buf); 157 } 158 159 static void 160 zev_print_znode_close_after_update(char *buf) 161 { 162 zev_znode_close_after_update_t *rec = 163 (zev_znode_close_after_update_t *)buf; 164 time_t op_time = rec->op_time; 165 char *ct = ctime(&op_time); ct[24] = '\0'; 166 167 printf("%s %s: guid=%llu file=%llu.%llu\n", 168 ct, zev_op_name[rec->op - ZEV_OP_MIN], 169 rec->guid, 170 rec->file.ino, rec->file.gen); 171 } 172 173 static void 174 zev_print_znode_create(char *buf) 175 { 176 zev_znode_create_t *rec = (zev_znode_create_t *)buf; 177 time_t op_time = rec->op_time; 178 char *ct = ctime(&op_time); ct[24] = '\0'; 179 180 printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 181 "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 182 ct, zev_op_name[rec->op - ZEV_OP_MIN], 183 rec->guid, 184 rec->parent.ino, rec->parent.gen, 185 rec->file.ino, rec->file.gen, 186 rec->file.mtime, rec->parent.mtime, 187 ZEV_NAME(rec)); 188 } 189 190 static void 191 zev_print_znode_mkdir(char *buf) 192 { 193 zev_print_znode_create(buf); 194 } 195 196 static void 197 zev_print_znode_make_xattr_dir(char *buf) 198 { 199 zev_print_znode_create(buf); 200 } 201 202 static void 203 zev_print_znode_remove(char *buf) 204 { 205 zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 206 time_t op_time = rec->op_time; 207 char *ct = ctime(&op_time); ct[24] = '\0'; 208 209 printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n", 210 ct, zev_op_name[rec->op - ZEV_OP_MIN], 211 rec->guid, 212 rec->parent.ino, rec->parent.gen, 213 rec->file.mtime, 214 ZEV_NAME(rec)); 215 } 216 217 static void 218 zev_print_znode_rmdir(char *buf) 219 { 220 zev_print_znode_remove(buf); 221 } 222 223 static void 224 zev_print_znode_link(char *buf) 225 { 226 zev_znode_link_t *rec = (zev_znode_link_t *)buf; 227 time_t op_time = rec->op_time; 228 char *ct = ctime(&op_time); ct[24] = '\0'; 229 230 printf("%s %s: parent=%llu.%llu file=%llu.%llu " 231 "file.ctime=%llu parent.ctime=%llu name='%s'\n", 232 ct, zev_op_name[rec->op - ZEV_OP_MIN], 233 rec->parent.ino, rec->parent.gen, 234 rec->file.ino, rec->file.gen, 235 rec->file.ctime, rec->parent.ctime, 236 ZEV_NAME(rec)); 237 printf("links: %d\n", rec->file.links); 238 } 239 240 static void 241 zev_print_znode_symlink(char *buf) 242 { 243 zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 244 time_t op_time = rec->op_time; 245 char *ct = ctime(&op_time); ct[24] = '\0'; 246 247 printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 248 ct, zev_op_name[rec->op - ZEV_OP_MIN], 249 rec->parent.ino, rec->parent.gen, 250 rec->file.ino, rec->file.gen, 251 ZEV_NAME(rec), 252 ZEV_LINK(rec)); 253 } 254 255 static void 256 zev_print_znode_rename(char *buf) 257 { 258 zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 259 time_t op_time = rec->op_time; 260 char *ct = ctime(&op_time); ct[24] = '\0'; 261 262 printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 263 "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 264 "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 265 "srcname='%s' dstname='%s'\n", 266 ct, zev_op_name[rec->op - ZEV_OP_MIN], 267 rec->srcdir.ino, rec->srcdir.gen, 268 rec->dstdir.ino, rec->dstdir.gen, 269 rec->file.ino, rec->file.gen, 270 rec->file.mtime, rec->file.ctime, 271 rec->srcdir.mtime, rec->srcdir.ctime, 272 rec->dstdir.mtime, rec->dstdir.ctime, 273 ZEV_SRCNAME(rec), 274 ZEV_DSTNAME(rec)); 275 } 276 277 static void 278 sig2hex_direct(const uint8_t *sig, char *hex) 279 { 280 int i; 281 282 for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 283 sprintf(hex + 2 * i, "%02x", sig[i]); 284 } 285 hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 286 } 287 288 static void 289 zev_print_znode_write(char *buf) 290 { 291 zev_znode_write_t *rec = (zev_znode_write_t *)buf; 292 time_t op_time = rec->op_time; 293 char *ct = ctime(&op_time); ct[24] = '\0'; 294 zev_sig_t *sig; 295 char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 296 int i; 297 298 printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 299 ct, zev_op_name[rec->op - ZEV_OP_MIN], 300 rec->file.ino, rec->file.gen, 301 rec->offset, rec->length); 302 if (verbose) { 303 for (i=0; i<rec->signature_cnt; i++) { 304 sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 305 sig += i; 306 sig2hex_direct(sig->value, sigval); 307 printf(" sig: level %d, offset %llu, value %s\n", 308 sig->level, sig->block_offset, sigval); 309 } 310 } 311 } 312 313 static void 314 zev_print_znode_truncate(char *buf) 315 { 316 zev_print_znode_write(buf); 317 } 318 319 static void 320 zev_print_znode_setattr(char *buf) 321 { 322 zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 323 time_t op_time = rec->op_time; 324 char *ct = ctime(&op_time); ct[24] = '\0'; 325 326 printf("%s %s: file=%llu.%llu mtime=%llu\n", 327 ct, zev_op_name[rec->op - ZEV_OP_MIN], 328 rec->file.ino, rec->file.gen, rec->file.mtime); 329 } 330 331 static void 332 zev_print_znode_acl(char *buf) 333 { 334 zev_print_znode_setattr(buf); 335 } 336 337 static void 338 zev_print_event(char *buf, int len) 339 { 340 int record_len; 341 int op; 342 343 record_len = *(uint32_t *)buf; 344 if (record_len != len) { 345 fprintf(stderr, "record length mismatch: got %d, expected %d\n", 346 record_len, len); 347 exit(1); 348 } 349 op = *((uint32_t *)buf + 1); 350 if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 351 fprintf(stderr, "unknown op code: %d\n", op); 352 exit(1); 353 } 354 switch (op) { 355 case ZEV_OP_ERROR: 356 zev_print_error(buf); 357 break; 358 case ZEV_OP_MARK: 359 zev_print_mark(buf); 360 break; 361 case ZEV_OP_ZFS_MOUNT: 362 zev_print_zfs_mount(buf); 363 break; 364 case ZEV_OP_ZFS_UMOUNT: 365 zev_print_zfs_umount(buf); 366 break; 367 case ZEV_OP_ZVOL_TRUNCATE: 368 zev_print_zvol_truncate(buf); 369 break; 370 case ZEV_OP_ZVOL_WRITE: 371 zev_print_zvol_write(buf); 372 break; 373 case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 374 zev_print_znode_close_after_update(buf); 375 break; 376 case ZEV_OP_ZNODE_CREATE: 377 zev_print_znode_create(buf); 378 break; 379 case ZEV_OP_ZNODE_MKDIR: 380 zev_print_znode_mkdir(buf); 381 break; 382 case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 383 zev_print_znode_make_xattr_dir(buf); 384 break; 385 case ZEV_OP_ZNODE_REMOVE: 386 zev_print_znode_remove(buf); 387 break; 388 case ZEV_OP_ZNODE_RMDIR: 389 zev_print_znode_rmdir(buf); 390 break; 391 case ZEV_OP_ZNODE_LINK: 392 zev_print_znode_link(buf); 393 break; 394 case ZEV_OP_ZNODE_SYMLINK: 395 zev_print_znode_symlink(buf); 396 break; 397 case ZEV_OP_ZNODE_RENAME: 398 zev_print_znode_rename(buf); 399 break; 400 case ZEV_OP_ZNODE_WRITE: 401 zev_print_znode_write(buf); 402 break; 403 case ZEV_OP_ZNODE_TRUNCATE: 404 zev_print_znode_truncate(buf); 405 break; 406 case ZEV_OP_ZNODE_SETATTR: 407 zev_print_znode_setattr(buf); 408 break; 409 case ZEV_OP_ZNODE_ACL: 410 zev_print_znode_acl(buf); 411 break; 412 default: 413 fprintf(stderr, "unhandled op code: %d\n", op); 414 exit(1); 415 } 416 } 417 418 static int 419 zev_poll_events(int fd, int create_tmp_queue) 420 { 421 struct pollfd pfd[1]; 422 int ret; 423 char buf[4096]; 424 zev_event_t *ev; 425 int off = 0; 426 zev_ioctl_add_queue_t aq; 427 int q_fd; 428 429 if (create_tmp_queue) { 430 aq.zev_max_queue_len = 0; 431 aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 432 snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 433 "zevadm.%ld.%ld", time(NULL), getpid()); 434 aq.zev_namelen = strlen(aq.zev_name); 435 436 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 437 perror("adding temporary queue failed"); 438 return (EXIT_FAILURE); 439 } 440 441 snprintf(buf, sizeof(buf), 442 "/devices/pseudo/zev@0:%s", aq.zev_name); 443 q_fd = open(buf, O_RDONLY); 444 if (q_fd < 0) { 445 perror("opening queue device failed"); 446 return (EXIT_FAILURE); 447 } 448 } else { 449 q_fd = fd; 450 } 451 452 while (1) { 453 pfd[0].fd = q_fd; 454 pfd[0].events = POLLIN; 455 ret = poll(pfd, 1, 1000); 456 if (ret < 0) { 457 perror("poll failed"); 458 close(q_fd); 459 return(EXIT_FAILURE); 460 } 461 if (!(pfd[0].revents & POLLIN)) 462 continue; 463 /* data available */ 464 ret = read(q_fd, buf, sizeof(buf)); 465 if (ret < 0) { 466 perror("read failed"); 467 close(q_fd); 468 return(EXIT_FAILURE); 469 } 470 if (ret == 0) 471 continue; 472 while (ret > off) { 473 ev = (zev_event_t *)(buf + off); 474 zev_print_event(buf + off, ev->header.record_len); 475 off += ev->header.record_len; 476 } 477 off = 0; 478 } 479 if (create_tmp_queue) 480 close(q_fd); 481 return EXIT_SUCCESS; 482 } 483 484 static void 485 usage(char *progname) 486 { 487 fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 488 fprintf(stderr, "\n"); 489 fprintf(stderr, " Status information:\n"); 490 fprintf(stderr, " -s show zev statistics\n"); 491 fprintf(stderr, " -p poll for ZFS events\n"); 492 fprintf(stderr, " -D print zev module debug " 493 "information\n"); 494 fprintf(stderr, "\n"); 495 fprintf(stderr, " Tune zev module settings:\n"); 496 fprintf(stderr, " -Q <bytes> set maximum event queue " 497 "length\n"); 498 fprintf(stderr, " -m <pool> mute pool, no events for " 499 "this pool\n"); 500 fprintf(stderr, " -M <pool> unmute pool\n"); 501 fprintf(stderr, "\n"); 502 fprintf(stderr, " Queue management:\n"); 503 fprintf(stderr, " -l list queues\n"); 504 fprintf(stderr, " -a <name> add non-blocking queue\n"); 505 fprintf(stderr, " -A <name> add blocking queue\n"); 506 fprintf(stderr, " -r <name> remove queue\n"); 507 fprintf(stderr, " -b <name> make queue non-blocking " 508 "(default)\n"); 509 fprintf(stderr, " -B <name> make queue block when full\n"); 510 fprintf(stderr, " -P <name> display queue properties\n"); 511 fprintf(stderr, " -L <name> <bytes> set maximum event queue " 512 "length\n"); 513 fprintf(stderr, " -t <name> <bytes> set queue length poll " 514 "throttle\n"); 515 fprintf(stderr, "\n"); 516 fprintf(stderr, " Other options:\n"); 517 fprintf(stderr, " -d <dev> non-default device file. " 518 "('%s')\n", ZEV_DEVICE); 519 fprintf(stderr, " -q <name> use device file for this " 520 "queue name\n"); 521 fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 522 fprintf(stderr, " -v verbose: addition output " 523 "for some operations\n"); 524 exit (EXIT_FAILURE); 525 } 526 527 static int 528 zev_add_queue(int fd, char *arg, int blocking) 529 { 530 zev_ioctl_add_queue_t aq; 531 int namelen; 532 533 namelen = strlen(arg); 534 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 535 fprintf(stderr, "queue name too long: %s\n", arg); 536 return (EXIT_FAILURE); 537 } 538 539 aq.zev_namelen = namelen; 540 strcpy(aq.zev_name, arg); 541 aq.zev_flags = ZEV_FL_PERSISTENT; 542 if (blocking) { 543 aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 544 aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 545 } else { 546 aq.zev_max_queue_len = (1024 * 1024); 547 } 548 549 if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 550 perror("adding queue failed"); 551 return (EXIT_FAILURE); 552 } 553 return (0); 554 } 555 556 static int 557 zev_remove_queue(int fd, char *arg) 558 { 559 zev_ioctl_remove_queue_t aq; 560 int namelen; 561 562 namelen = strlen(arg); 563 if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 564 fprintf(stderr, "queue name too long: %s\n", arg); 565 return (EXIT_FAILURE); 566 } 567 568 aq.zev_queue_name.zev_namelen = namelen; 569 strcpy(aq.zev_queue_name.zev_name, arg); 570 571 if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 572 perror("removing queue failed"); 573 return (EXIT_FAILURE); 574 } 575 return (0); 576 } 577 578 static int 579 zev_set_global_max_queue_len(int fd, char *arg) 580 { 581 uint64_t maxqueuelen; 582 583 errno = 0; 584 maxqueuelen = strtol(arg, (char **)NULL, 10); 585 if (errno) { 586 fprintf(stderr, "invalid queue length parameter: %s\n", arg); 587 return (EXIT_FAILURE); 588 } 589 if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 590 perror("setting max queue length failed"); 591 return (EXIT_FAILURE); 592 } 593 return (0); 594 } 595 596 static int 597 zev_mute_unmute_impl(int fd, char *poolname, int mute) 598 { 599 zev_ioctl_poolarg_t pa; 600 int len; 601 int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 602 len = strlen(poolname); 603 if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 604 fprintf(stderr, "invalid poolname: %s\n", poolname); 605 return (EXIT_FAILURE); 606 } 607 strcpy(pa.zev_poolname, poolname); 608 pa.zev_poolname_len = len; 609 if (ioctl(fd, op, &pa)) { 610 perror("muting pool data failed"); 611 return (EXIT_FAILURE); 612 } 613 return (0); 614 } 615 616 int 617 zev_mute_pool(int fd, char *poolname) 618 { 619 return zev_mute_unmute_impl(fd, poolname, 1); 620 } 621 622 int 623 zev_unmute_pool(int fd, char *poolname) 624 { 625 return zev_mute_unmute_impl(fd, poolname, 0); 626 } 627 628 static int 629 zev_debug_info(int fd) 630 { 631 zev_ioctl_debug_info_t di; 632 633 if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 634 perror("getting zev debug info failed"); 635 return (EXIT_FAILURE); 636 } 637 638 printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 639 printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 640 printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 641 printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 642 return 0; 643 } 644 645 static int 646 zev_mark(int fd, char *arg) 647 { 648 zev_ioctl_mark_t *mark; 649 uint64_t guid; 650 int len; 651 char *p; 652 653 p = strchr(arg, ':'); 654 if (!p) { 655 fprintf(stderr, "expected value is <guid>:<payload>, " 656 "e.g. '123:hello'\n"); 657 exit (EXIT_FAILURE); 658 } 659 *p = '\n'; 660 p++; 661 662 errno = 0; 663 guid = strtoll(arg, (char **)NULL, 10); 664 if (errno) { 665 fprintf(stderr, "guid must be a number.\n"); 666 exit (EXIT_FAILURE); 667 } 668 669 len = strlen(p); 670 671 mark = malloc(sizeof(*mark) + len + 1); 672 if (!mark) { 673 fprintf(stderr, "can't allocate mark structure: %s\n", 674 strerror(errno)); 675 exit (EXIT_FAILURE); 676 } 677 mark->zev_guid = guid; 678 mark->zev_mark_id = 0; 679 mark->zev_payload_len = len; 680 strcpy(ZEV_PAYLOAD(mark), p); 681 682 if (ioctl(fd, ZEV_IOC_MARK, mark)) { 683 perror("queueing mark failed"); 684 return (EXIT_FAILURE); 685 } 686 687 printf("mark id: %lu\n", mark->zev_mark_id); 688 return (0); 689 } 690 691 static int 692 zev_queue_blocking(int fd, char *arg, int block) 693 { 694 zev_ioctl_get_queue_properties_t gqp; 695 696 gqp.zev_queue_name.zev_namelen = strlen(arg); 697 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 698 fprintf(stderr, "queue name too long.\n"); 699 return EXIT_FAILURE; 700 } 701 strcpy(gqp.zev_queue_name.zev_name, arg); 702 703 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 704 perror("getting queue properties failed"); 705 return (EXIT_FAILURE); 706 } 707 if (block) { 708 gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 709 } else { 710 gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 711 } 712 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 713 perror("setting queue properties failed"); 714 return (EXIT_FAILURE); 715 } 716 return (0); 717 } 718 719 static int 720 zev_set_max_queue_len(int fd, char *arg, char *len) 721 { 722 zev_ioctl_get_queue_properties_t gqp; 723 724 if (!len) { 725 fprintf(stderr, "queue size parameter missing.\n"); 726 return EXIT_FAILURE; 727 } 728 729 gqp.zev_queue_name.zev_namelen = strlen(arg); 730 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 731 fprintf(stderr, "queue name too long.\n"); 732 return EXIT_FAILURE; 733 } 734 strcpy(gqp.zev_queue_name.zev_name, arg); 735 736 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 737 perror("getting queue properties failed"); 738 return (EXIT_FAILURE); 739 } 740 gqp.zev_max_queue_len = atol(len); 741 if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 742 fprintf(stderr, "queue size parameter garbled.\n"); 743 return (EXIT_FAILURE); 744 } 745 if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 746 fprintf(stderr, "queue size parameter out of bounds.\n"); 747 return (EXIT_FAILURE); 748 } 749 750 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 751 perror("setting queue properties failed"); 752 return (EXIT_FAILURE); 753 } 754 return (0); 755 } 756 757 static int 758 zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 759 { 760 zev_ioctl_get_queue_properties_t gqp; 761 762 if (!len) { 763 fprintf(stderr, "poll throttle parameter missing.\n"); 764 return EXIT_FAILURE; 765 } 766 767 gqp.zev_queue_name.zev_namelen = strlen(arg); 768 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 769 fprintf(stderr, "queue name too long.\n"); 770 return EXIT_FAILURE; 771 } 772 strcpy(gqp.zev_queue_name.zev_name, arg); 773 774 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 775 perror("getting queue properties failed"); 776 return (EXIT_FAILURE); 777 } 778 gqp.zev_poll_wakeup_threshold = atol(len); 779 if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 780 fprintf(stderr, "poll throttle parameter garbled.\n"); 781 return (EXIT_FAILURE); 782 } 783 if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 784 fprintf(stderr, "poll throttle parameter out of bounds.\n"); 785 return (EXIT_FAILURE); 786 } 787 788 if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 789 perror("setting queue properties failed"); 790 return (EXIT_FAILURE); 791 } 792 return (0); 793 } 794 795 static int 796 zev_queue_properties(int fd, char *arg) 797 { 798 zev_ioctl_get_queue_properties_t gqp; 799 800 gqp.zev_queue_name.zev_namelen = strlen(arg); 801 if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 802 fprintf(stderr, "queue name too long.\n"); 803 return EXIT_FAILURE; 804 } 805 strcpy(gqp.zev_queue_name.zev_name, arg); 806 807 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 808 perror("getting queue properties failed"); 809 return (EXIT_FAILURE); 810 } 811 812 printf("queue : %s\n", arg); 813 printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 814 printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 815 printf("persistent : %s\n", 816 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 817 printf("blocking : %s\n", 818 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 819 820 return (0); 821 } 822 823 static int 824 zev_list_queues(int fd) 825 { 826 zev_ioctl_get_queue_properties_t gqp; 827 zev_ioctl_get_queue_list_t gql; 828 zev_ioctl_get_queue_statistics_t gs; 829 uint64_t i; 830 char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 831 832 if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 833 perror("getting queue list failed"); 834 return (EXIT_FAILURE); 835 } 836 837 printf("Name Size " 838 "Max Size Wakeup Per Block\n"); 839 840 for (i=0; i<gql.zev_n_queues; i++) { 841 strncpy(name, gql.zev_queue_name[i].zev_name, 842 ZEV_MAX_QUEUE_NAME_LEN); 843 name[gql.zev_queue_name[i].zev_namelen] = '\0'; 844 845 memcpy(gqp.zev_queue_name.zev_name, 846 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 847 gqp.zev_queue_name.zev_namelen = 848 gql.zev_queue_name[i].zev_namelen; 849 850 if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 851 if (errno == ENOENT) 852 continue; 853 perror("getting queue properties failed"); 854 return (EXIT_FAILURE); 855 } 856 857 memcpy(gs.zev_queue_name.zev_name, 858 gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 859 gs.zev_queue_name.zev_namelen = 860 gql.zev_queue_name[i].zev_namelen; 861 862 if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 863 if (errno == ENOENT) 864 continue; 865 perror("getting statistics data failed"); 866 return (EXIT_FAILURE); 867 } 868 869 printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 870 " %-3s %-3s\n", 871 name, 872 gs.zev_statistics.zev_queue_len, 873 gqp.zev_max_queue_len, 874 gqp.zev_poll_wakeup_threshold, 875 gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 876 gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 877 "yes" : "no"); 878 } 879 880 return (0); 881 } 882 883 int 884 main(int argc, char **argv) 885 { 886 int fd; 887 int c; 888 extern char *optarg; 889 int create_tmp_queue = 1; 890 char buf[MAXPATHLEN]; 891 892 /* open device */ 893 fd = open(zev_device, O_RDONLY); 894 if (fd < 0) { 895 perror("opening zev device failed"); 896 return EXIT_FAILURE; 897 } 898 while ((c = getopt(argc, argv, 899 "vspd:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 900 switch(c) { 901 case 'v': 902 verbose++; 903 break; 904 case 's': 905 return zev_statistics(fd); 906 case 'p': 907 return zev_poll_events(fd, create_tmp_queue); 908 case 'D': 909 return zev_debug_info(fd); 910 case 'd': 911 close(fd); 912 zev_device = optarg; 913 fd = open(zev_device, O_RDONLY); 914 if (fd < 0) { 915 perror("opening zev device failed"); 916 return EXIT_FAILURE; 917 } 918 create_tmp_queue = 0; 919 break; 920 case 'q': 921 snprintf(buf, sizeof(buf), 922 "/devices/pseudo/zev@0:%s", optarg); 923 close(fd); 924 zev_device = buf; 925 fd = open(zev_device, O_RDONLY); 926 if (fd < 0) { 927 perror("opening zev device failed"); 928 return EXIT_FAILURE; 929 } 930 create_tmp_queue = 0; 931 break; 932 case 'l': 933 return zev_list_queues(fd); 934 case 'Q': 935 return zev_set_global_max_queue_len(fd, optarg); 936 case 'L': 937 return zev_set_max_queue_len(fd, optarg, argv[optind]); 938 case 't': 939 return zev_set_poll_wakeup_queue_len(fd, optarg, 940 argv[optind]); 941 case 'm': 942 return zev_mute_pool(fd, optarg); 943 case 'M': 944 return zev_unmute_pool(fd, optarg); 945 case 'k': 946 return zev_mark(fd, optarg); 947 case 'a': 948 return zev_add_queue(fd, optarg, 0); 949 case 'A': 950 return zev_add_queue(fd, optarg, 1); 951 case 'r': 952 return zev_remove_queue(fd, optarg); 953 case 'b': 954 return zev_queue_blocking(fd, optarg, 0); 955 case 'B': 956 return zev_queue_blocking(fd, optarg, 1); 957 case 'P': 958 return zev_queue_properties(fd, optarg); 959 case 'h': 960 case '?': 961 default: 962 usage(argv[0]); 963 } 964 } 965 usage(argv[0]); 966 close(fd); 967 return EXIT_FAILURE; 968 } 969 970