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", 239193e9c2SAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 249193e9c2SAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 259193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 269193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 279193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 289193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 299193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 309193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 319193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 329193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 339193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_LINK", 349193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 359193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 369193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 379193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 389193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 399193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_ACL", 409193e9c2SAndreas Jaekel NULL 419193e9c2SAndreas Jaekel }; 429193e9c2SAndreas Jaekel 432bb8e5e2SAndreas Jaekel static void 442bb8e5e2SAndreas Jaekel zev_statistics(int fd) 452bb8e5e2SAndreas Jaekel { 462bb8e5e2SAndreas Jaekel zev_statistics_t zs; 472bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 482bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 492bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 502bb8e5e2SAndreas Jaekel } 512bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 522bb8e5e2SAndreas Jaekel 532bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 542bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 55205a9bc9SAndreas Jaekel printf(" poll wakeup throttle : %lu\n\n", 56205a9bc9SAndreas Jaekel zs.zev_poll_wakeup_queue_len); 572bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 582bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 592bb8e5e2SAndreas Jaekel 602bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 612bb8e5e2SAndreas Jaekel 622bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 632bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 642bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 652bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 662bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 672bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 682bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 692bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 702bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 712bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 722bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 732bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 742bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 752bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 762bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 772bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 782bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 792bb8e5e2SAndreas Jaekel } 802bb8e5e2SAndreas Jaekel 812bb8e5e2SAndreas Jaekel static void 8263aba447SAndreas Jaekel zev_print_error(char *buf) 8363aba447SAndreas Jaekel { 8463aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 8563aba447SAndreas Jaekel time_t op_time = rec->op_time; 8663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 8763aba447SAndreas Jaekel 8863aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 8963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 9063aba447SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 9163aba447SAndreas Jaekel } 9263aba447SAndreas Jaekel 9363aba447SAndreas Jaekel static void 9463aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 9563aba447SAndreas Jaekel { 9663aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 9763aba447SAndreas Jaekel time_t op_time = rec->op_time; 9863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 9963aba447SAndreas Jaekel 10063aba447SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 10163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 10263aba447SAndreas Jaekel rec->guid, 10363aba447SAndreas Jaekel rec->remount ? "true" : "false", 10463aba447SAndreas Jaekel ZEV_DATASET(rec), 10563aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 10663aba447SAndreas Jaekel } 10763aba447SAndreas Jaekel 10863aba447SAndreas Jaekel static void 10963aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 11063aba447SAndreas Jaekel { 11163aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 11263aba447SAndreas Jaekel time_t op_time = rec->op_time; 11363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 11463aba447SAndreas Jaekel 11563aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 11663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 11763aba447SAndreas Jaekel rec->guid); 11863aba447SAndreas Jaekel } 11963aba447SAndreas Jaekel 12063aba447SAndreas Jaekel static void 12163aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 12263aba447SAndreas Jaekel { 12363aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 12463aba447SAndreas Jaekel time_t op_time = rec->op_time; 12563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 12663aba447SAndreas Jaekel 12763aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 12863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 12963aba447SAndreas Jaekel rec->guid, 13063aba447SAndreas Jaekel rec->offset, 13163aba447SAndreas Jaekel rec->length); 13263aba447SAndreas Jaekel } 13363aba447SAndreas Jaekel 13463aba447SAndreas Jaekel static void 13563aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 13663aba447SAndreas Jaekel { 13763aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 13863aba447SAndreas Jaekel } 13963aba447SAndreas Jaekel 14063aba447SAndreas Jaekel static void 14163aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 14263aba447SAndreas Jaekel { 14363aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 14463aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 14563aba447SAndreas Jaekel time_t op_time = rec->op_time; 14663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 14763aba447SAndreas Jaekel 14863aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 14963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 15063aba447SAndreas Jaekel rec->guid, 15163aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 15263aba447SAndreas Jaekel } 15363aba447SAndreas Jaekel 15463aba447SAndreas Jaekel static void 15563aba447SAndreas Jaekel zev_print_znode_create(char *buf) 15663aba447SAndreas Jaekel { 15763aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_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 parent=%llu.%llu file=%llu.%llu name='%s'\n", 16263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 16363aba447SAndreas Jaekel rec->guid, 16463aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 16563aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 16663aba447SAndreas Jaekel ZEV_NAME(rec)); 16763aba447SAndreas Jaekel } 16863aba447SAndreas Jaekel 16963aba447SAndreas Jaekel static void 17063aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 17163aba447SAndreas Jaekel { 17263aba447SAndreas Jaekel zev_print_znode_create(buf); 17363aba447SAndreas Jaekel } 17463aba447SAndreas Jaekel 17563aba447SAndreas Jaekel static void 17663aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 17763aba447SAndreas Jaekel { 17863aba447SAndreas Jaekel zev_print_znode_create(buf); 17963aba447SAndreas Jaekel } 18063aba447SAndreas Jaekel 18163aba447SAndreas Jaekel static void 18263aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 18363aba447SAndreas Jaekel { 18463aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 18563aba447SAndreas Jaekel time_t op_time = rec->op_time; 18663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 18763aba447SAndreas Jaekel 18863aba447SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n", 18963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 19063aba447SAndreas Jaekel rec->guid, 19163aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 19263aba447SAndreas Jaekel ZEV_NAME(rec)); 19363aba447SAndreas Jaekel } 19463aba447SAndreas Jaekel 19563aba447SAndreas Jaekel static void 19663aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 19763aba447SAndreas Jaekel { 19863aba447SAndreas Jaekel zev_print_znode_remove(buf); 19963aba447SAndreas Jaekel } 20063aba447SAndreas Jaekel 20163aba447SAndreas Jaekel static void 20263aba447SAndreas Jaekel zev_print_znode_link(char *buf) 20363aba447SAndreas Jaekel { 20463aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 20563aba447SAndreas Jaekel time_t op_time = rec->op_time; 20663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 20763aba447SAndreas Jaekel 20863aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s'\n", 20963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 21063aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 21163aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 21263aba447SAndreas Jaekel ZEV_NAME(rec)); 21363aba447SAndreas Jaekel printf("links: %d\n", rec->file.links); 21463aba447SAndreas Jaekel } 21563aba447SAndreas Jaekel 21663aba447SAndreas Jaekel static void 21763aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 21863aba447SAndreas Jaekel { 21963aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 22063aba447SAndreas Jaekel time_t op_time = rec->op_time; 22163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 22263aba447SAndreas Jaekel 22363aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 22463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 22563aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 22663aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 22763aba447SAndreas Jaekel ZEV_NAME(rec), 22863aba447SAndreas Jaekel ZEV_LINK(rec)); 22963aba447SAndreas Jaekel } 23063aba447SAndreas Jaekel 23163aba447SAndreas Jaekel static void 23263aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 23363aba447SAndreas Jaekel { 23463aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 23563aba447SAndreas Jaekel time_t op_time = rec->op_time; 23663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 23763aba447SAndreas Jaekel 23863aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 23963aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 24063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 24163aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 24263aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 24363aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 24463aba447SAndreas Jaekel ZEV_SRCNAME(rec), 24563aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 24663aba447SAndreas Jaekel } 24763aba447SAndreas Jaekel 24863aba447SAndreas Jaekel static void 24963aba447SAndreas Jaekel zev_print_znode_write(char *buf) 25063aba447SAndreas Jaekel { 25163aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_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: file=%llu.%llu offset=%llu length=%llu\n", 25663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 25763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 25863aba447SAndreas Jaekel rec->offset, rec->length); 25963aba447SAndreas Jaekel } 26063aba447SAndreas Jaekel 26163aba447SAndreas Jaekel static void 26263aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 26363aba447SAndreas Jaekel { 26463aba447SAndreas Jaekel zev_print_znode_write(buf); 26563aba447SAndreas Jaekel } 26663aba447SAndreas Jaekel 26763aba447SAndreas Jaekel static void 26863aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 26963aba447SAndreas Jaekel { 27063aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 27163aba447SAndreas Jaekel time_t op_time = rec->op_time; 27263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 27363aba447SAndreas Jaekel 27463aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu\n", 27563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 27663aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 27763aba447SAndreas Jaekel } 27863aba447SAndreas Jaekel 27963aba447SAndreas Jaekel static void 28063aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 28163aba447SAndreas Jaekel { 28263aba447SAndreas Jaekel zev_print_znode_setattr(buf); 28363aba447SAndreas Jaekel } 28463aba447SAndreas Jaekel 28563aba447SAndreas Jaekel static void 2869193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 2879193e9c2SAndreas Jaekel { 28863aba447SAndreas Jaekel int record_len; 28963aba447SAndreas Jaekel int op; 2909193e9c2SAndreas Jaekel 29163aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 29263aba447SAndreas Jaekel if (record_len != len) { 29363aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 29463aba447SAndreas Jaekel record_len, len); 2959193e9c2SAndreas Jaekel exit(1); 2969193e9c2SAndreas Jaekel } 29763aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 2989193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 29963aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3009193e9c2SAndreas Jaekel exit(1); 3019193e9c2SAndreas Jaekel } 30263aba447SAndreas Jaekel switch (op) { 30363aba447SAndreas Jaekel case ZEV_OP_ERROR: 30463aba447SAndreas Jaekel zev_print_error(buf); 3059193e9c2SAndreas Jaekel break; 30663aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 30763aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3089193e9c2SAndreas Jaekel break; 30963aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 31063aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3119193e9c2SAndreas Jaekel break; 31263aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 31363aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3149193e9c2SAndreas Jaekel break; 31563aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 31663aba447SAndreas Jaekel zev_print_zvol_write(buf); 31763aba447SAndreas Jaekel break; 31863aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 31963aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 32063aba447SAndreas Jaekel break; 32163aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 32263aba447SAndreas Jaekel zev_print_znode_create(buf); 32363aba447SAndreas Jaekel break; 32463aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 32563aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 32663aba447SAndreas Jaekel break; 32763aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 32863aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 32963aba447SAndreas Jaekel break; 33063aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 33163aba447SAndreas Jaekel zev_print_znode_remove(buf); 33263aba447SAndreas Jaekel break; 33363aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 33463aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 33563aba447SAndreas Jaekel break; 33663aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 33763aba447SAndreas Jaekel zev_print_znode_link(buf); 33863aba447SAndreas Jaekel break; 33963aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 34063aba447SAndreas Jaekel zev_print_znode_symlink(buf); 34163aba447SAndreas Jaekel break; 34263aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 34363aba447SAndreas Jaekel zev_print_znode_rename(buf); 34463aba447SAndreas Jaekel break; 34563aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 34663aba447SAndreas Jaekel zev_print_znode_write(buf); 34763aba447SAndreas Jaekel break; 34863aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 34963aba447SAndreas Jaekel zev_print_znode_truncate(buf); 35063aba447SAndreas Jaekel break; 35163aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 35263aba447SAndreas Jaekel zev_print_znode_setattr(buf); 35363aba447SAndreas Jaekel break; 35463aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 35563aba447SAndreas Jaekel zev_print_znode_acl(buf); 3569193e9c2SAndreas Jaekel break; 3579193e9c2SAndreas Jaekel default: 35863aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 3599193e9c2SAndreas Jaekel exit(1); 3609193e9c2SAndreas Jaekel } 3619193e9c2SAndreas Jaekel } 3629193e9c2SAndreas Jaekel 3639193e9c2SAndreas Jaekel static void 3642bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 3652bb8e5e2SAndreas Jaekel { 3662bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 3672bb8e5e2SAndreas Jaekel int ret; 3689193e9c2SAndreas Jaekel char buf[4096]; 369*68a46c64SAndreas Jaekel zev_event_t *ev; 370*68a46c64SAndreas Jaekel int off = 0; 3712bb8e5e2SAndreas Jaekel while (1) { 3722bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 3732bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 3742bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 3752bb8e5e2SAndreas Jaekel if (ret < 0) { 3762bb8e5e2SAndreas Jaekel perror("poll failed"); 3772bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 3782bb8e5e2SAndreas Jaekel } 3792bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 3802bb8e5e2SAndreas Jaekel continue; 3812bb8e5e2SAndreas Jaekel /* data available */ 3822bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 3832bb8e5e2SAndreas Jaekel if (ret < 0) { 3842bb8e5e2SAndreas Jaekel perror("read failed"); 3852bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 3862bb8e5e2SAndreas Jaekel } 3872bb8e5e2SAndreas Jaekel if (ret == 0) 3882bb8e5e2SAndreas Jaekel continue; 389*68a46c64SAndreas Jaekel while (ret > off) { 390*68a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 391*68a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 392*68a46c64SAndreas Jaekel off += ev->header.record_len; 393*68a46c64SAndreas Jaekel } 3942bb8e5e2SAndreas Jaekel } 3952bb8e5e2SAndreas Jaekel return; 3962bb8e5e2SAndreas Jaekel } 3972bb8e5e2SAndreas Jaekel 3982bb8e5e2SAndreas Jaekel static void 3992bb8e5e2SAndreas Jaekel usage(char *progname) 4002bb8e5e2SAndreas Jaekel { 4012bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 4022bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 4032bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 4042bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 405205a9bc9SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 4062bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 4072bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 4082bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 4092bb8e5e2SAndreas Jaekel ZEV_DEVICE); 4102bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 4112bb8e5e2SAndreas Jaekel } 4122bb8e5e2SAndreas Jaekel 4132bb8e5e2SAndreas Jaekel static int 4142bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 4152bb8e5e2SAndreas Jaekel { 4162bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 4172bb8e5e2SAndreas Jaekel 4182bb8e5e2SAndreas Jaekel errno = 0; 4192bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 4202bb8e5e2SAndreas Jaekel if (errno) { 4212bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 4222bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4232bb8e5e2SAndreas Jaekel } 4242bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 4252bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 4262bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4272bb8e5e2SAndreas Jaekel } 4282bb8e5e2SAndreas Jaekel return (0); 4292bb8e5e2SAndreas Jaekel } 4302bb8e5e2SAndreas Jaekel 4312bb8e5e2SAndreas Jaekel static int 432205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 433205a9bc9SAndreas Jaekel { 434205a9bc9SAndreas Jaekel uint64_t queuelen; 435205a9bc9SAndreas Jaekel 436205a9bc9SAndreas Jaekel errno = 0; 437205a9bc9SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 438205a9bc9SAndreas Jaekel if (errno) { 439205a9bc9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 440205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 441205a9bc9SAndreas Jaekel } 442205a9bc9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 443205a9bc9SAndreas Jaekel perror("setting poll wakeup queue length failed"); 444205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 445205a9bc9SAndreas Jaekel } 446205a9bc9SAndreas Jaekel return (0); 447205a9bc9SAndreas Jaekel } 448205a9bc9SAndreas Jaekel 449205a9bc9SAndreas Jaekel static int 4502bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 4512bb8e5e2SAndreas Jaekel { 4522bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 4532bb8e5e2SAndreas Jaekel int len; 4542bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 4552bb8e5e2SAndreas Jaekel len = strlen(poolname); 4562bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 4572bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 4582bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4592bb8e5e2SAndreas Jaekel } 4602bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 4612bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 4622bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 4632bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 4642bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4652bb8e5e2SAndreas Jaekel } 4662bb8e5e2SAndreas Jaekel return (0); 4672bb8e5e2SAndreas Jaekel } 4682bb8e5e2SAndreas Jaekel 4692bb8e5e2SAndreas Jaekel int 4702bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 4712bb8e5e2SAndreas Jaekel { 4722bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 4732bb8e5e2SAndreas Jaekel } 4742bb8e5e2SAndreas Jaekel 4752bb8e5e2SAndreas Jaekel int 4762bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 4772bb8e5e2SAndreas Jaekel { 4782bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 4792bb8e5e2SAndreas Jaekel } 4802bb8e5e2SAndreas Jaekel 4812bb8e5e2SAndreas Jaekel int 4822bb8e5e2SAndreas Jaekel main(int argc, char **argv) 4832bb8e5e2SAndreas Jaekel { 4842bb8e5e2SAndreas Jaekel int fd; 4852bb8e5e2SAndreas Jaekel int c; 4862bb8e5e2SAndreas Jaekel int ops = 0; 4872bb8e5e2SAndreas Jaekel extern char *optarg; 4882bb8e5e2SAndreas Jaekel 4892bb8e5e2SAndreas Jaekel /* open device */ 4902bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 4912bb8e5e2SAndreas Jaekel if (fd < 0) { 4922bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 4932bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 4942bb8e5e2SAndreas Jaekel } 495205a9bc9SAndreas Jaekel while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) { 4962bb8e5e2SAndreas Jaekel switch(c) { 4972bb8e5e2SAndreas Jaekel case 's': 4982bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 4992bb8e5e2SAndreas Jaekel break; 5002bb8e5e2SAndreas Jaekel case 'p': 5012bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 5022bb8e5e2SAndreas Jaekel break; 5032bb8e5e2SAndreas Jaekel case 'd': 5042bb8e5e2SAndreas Jaekel zev_device = optarg; 5052bb8e5e2SAndreas Jaekel break; 5062bb8e5e2SAndreas Jaekel case 'q': 5072bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 508205a9bc9SAndreas Jaekel case 't': 509205a9bc9SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 5102bb8e5e2SAndreas Jaekel case 'm': 5112bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 5122bb8e5e2SAndreas Jaekel case 'M': 5132bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 5142bb8e5e2SAndreas Jaekel case 'h': 5152bb8e5e2SAndreas Jaekel case '?': 5162bb8e5e2SAndreas Jaekel default: 5172bb8e5e2SAndreas Jaekel usage(argv[0]); 5182bb8e5e2SAndreas Jaekel } 5192bb8e5e2SAndreas Jaekel } 5202bb8e5e2SAndreas Jaekel if (!ops) 5212bb8e5e2SAndreas Jaekel usage(argv[0]); 5222bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 5232bb8e5e2SAndreas Jaekel zev_statistics(fd); 5242bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 5252bb8e5e2SAndreas Jaekel zev_poll_events(fd); 5262bb8e5e2SAndreas Jaekel close(fd); 5272bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 5282bb8e5e2SAndreas Jaekel } 5292bb8e5e2SAndreas Jaekel 530