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 174*c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 175*c035b1e8SAndreas 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, 180*c035b1e8SAndreas 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 22363aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%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 printf("links: %d\n", rec->file.links); 22963aba447SAndreas Jaekel } 23063aba447SAndreas Jaekel 23163aba447SAndreas Jaekel static void 23263aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 23363aba447SAndreas Jaekel { 23463aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_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: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 23963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 24063aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 24163aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 24263aba447SAndreas Jaekel ZEV_NAME(rec), 24363aba447SAndreas Jaekel ZEV_LINK(rec)); 24463aba447SAndreas Jaekel } 24563aba447SAndreas Jaekel 24663aba447SAndreas Jaekel static void 24763aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 24863aba447SAndreas Jaekel { 24963aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 25063aba447SAndreas Jaekel time_t op_time = rec->op_time; 25163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 25263aba447SAndreas Jaekel 25363aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 254*c035b1e8SAndreas Jaekel "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 255*c035b1e8SAndreas Jaekel "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 25663aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 25763aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 25863aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 25963aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 26063aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 261*c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 262*c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 263*c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 26463aba447SAndreas Jaekel ZEV_SRCNAME(rec), 26563aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 26663aba447SAndreas Jaekel } 26763aba447SAndreas Jaekel 26863aba447SAndreas Jaekel static void 26963aba447SAndreas Jaekel zev_print_znode_write(char *buf) 27063aba447SAndreas Jaekel { 27163aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 27263aba447SAndreas Jaekel time_t op_time = rec->op_time; 27363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 27463aba447SAndreas Jaekel 27563aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 27663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 27763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 27863aba447SAndreas Jaekel rec->offset, rec->length); 27963aba447SAndreas Jaekel } 28063aba447SAndreas Jaekel 28163aba447SAndreas Jaekel static void 28263aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 28363aba447SAndreas Jaekel { 28463aba447SAndreas Jaekel zev_print_znode_write(buf); 28563aba447SAndreas Jaekel } 28663aba447SAndreas Jaekel 28763aba447SAndreas Jaekel static void 28863aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 28963aba447SAndreas Jaekel { 29063aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 29163aba447SAndreas Jaekel time_t op_time = rec->op_time; 29263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 29363aba447SAndreas Jaekel 294*c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 29563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 296*c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 29763aba447SAndreas Jaekel } 29863aba447SAndreas Jaekel 29963aba447SAndreas Jaekel static void 30063aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 30163aba447SAndreas Jaekel { 30263aba447SAndreas Jaekel zev_print_znode_setattr(buf); 30363aba447SAndreas Jaekel } 30463aba447SAndreas Jaekel 30563aba447SAndreas Jaekel static void 3069193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 3079193e9c2SAndreas Jaekel { 30863aba447SAndreas Jaekel int record_len; 30963aba447SAndreas Jaekel int op; 3109193e9c2SAndreas Jaekel 31163aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 31263aba447SAndreas Jaekel if (record_len != len) { 31363aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 31463aba447SAndreas Jaekel record_len, len); 3159193e9c2SAndreas Jaekel exit(1); 3169193e9c2SAndreas Jaekel } 31763aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 3189193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 31963aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3209193e9c2SAndreas Jaekel exit(1); 3219193e9c2SAndreas Jaekel } 32263aba447SAndreas Jaekel switch (op) { 32363aba447SAndreas Jaekel case ZEV_OP_ERROR: 32463aba447SAndreas Jaekel zev_print_error(buf); 3259193e9c2SAndreas Jaekel break; 32601c2c787SAndreas Jaekel case ZEV_OP_MARK: 32701c2c787SAndreas Jaekel zev_print_mark(buf); 32801c2c787SAndreas Jaekel break; 32963aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 33063aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3319193e9c2SAndreas Jaekel break; 33263aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 33363aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3349193e9c2SAndreas Jaekel break; 33563aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 33663aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3379193e9c2SAndreas Jaekel break; 33863aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 33963aba447SAndreas Jaekel zev_print_zvol_write(buf); 34063aba447SAndreas Jaekel break; 34163aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 34263aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 34363aba447SAndreas Jaekel break; 34463aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 34563aba447SAndreas Jaekel zev_print_znode_create(buf); 34663aba447SAndreas Jaekel break; 34763aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 34863aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 34963aba447SAndreas Jaekel break; 35063aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 35163aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 35263aba447SAndreas Jaekel break; 35363aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 35463aba447SAndreas Jaekel zev_print_znode_remove(buf); 35563aba447SAndreas Jaekel break; 35663aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 35763aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 35863aba447SAndreas Jaekel break; 35963aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 36063aba447SAndreas Jaekel zev_print_znode_link(buf); 36163aba447SAndreas Jaekel break; 36263aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 36363aba447SAndreas Jaekel zev_print_znode_symlink(buf); 36463aba447SAndreas Jaekel break; 36563aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 36663aba447SAndreas Jaekel zev_print_znode_rename(buf); 36763aba447SAndreas Jaekel break; 36863aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 36963aba447SAndreas Jaekel zev_print_znode_write(buf); 37063aba447SAndreas Jaekel break; 37163aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 37263aba447SAndreas Jaekel zev_print_znode_truncate(buf); 37363aba447SAndreas Jaekel break; 37463aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 37563aba447SAndreas Jaekel zev_print_znode_setattr(buf); 37663aba447SAndreas Jaekel break; 37763aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 37863aba447SAndreas Jaekel zev_print_znode_acl(buf); 3799193e9c2SAndreas Jaekel break; 3809193e9c2SAndreas Jaekel default: 38163aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 3829193e9c2SAndreas Jaekel exit(1); 3839193e9c2SAndreas Jaekel } 3849193e9c2SAndreas Jaekel } 3859193e9c2SAndreas Jaekel 3869193e9c2SAndreas Jaekel static void 3872bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 3882bb8e5e2SAndreas Jaekel { 3892bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 3902bb8e5e2SAndreas Jaekel int ret; 3919193e9c2SAndreas Jaekel char buf[4096]; 39268a46c64SAndreas Jaekel zev_event_t *ev; 39368a46c64SAndreas Jaekel int off = 0; 3942bb8e5e2SAndreas Jaekel while (1) { 3952bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 3962bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 3972bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 3982bb8e5e2SAndreas Jaekel if (ret < 0) { 3992bb8e5e2SAndreas Jaekel perror("poll failed"); 4002bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 4012bb8e5e2SAndreas Jaekel } 4022bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 4032bb8e5e2SAndreas Jaekel continue; 4042bb8e5e2SAndreas Jaekel /* data available */ 4052bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 4062bb8e5e2SAndreas Jaekel if (ret < 0) { 4072bb8e5e2SAndreas Jaekel perror("read failed"); 4082bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 4092bb8e5e2SAndreas Jaekel } 4102bb8e5e2SAndreas Jaekel if (ret == 0) 4112bb8e5e2SAndreas Jaekel continue; 41268a46c64SAndreas Jaekel while (ret > off) { 41368a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 41468a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 41568a46c64SAndreas Jaekel off += ev->header.record_len; 41668a46c64SAndreas Jaekel } 417108668daSAndreas Jaekel off = 0; 4182bb8e5e2SAndreas Jaekel } 4192bb8e5e2SAndreas Jaekel return; 4202bb8e5e2SAndreas Jaekel } 4212bb8e5e2SAndreas Jaekel 4222bb8e5e2SAndreas Jaekel static void 4232bb8e5e2SAndreas Jaekel usage(char *progname) 4242bb8e5e2SAndreas Jaekel { 4252bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 4262bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 4272bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 4282bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 429205a9bc9SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 4302bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 4312bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 4322bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 4332bb8e5e2SAndreas Jaekel ZEV_DEVICE); 43401c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 4352bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 4362bb8e5e2SAndreas Jaekel } 4372bb8e5e2SAndreas Jaekel 4382bb8e5e2SAndreas Jaekel static int 4392bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 4402bb8e5e2SAndreas Jaekel { 4412bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 4422bb8e5e2SAndreas Jaekel 4432bb8e5e2SAndreas Jaekel errno = 0; 4442bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 4452bb8e5e2SAndreas Jaekel if (errno) { 4462bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 4472bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4482bb8e5e2SAndreas Jaekel } 4492bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 4502bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 4512bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4522bb8e5e2SAndreas Jaekel } 4532bb8e5e2SAndreas Jaekel return (0); 4542bb8e5e2SAndreas Jaekel } 4552bb8e5e2SAndreas Jaekel 4562bb8e5e2SAndreas Jaekel static int 457205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 458205a9bc9SAndreas Jaekel { 459205a9bc9SAndreas Jaekel uint64_t queuelen; 460205a9bc9SAndreas Jaekel 461205a9bc9SAndreas Jaekel errno = 0; 462205a9bc9SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 463205a9bc9SAndreas Jaekel if (errno) { 464205a9bc9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 465205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 466205a9bc9SAndreas Jaekel } 467205a9bc9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 468205a9bc9SAndreas Jaekel perror("setting poll wakeup queue length failed"); 469205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 470205a9bc9SAndreas Jaekel } 471205a9bc9SAndreas Jaekel return (0); 472205a9bc9SAndreas Jaekel } 473205a9bc9SAndreas Jaekel 474205a9bc9SAndreas Jaekel static int 4752bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 4762bb8e5e2SAndreas Jaekel { 4772bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 4782bb8e5e2SAndreas Jaekel int len; 4792bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 4802bb8e5e2SAndreas Jaekel len = strlen(poolname); 4812bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 4822bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 4832bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4842bb8e5e2SAndreas Jaekel } 4852bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 4862bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 4872bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 4882bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 4892bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4902bb8e5e2SAndreas Jaekel } 4912bb8e5e2SAndreas Jaekel return (0); 4922bb8e5e2SAndreas Jaekel } 4932bb8e5e2SAndreas Jaekel 4942bb8e5e2SAndreas Jaekel int 4952bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 4962bb8e5e2SAndreas Jaekel { 4972bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 4982bb8e5e2SAndreas Jaekel } 4992bb8e5e2SAndreas Jaekel 5002bb8e5e2SAndreas Jaekel int 5012bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 5022bb8e5e2SAndreas Jaekel { 5032bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 5042bb8e5e2SAndreas Jaekel } 5052bb8e5e2SAndreas Jaekel 50601c2c787SAndreas Jaekel static int 50701c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 50801c2c787SAndreas Jaekel { 50901c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 51001c2c787SAndreas Jaekel uint64_t guid; 51101c2c787SAndreas Jaekel int len; 51201c2c787SAndreas Jaekel char *p; 51301c2c787SAndreas Jaekel 51401c2c787SAndreas Jaekel p = strchr(arg, ':'); 51501c2c787SAndreas Jaekel if (!p) { 51601c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 51701c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 51801c2c787SAndreas Jaekel exit (EXIT_FAILURE); 51901c2c787SAndreas Jaekel } 52001c2c787SAndreas Jaekel *p = '\n'; 52101c2c787SAndreas Jaekel p++; 52201c2c787SAndreas Jaekel 52301c2c787SAndreas Jaekel errno = 0; 52401c2c787SAndreas Jaekel guid = strtoll(optarg, (char **)NULL, 10); 52501c2c787SAndreas Jaekel if (errno) { 52601c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 52701c2c787SAndreas Jaekel exit (EXIT_FAILURE); 52801c2c787SAndreas Jaekel } 52901c2c787SAndreas Jaekel 53001c2c787SAndreas Jaekel len = strlen(p); 53101c2c787SAndreas Jaekel 53201c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 53301c2c787SAndreas Jaekel if (!mark) { 53401c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 53501c2c787SAndreas Jaekel strerror(errno)); 53601c2c787SAndreas Jaekel exit (EXIT_FAILURE); 53701c2c787SAndreas Jaekel } 53801c2c787SAndreas Jaekel mark->zev_guid = guid; 53901c2c787SAndreas Jaekel mark->zev_mark_id = 0; 54001c2c787SAndreas Jaekel mark->zev_payload_len = len; 54101c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 54201c2c787SAndreas Jaekel 54301c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 54401c2c787SAndreas Jaekel perror("queueing mark failed"); 54501c2c787SAndreas Jaekel return (EXIT_FAILURE); 54601c2c787SAndreas Jaekel } 54701c2c787SAndreas Jaekel 54801c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 54901c2c787SAndreas Jaekel return (0); 55001c2c787SAndreas Jaekel } 55101c2c787SAndreas Jaekel 5522bb8e5e2SAndreas Jaekel int 5532bb8e5e2SAndreas Jaekel main(int argc, char **argv) 5542bb8e5e2SAndreas Jaekel { 5552bb8e5e2SAndreas Jaekel int fd; 5562bb8e5e2SAndreas Jaekel int c; 5572bb8e5e2SAndreas Jaekel int ops = 0; 5582bb8e5e2SAndreas Jaekel extern char *optarg; 5592bb8e5e2SAndreas Jaekel 5602bb8e5e2SAndreas Jaekel /* open device */ 5612bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 5622bb8e5e2SAndreas Jaekel if (fd < 0) { 5632bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 5642bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 5652bb8e5e2SAndreas Jaekel } 56601c2c787SAndreas Jaekel while ((c = getopt(argc, argv, "spdk:q:t:m:M:h?")) != -1) { 5672bb8e5e2SAndreas Jaekel switch(c) { 5682bb8e5e2SAndreas Jaekel case 's': 5692bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 5702bb8e5e2SAndreas Jaekel break; 5712bb8e5e2SAndreas Jaekel case 'p': 5722bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 5732bb8e5e2SAndreas Jaekel break; 5742bb8e5e2SAndreas Jaekel case 'd': 5752bb8e5e2SAndreas Jaekel zev_device = optarg; 5762bb8e5e2SAndreas Jaekel break; 5772bb8e5e2SAndreas Jaekel case 'q': 5782bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 579205a9bc9SAndreas Jaekel case 't': 580205a9bc9SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 5812bb8e5e2SAndreas Jaekel case 'm': 5822bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 5832bb8e5e2SAndreas Jaekel case 'M': 5842bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 58501c2c787SAndreas Jaekel case 'k': 58601c2c787SAndreas Jaekel return zev_mark(fd, optarg); 5872bb8e5e2SAndreas Jaekel case 'h': 5882bb8e5e2SAndreas Jaekel case '?': 5892bb8e5e2SAndreas Jaekel default: 5902bb8e5e2SAndreas Jaekel usage(argv[0]); 5912bb8e5e2SAndreas Jaekel } 5922bb8e5e2SAndreas Jaekel } 5932bb8e5e2SAndreas Jaekel if (!ops) 5942bb8e5e2SAndreas Jaekel usage(argv[0]); 5952bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 5962bb8e5e2SAndreas Jaekel zev_statistics(fd); 5972bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 5982bb8e5e2SAndreas Jaekel zev_poll_events(fd); 5992bb8e5e2SAndreas Jaekel close(fd); 6002bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 6012bb8e5e2SAndreas Jaekel } 6022bb8e5e2SAndreas Jaekel 603