12bb8e5e2SAndreas Jaekel #include <stdio.h> 22bb8e5e2SAndreas Jaekel #include <unistd.h> 32bb8e5e2SAndreas Jaekel #include <stdlib.h> 42bb8e5e2SAndreas Jaekel #include <fcntl.h> 52bb8e5e2SAndreas Jaekel #include <stropts.h> 62bb8e5e2SAndreas Jaekel #include <poll.h> 72bb8e5e2SAndreas Jaekel #include <string.h> 82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h> 92bb8e5e2SAndreas Jaekel #include <errno.h> 102bb8e5e2SAndreas Jaekel 112bb8e5e2SAndreas Jaekel #define OP_STATISTICS (1 << 0) 122bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS (1 << 1) 132bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL (1 << 2) 142bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL (1 << 3) 152bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN (1 << 4) 162bb8e5e2SAndreas Jaekel 172bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev" 182bb8e5e2SAndreas Jaekel 192bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 202bb8e5e2SAndreas Jaekel 219193e9c2SAndreas Jaekel static char *zev_op_name[] = { 229193e9c2SAndreas Jaekel "ZEV_OP_ERROR", 2301c2c787SAndreas Jaekel "ZEV_OP_MARK", 249193e9c2SAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 259193e9c2SAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 269193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 279193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 289193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 299193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 309193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 319193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 329193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 339193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 349193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_LINK", 359193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 369193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 379193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 389193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 399193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 409193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_ACL", 419193e9c2SAndreas Jaekel NULL 429193e9c2SAndreas Jaekel }; 439193e9c2SAndreas Jaekel 442bb8e5e2SAndreas Jaekel static void 452bb8e5e2SAndreas Jaekel zev_statistics(int fd) 462bb8e5e2SAndreas Jaekel { 472bb8e5e2SAndreas Jaekel zev_statistics_t zs; 482bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 492bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 502bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 512bb8e5e2SAndreas Jaekel } 522bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 532bb8e5e2SAndreas Jaekel 542bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 552bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 56205a9bc9SAndreas Jaekel printf(" poll wakeup throttle : %lu\n\n", 57205a9bc9SAndreas Jaekel zs.zev_poll_wakeup_queue_len); 582bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 592bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 602bb8e5e2SAndreas Jaekel 612bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 622bb8e5e2SAndreas Jaekel 632bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 642bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 652bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 662bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 672bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 682bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 692bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 702bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 712bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 722bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 732bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 742bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 752bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 762bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 772bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 782bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 792bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 802bb8e5e2SAndreas Jaekel } 812bb8e5e2SAndreas Jaekel 822bb8e5e2SAndreas Jaekel static void 8363aba447SAndreas Jaekel zev_print_error(char *buf) 8463aba447SAndreas Jaekel { 8563aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 8663aba447SAndreas Jaekel time_t op_time = rec->op_time; 8763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 8863aba447SAndreas Jaekel 8963aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 9063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 9163aba447SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 9263aba447SAndreas Jaekel } 9363aba447SAndreas Jaekel 9463aba447SAndreas Jaekel static void 9501c2c787SAndreas Jaekel zev_print_mark(char *buf) 9601c2c787SAndreas Jaekel { 9701c2c787SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 9801c2c787SAndreas Jaekel time_t op_time = rec->op_time; 9901c2c787SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 10001c2c787SAndreas Jaekel 10101c2c787SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 10201c2c787SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id, 10301c2c787SAndreas Jaekel rec->payload_len); 10401c2c787SAndreas Jaekel } 10501c2c787SAndreas Jaekel 10601c2c787SAndreas Jaekel static void 10763aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 10863aba447SAndreas Jaekel { 10963aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 11063aba447SAndreas Jaekel time_t op_time = rec->op_time; 11163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 11263aba447SAndreas Jaekel 11363aba447SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 11463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 11563aba447SAndreas Jaekel rec->guid, 11663aba447SAndreas Jaekel rec->remount ? "true" : "false", 11763aba447SAndreas Jaekel ZEV_DATASET(rec), 11863aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 11963aba447SAndreas Jaekel } 12063aba447SAndreas Jaekel 12163aba447SAndreas Jaekel static void 12263aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 12363aba447SAndreas Jaekel { 12463aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 12563aba447SAndreas Jaekel time_t op_time = rec->op_time; 12663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 12763aba447SAndreas Jaekel 12863aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 12963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 13063aba447SAndreas Jaekel rec->guid); 13163aba447SAndreas Jaekel } 13263aba447SAndreas Jaekel 13363aba447SAndreas Jaekel static void 13463aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 13563aba447SAndreas Jaekel { 13663aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 13763aba447SAndreas Jaekel time_t op_time = rec->op_time; 13863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 13963aba447SAndreas Jaekel 14063aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 14163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 14263aba447SAndreas Jaekel rec->guid, 14363aba447SAndreas Jaekel rec->offset, 14463aba447SAndreas Jaekel rec->length); 14563aba447SAndreas Jaekel } 14663aba447SAndreas Jaekel 14763aba447SAndreas Jaekel static void 14863aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 14963aba447SAndreas Jaekel { 15063aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 15163aba447SAndreas Jaekel } 15263aba447SAndreas Jaekel 15363aba447SAndreas Jaekel static void 15463aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 15563aba447SAndreas Jaekel { 15663aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 15763aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 15863aba447SAndreas Jaekel time_t op_time = rec->op_time; 15963aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 16063aba447SAndreas Jaekel 16163aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 16263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 16363aba447SAndreas Jaekel rec->guid, 16463aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 16563aba447SAndreas Jaekel } 16663aba447SAndreas Jaekel 16763aba447SAndreas Jaekel static void 16863aba447SAndreas Jaekel zev_print_znode_create(char *buf) 16963aba447SAndreas Jaekel { 17063aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 17163aba447SAndreas Jaekel time_t op_time = rec->op_time; 17263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 17363aba447SAndreas Jaekel 174c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 175c035b1e8SAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 17663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 17763aba447SAndreas Jaekel rec->guid, 17863aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 17963aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 180c035b1e8SAndreas Jaekel rec->file.mtime, rec->parent.mtime, 18163aba447SAndreas Jaekel ZEV_NAME(rec)); 18263aba447SAndreas Jaekel } 18363aba447SAndreas Jaekel 18463aba447SAndreas Jaekel static void 18563aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 18663aba447SAndreas Jaekel { 18763aba447SAndreas Jaekel zev_print_znode_create(buf); 18863aba447SAndreas Jaekel } 18963aba447SAndreas Jaekel 19063aba447SAndreas Jaekel static void 19163aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 19263aba447SAndreas Jaekel { 19363aba447SAndreas Jaekel zev_print_znode_create(buf); 19463aba447SAndreas Jaekel } 19563aba447SAndreas Jaekel 19663aba447SAndreas Jaekel static void 19763aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 19863aba447SAndreas Jaekel { 19963aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 20063aba447SAndreas Jaekel time_t op_time = rec->op_time; 20163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 20263aba447SAndreas Jaekel 20363aba447SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n", 20463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 20563aba447SAndreas Jaekel rec->guid, 20663aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 20763aba447SAndreas Jaekel ZEV_NAME(rec)); 20863aba447SAndreas Jaekel } 20963aba447SAndreas Jaekel 21063aba447SAndreas Jaekel static void 21163aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 21263aba447SAndreas Jaekel { 21363aba447SAndreas Jaekel zev_print_znode_remove(buf); 21463aba447SAndreas Jaekel } 21563aba447SAndreas Jaekel 21663aba447SAndreas Jaekel static void 21763aba447SAndreas Jaekel zev_print_znode_link(char *buf) 21863aba447SAndreas Jaekel { 21963aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 22063aba447SAndreas Jaekel time_t op_time = rec->op_time; 22163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 22263aba447SAndreas Jaekel 223*03101f54SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 224*03101f54SAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 22563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 22663aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 22763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 228*03101f54SAndreas Jaekel rec->file.ctime, rec->parent.ctime, 22963aba447SAndreas Jaekel ZEV_NAME(rec)); 23063aba447SAndreas Jaekel printf("links: %d\n", rec->file.links); 23163aba447SAndreas Jaekel } 23263aba447SAndreas Jaekel 23363aba447SAndreas Jaekel static void 23463aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 23563aba447SAndreas Jaekel { 23663aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 23763aba447SAndreas Jaekel time_t op_time = rec->op_time; 23863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 23963aba447SAndreas Jaekel 24063aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 24163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 24263aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 24363aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 24463aba447SAndreas Jaekel ZEV_NAME(rec), 24563aba447SAndreas Jaekel ZEV_LINK(rec)); 24663aba447SAndreas Jaekel } 24763aba447SAndreas Jaekel 24863aba447SAndreas Jaekel static void 24963aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 25063aba447SAndreas Jaekel { 25163aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 25263aba447SAndreas Jaekel time_t op_time = rec->op_time; 25363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 25463aba447SAndreas Jaekel 25563aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 256c035b1e8SAndreas Jaekel "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 257c035b1e8SAndreas Jaekel "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 25863aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 25963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 26063aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 26163aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 26263aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 263c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 264c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 265c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 26663aba447SAndreas Jaekel ZEV_SRCNAME(rec), 26763aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 26863aba447SAndreas Jaekel } 26963aba447SAndreas Jaekel 27063aba447SAndreas Jaekel static void 27163aba447SAndreas Jaekel zev_print_znode_write(char *buf) 27263aba447SAndreas Jaekel { 27363aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 27463aba447SAndreas Jaekel time_t op_time = rec->op_time; 27563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 27663aba447SAndreas Jaekel 27763aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 27863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 27963aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 28063aba447SAndreas Jaekel rec->offset, rec->length); 28163aba447SAndreas Jaekel } 28263aba447SAndreas Jaekel 28363aba447SAndreas Jaekel static void 28463aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 28563aba447SAndreas Jaekel { 28663aba447SAndreas Jaekel zev_print_znode_write(buf); 28763aba447SAndreas Jaekel } 28863aba447SAndreas Jaekel 28963aba447SAndreas Jaekel static void 29063aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 29163aba447SAndreas Jaekel { 29263aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 29363aba447SAndreas Jaekel time_t op_time = rec->op_time; 29463aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 29563aba447SAndreas Jaekel 296c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 29763aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 298c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 29963aba447SAndreas Jaekel } 30063aba447SAndreas Jaekel 30163aba447SAndreas Jaekel static void 30263aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 30363aba447SAndreas Jaekel { 30463aba447SAndreas Jaekel zev_print_znode_setattr(buf); 30563aba447SAndreas Jaekel } 30663aba447SAndreas Jaekel 30763aba447SAndreas Jaekel static void 3089193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 3099193e9c2SAndreas Jaekel { 31063aba447SAndreas Jaekel int record_len; 31163aba447SAndreas Jaekel int op; 3129193e9c2SAndreas Jaekel 31363aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 31463aba447SAndreas Jaekel if (record_len != len) { 31563aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 31663aba447SAndreas Jaekel record_len, len); 3179193e9c2SAndreas Jaekel exit(1); 3189193e9c2SAndreas Jaekel } 31963aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 3209193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 32163aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3229193e9c2SAndreas Jaekel exit(1); 3239193e9c2SAndreas Jaekel } 32463aba447SAndreas Jaekel switch (op) { 32563aba447SAndreas Jaekel case ZEV_OP_ERROR: 32663aba447SAndreas Jaekel zev_print_error(buf); 3279193e9c2SAndreas Jaekel break; 32801c2c787SAndreas Jaekel case ZEV_OP_MARK: 32901c2c787SAndreas Jaekel zev_print_mark(buf); 33001c2c787SAndreas Jaekel break; 33163aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 33263aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3339193e9c2SAndreas Jaekel break; 33463aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 33563aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3369193e9c2SAndreas Jaekel break; 33763aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 33863aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3399193e9c2SAndreas Jaekel break; 34063aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 34163aba447SAndreas Jaekel zev_print_zvol_write(buf); 34263aba447SAndreas Jaekel break; 34363aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 34463aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 34563aba447SAndreas Jaekel break; 34663aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 34763aba447SAndreas Jaekel zev_print_znode_create(buf); 34863aba447SAndreas Jaekel break; 34963aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 35063aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 35163aba447SAndreas Jaekel break; 35263aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 35363aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 35463aba447SAndreas Jaekel break; 35563aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 35663aba447SAndreas Jaekel zev_print_znode_remove(buf); 35763aba447SAndreas Jaekel break; 35863aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 35963aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 36063aba447SAndreas Jaekel break; 36163aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 36263aba447SAndreas Jaekel zev_print_znode_link(buf); 36363aba447SAndreas Jaekel break; 36463aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 36563aba447SAndreas Jaekel zev_print_znode_symlink(buf); 36663aba447SAndreas Jaekel break; 36763aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 36863aba447SAndreas Jaekel zev_print_znode_rename(buf); 36963aba447SAndreas Jaekel break; 37063aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 37163aba447SAndreas Jaekel zev_print_znode_write(buf); 37263aba447SAndreas Jaekel break; 37363aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 37463aba447SAndreas Jaekel zev_print_znode_truncate(buf); 37563aba447SAndreas Jaekel break; 37663aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 37763aba447SAndreas Jaekel zev_print_znode_setattr(buf); 37863aba447SAndreas Jaekel break; 37963aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 38063aba447SAndreas Jaekel zev_print_znode_acl(buf); 3819193e9c2SAndreas Jaekel break; 3829193e9c2SAndreas Jaekel default: 38363aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 3849193e9c2SAndreas Jaekel exit(1); 3859193e9c2SAndreas Jaekel } 3869193e9c2SAndreas Jaekel } 3879193e9c2SAndreas Jaekel 3889193e9c2SAndreas Jaekel static void 3892bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 3902bb8e5e2SAndreas Jaekel { 3912bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 3922bb8e5e2SAndreas Jaekel int ret; 3939193e9c2SAndreas Jaekel char buf[4096]; 39468a46c64SAndreas Jaekel zev_event_t *ev; 39568a46c64SAndreas Jaekel int off = 0; 3962bb8e5e2SAndreas Jaekel while (1) { 3972bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 3982bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 3992bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 4002bb8e5e2SAndreas Jaekel if (ret < 0) { 4012bb8e5e2SAndreas Jaekel perror("poll failed"); 4022bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 4032bb8e5e2SAndreas Jaekel } 4042bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 4052bb8e5e2SAndreas Jaekel continue; 4062bb8e5e2SAndreas Jaekel /* data available */ 4072bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 4082bb8e5e2SAndreas Jaekel if (ret < 0) { 4092bb8e5e2SAndreas Jaekel perror("read failed"); 4102bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 4112bb8e5e2SAndreas Jaekel } 4122bb8e5e2SAndreas Jaekel if (ret == 0) 4132bb8e5e2SAndreas Jaekel continue; 41468a46c64SAndreas Jaekel while (ret > off) { 41568a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 41668a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 41768a46c64SAndreas Jaekel off += ev->header.record_len; 41868a46c64SAndreas Jaekel } 419108668daSAndreas Jaekel off = 0; 4202bb8e5e2SAndreas Jaekel } 4212bb8e5e2SAndreas Jaekel return; 4222bb8e5e2SAndreas Jaekel } 4232bb8e5e2SAndreas Jaekel 4242bb8e5e2SAndreas Jaekel static void 4252bb8e5e2SAndreas Jaekel usage(char *progname) 4262bb8e5e2SAndreas Jaekel { 4272bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 4282bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 4292bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 4302bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 431205a9bc9SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 4322bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 4332bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 4342bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 4352bb8e5e2SAndreas Jaekel ZEV_DEVICE); 43601c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 4372bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 4382bb8e5e2SAndreas Jaekel } 4392bb8e5e2SAndreas Jaekel 4402bb8e5e2SAndreas Jaekel static int 4412bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 4422bb8e5e2SAndreas Jaekel { 4432bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 4442bb8e5e2SAndreas Jaekel 4452bb8e5e2SAndreas Jaekel errno = 0; 4462bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 4472bb8e5e2SAndreas Jaekel if (errno) { 4482bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 4492bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4502bb8e5e2SAndreas Jaekel } 4512bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 4522bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 4532bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4542bb8e5e2SAndreas Jaekel } 4552bb8e5e2SAndreas Jaekel return (0); 4562bb8e5e2SAndreas Jaekel } 4572bb8e5e2SAndreas Jaekel 4582bb8e5e2SAndreas Jaekel static int 459205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 460205a9bc9SAndreas Jaekel { 461205a9bc9SAndreas Jaekel uint64_t queuelen; 462205a9bc9SAndreas Jaekel 463205a9bc9SAndreas Jaekel errno = 0; 464205a9bc9SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 465205a9bc9SAndreas Jaekel if (errno) { 466205a9bc9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 467205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 468205a9bc9SAndreas Jaekel } 469205a9bc9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 470205a9bc9SAndreas Jaekel perror("setting poll wakeup queue length failed"); 471205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 472205a9bc9SAndreas Jaekel } 473205a9bc9SAndreas Jaekel return (0); 474205a9bc9SAndreas Jaekel } 475205a9bc9SAndreas Jaekel 476205a9bc9SAndreas Jaekel static int 4772bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 4782bb8e5e2SAndreas Jaekel { 4792bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 4802bb8e5e2SAndreas Jaekel int len; 4812bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 4822bb8e5e2SAndreas Jaekel len = strlen(poolname); 4832bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 4842bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 4852bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4862bb8e5e2SAndreas Jaekel } 4872bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 4882bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 4892bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 4902bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 4912bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4922bb8e5e2SAndreas Jaekel } 4932bb8e5e2SAndreas Jaekel return (0); 4942bb8e5e2SAndreas Jaekel } 4952bb8e5e2SAndreas Jaekel 4962bb8e5e2SAndreas Jaekel int 4972bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 4982bb8e5e2SAndreas Jaekel { 4992bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 5002bb8e5e2SAndreas Jaekel } 5012bb8e5e2SAndreas Jaekel 5022bb8e5e2SAndreas Jaekel int 5032bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 5042bb8e5e2SAndreas Jaekel { 5052bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 5062bb8e5e2SAndreas Jaekel } 5072bb8e5e2SAndreas Jaekel 50801c2c787SAndreas Jaekel static int 50901c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 51001c2c787SAndreas Jaekel { 51101c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 51201c2c787SAndreas Jaekel uint64_t guid; 51301c2c787SAndreas Jaekel int len; 51401c2c787SAndreas Jaekel char *p; 51501c2c787SAndreas Jaekel 51601c2c787SAndreas Jaekel p = strchr(arg, ':'); 51701c2c787SAndreas Jaekel if (!p) { 51801c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 51901c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 52001c2c787SAndreas Jaekel exit (EXIT_FAILURE); 52101c2c787SAndreas Jaekel } 52201c2c787SAndreas Jaekel *p = '\n'; 52301c2c787SAndreas Jaekel p++; 52401c2c787SAndreas Jaekel 52501c2c787SAndreas Jaekel errno = 0; 52601c2c787SAndreas Jaekel guid = strtoll(optarg, (char **)NULL, 10); 52701c2c787SAndreas Jaekel if (errno) { 52801c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 52901c2c787SAndreas Jaekel exit (EXIT_FAILURE); 53001c2c787SAndreas Jaekel } 53101c2c787SAndreas Jaekel 53201c2c787SAndreas Jaekel len = strlen(p); 53301c2c787SAndreas Jaekel 53401c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 53501c2c787SAndreas Jaekel if (!mark) { 53601c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 53701c2c787SAndreas Jaekel strerror(errno)); 53801c2c787SAndreas Jaekel exit (EXIT_FAILURE); 53901c2c787SAndreas Jaekel } 54001c2c787SAndreas Jaekel mark->zev_guid = guid; 54101c2c787SAndreas Jaekel mark->zev_mark_id = 0; 54201c2c787SAndreas Jaekel mark->zev_payload_len = len; 54301c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 54401c2c787SAndreas Jaekel 54501c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 54601c2c787SAndreas Jaekel perror("queueing mark failed"); 54701c2c787SAndreas Jaekel return (EXIT_FAILURE); 54801c2c787SAndreas Jaekel } 54901c2c787SAndreas Jaekel 55001c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 55101c2c787SAndreas Jaekel return (0); 55201c2c787SAndreas Jaekel } 55301c2c787SAndreas Jaekel 5542bb8e5e2SAndreas Jaekel int 5552bb8e5e2SAndreas Jaekel main(int argc, char **argv) 5562bb8e5e2SAndreas Jaekel { 5572bb8e5e2SAndreas Jaekel int fd; 5582bb8e5e2SAndreas Jaekel int c; 5592bb8e5e2SAndreas Jaekel int ops = 0; 5602bb8e5e2SAndreas Jaekel extern char *optarg; 5612bb8e5e2SAndreas Jaekel 5622bb8e5e2SAndreas Jaekel /* open device */ 5632bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 5642bb8e5e2SAndreas Jaekel if (fd < 0) { 5652bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 5662bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 5672bb8e5e2SAndreas Jaekel } 56801c2c787SAndreas Jaekel while ((c = getopt(argc, argv, "spdk:q:t:m:M:h?")) != -1) { 5692bb8e5e2SAndreas Jaekel switch(c) { 5702bb8e5e2SAndreas Jaekel case 's': 5712bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 5722bb8e5e2SAndreas Jaekel break; 5732bb8e5e2SAndreas Jaekel case 'p': 5742bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 5752bb8e5e2SAndreas Jaekel break; 5762bb8e5e2SAndreas Jaekel case 'd': 5772bb8e5e2SAndreas Jaekel zev_device = optarg; 5782bb8e5e2SAndreas Jaekel break; 5792bb8e5e2SAndreas Jaekel case 'q': 5802bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 581205a9bc9SAndreas Jaekel case 't': 582205a9bc9SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 5832bb8e5e2SAndreas Jaekel case 'm': 5842bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 5852bb8e5e2SAndreas Jaekel case 'M': 5862bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 58701c2c787SAndreas Jaekel case 'k': 58801c2c787SAndreas Jaekel return zev_mark(fd, optarg); 5892bb8e5e2SAndreas Jaekel case 'h': 5902bb8e5e2SAndreas Jaekel case '?': 5912bb8e5e2SAndreas Jaekel default: 5922bb8e5e2SAndreas Jaekel usage(argv[0]); 5932bb8e5e2SAndreas Jaekel } 5942bb8e5e2SAndreas Jaekel } 5952bb8e5e2SAndreas Jaekel if (!ops) 5962bb8e5e2SAndreas Jaekel usage(argv[0]); 5972bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 5982bb8e5e2SAndreas Jaekel zev_statistics(fd); 5992bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 6002bb8e5e2SAndreas Jaekel zev_poll_events(fd); 6012bb8e5e2SAndreas Jaekel close(fd); 6022bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 6032bb8e5e2SAndreas Jaekel } 6042bb8e5e2SAndreas Jaekel 605