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) 16*e9a5e479SAndreas Jaekel #define OP_DEBUG_INFO (1 << 5) 172bb8e5e2SAndreas Jaekel 18*e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 192bb8e5e2SAndreas Jaekel 202bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 212bb8e5e2SAndreas Jaekel 229193e9c2SAndreas Jaekel static char *zev_op_name[] = { 239193e9c2SAndreas Jaekel "ZEV_OP_ERROR", 2401c2c787SAndreas Jaekel "ZEV_OP_MARK", 259193e9c2SAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 269193e9c2SAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 279193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 289193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 299193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 309193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 319193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 329193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 339193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 349193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 359193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_LINK", 369193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 379193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 389193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 399193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 409193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 419193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_ACL", 429193e9c2SAndreas Jaekel NULL 439193e9c2SAndreas Jaekel }; 449193e9c2SAndreas Jaekel 45*e9a5e479SAndreas Jaekel static int 462bb8e5e2SAndreas Jaekel zev_statistics(int fd) 472bb8e5e2SAndreas Jaekel { 482bb8e5e2SAndreas Jaekel zev_statistics_t zs; 49*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 502bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 51*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 522bb8e5e2SAndreas Jaekel } 532bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 542bb8e5e2SAndreas Jaekel 552bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 562bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_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 60*e9a5e479SAndreas Jaekel printf(" discarded events : %lu\n", 61*e9a5e479SAndreas Jaekel zs.zev_cnt_discarded_events); 62*e9a5e479SAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 63*e9a5e479SAndreas Jaekel 642bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 652bb8e5e2SAndreas Jaekel 662bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 672bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 682bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 692bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 702bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 712bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 722bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 732bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 742bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 752bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 762bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 772bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 782bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 792bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 802bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 812bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 822bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 83*e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 842bb8e5e2SAndreas Jaekel } 852bb8e5e2SAndreas Jaekel 862bb8e5e2SAndreas Jaekel static void 8763aba447SAndreas Jaekel zev_print_error(char *buf) 8863aba447SAndreas Jaekel { 8963aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 9063aba447SAndreas Jaekel time_t op_time = rec->op_time; 9163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 9263aba447SAndreas Jaekel 9363aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 9463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 9563aba447SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 9663aba447SAndreas Jaekel } 9763aba447SAndreas Jaekel 9863aba447SAndreas Jaekel static void 9901c2c787SAndreas Jaekel zev_print_mark(char *buf) 10001c2c787SAndreas Jaekel { 10101c2c787SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 10201c2c787SAndreas Jaekel time_t op_time = rec->op_time; 10301c2c787SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 10401c2c787SAndreas Jaekel 10501c2c787SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 10601c2c787SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id, 10701c2c787SAndreas Jaekel rec->payload_len); 10801c2c787SAndreas Jaekel } 10901c2c787SAndreas Jaekel 11001c2c787SAndreas Jaekel static void 11163aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 11263aba447SAndreas Jaekel { 11363aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 11463aba447SAndreas Jaekel time_t op_time = rec->op_time; 11563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 11663aba447SAndreas Jaekel 11763aba447SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 11863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 11963aba447SAndreas Jaekel rec->guid, 12063aba447SAndreas Jaekel rec->remount ? "true" : "false", 12163aba447SAndreas Jaekel ZEV_DATASET(rec), 12263aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 12363aba447SAndreas Jaekel } 12463aba447SAndreas Jaekel 12563aba447SAndreas Jaekel static void 12663aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 12763aba447SAndreas Jaekel { 12863aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 12963aba447SAndreas Jaekel time_t op_time = rec->op_time; 13063aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 13163aba447SAndreas Jaekel 13263aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 13363aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 13463aba447SAndreas Jaekel rec->guid); 13563aba447SAndreas Jaekel } 13663aba447SAndreas Jaekel 13763aba447SAndreas Jaekel static void 13863aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 13963aba447SAndreas Jaekel { 14063aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 14163aba447SAndreas Jaekel time_t op_time = rec->op_time; 14263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 14363aba447SAndreas Jaekel 14463aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 14563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 14663aba447SAndreas Jaekel rec->guid, 14763aba447SAndreas Jaekel rec->offset, 14863aba447SAndreas Jaekel rec->length); 14963aba447SAndreas Jaekel } 15063aba447SAndreas Jaekel 15163aba447SAndreas Jaekel static void 15263aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 15363aba447SAndreas Jaekel { 15463aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 15563aba447SAndreas Jaekel } 15663aba447SAndreas Jaekel 15763aba447SAndreas Jaekel static void 15863aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 15963aba447SAndreas Jaekel { 16063aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 16163aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 16263aba447SAndreas Jaekel time_t op_time = rec->op_time; 16363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 16463aba447SAndreas Jaekel 16563aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 16663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 16763aba447SAndreas Jaekel rec->guid, 16863aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 16963aba447SAndreas Jaekel } 17063aba447SAndreas Jaekel 17163aba447SAndreas Jaekel static void 17263aba447SAndreas Jaekel zev_print_znode_create(char *buf) 17363aba447SAndreas Jaekel { 17463aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 17563aba447SAndreas Jaekel time_t op_time = rec->op_time; 17663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 17763aba447SAndreas Jaekel 178c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 179c035b1e8SAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 18063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 18163aba447SAndreas Jaekel rec->guid, 18263aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 18363aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 184c035b1e8SAndreas Jaekel rec->file.mtime, rec->parent.mtime, 18563aba447SAndreas Jaekel ZEV_NAME(rec)); 18663aba447SAndreas Jaekel } 18763aba447SAndreas Jaekel 18863aba447SAndreas Jaekel static void 18963aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 19063aba447SAndreas Jaekel { 19163aba447SAndreas Jaekel zev_print_znode_create(buf); 19263aba447SAndreas Jaekel } 19363aba447SAndreas Jaekel 19463aba447SAndreas Jaekel static void 19563aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 19663aba447SAndreas Jaekel { 19763aba447SAndreas Jaekel zev_print_znode_create(buf); 19863aba447SAndreas Jaekel } 19963aba447SAndreas Jaekel 20063aba447SAndreas Jaekel static void 20163aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 20263aba447SAndreas Jaekel { 20363aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 20463aba447SAndreas Jaekel time_t op_time = rec->op_time; 20563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 20663aba447SAndreas Jaekel 2076db5d4ecSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n", 20863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 20963aba447SAndreas Jaekel rec->guid, 21063aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 2116db5d4ecSAndreas Jaekel rec->file.mtime, 21263aba447SAndreas Jaekel ZEV_NAME(rec)); 21363aba447SAndreas Jaekel } 21463aba447SAndreas Jaekel 21563aba447SAndreas Jaekel static void 21663aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 21763aba447SAndreas Jaekel { 21863aba447SAndreas Jaekel zev_print_znode_remove(buf); 21963aba447SAndreas Jaekel } 22063aba447SAndreas Jaekel 22163aba447SAndreas Jaekel static void 22263aba447SAndreas Jaekel zev_print_znode_link(char *buf) 22363aba447SAndreas Jaekel { 22463aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 22563aba447SAndreas Jaekel time_t op_time = rec->op_time; 22663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 22763aba447SAndreas Jaekel 22803101f54SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 22903101f54SAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 23063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 23163aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 23263aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 23303101f54SAndreas Jaekel rec->file.ctime, rec->parent.ctime, 23463aba447SAndreas Jaekel ZEV_NAME(rec)); 23563aba447SAndreas Jaekel printf("links: %d\n", rec->file.links); 23663aba447SAndreas Jaekel } 23763aba447SAndreas Jaekel 23863aba447SAndreas Jaekel static void 23963aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 24063aba447SAndreas Jaekel { 24163aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 24263aba447SAndreas Jaekel time_t op_time = rec->op_time; 24363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 24463aba447SAndreas Jaekel 24563aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 24663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 24763aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 24863aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 24963aba447SAndreas Jaekel ZEV_NAME(rec), 25063aba447SAndreas Jaekel ZEV_LINK(rec)); 25163aba447SAndreas Jaekel } 25263aba447SAndreas Jaekel 25363aba447SAndreas Jaekel static void 25463aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 25563aba447SAndreas Jaekel { 25663aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 25763aba447SAndreas Jaekel time_t op_time = rec->op_time; 25863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 25963aba447SAndreas Jaekel 26063aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 261c035b1e8SAndreas Jaekel "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 262c035b1e8SAndreas Jaekel "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 26363aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 26463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 26563aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 26663aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 26763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 268c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 269c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 270c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 27163aba447SAndreas Jaekel ZEV_SRCNAME(rec), 27263aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 27363aba447SAndreas Jaekel } 27463aba447SAndreas Jaekel 27563aba447SAndreas Jaekel static void 27663aba447SAndreas Jaekel zev_print_znode_write(char *buf) 27763aba447SAndreas Jaekel { 27863aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 27963aba447SAndreas Jaekel time_t op_time = rec->op_time; 28063aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 28163aba447SAndreas Jaekel 28263aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 28363aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 28463aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 28563aba447SAndreas Jaekel rec->offset, rec->length); 28663aba447SAndreas Jaekel } 28763aba447SAndreas Jaekel 28863aba447SAndreas Jaekel static void 28963aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 29063aba447SAndreas Jaekel { 29163aba447SAndreas Jaekel zev_print_znode_write(buf); 29263aba447SAndreas Jaekel } 29363aba447SAndreas Jaekel 29463aba447SAndreas Jaekel static void 29563aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 29663aba447SAndreas Jaekel { 29763aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 29863aba447SAndreas Jaekel time_t op_time = rec->op_time; 29963aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 30063aba447SAndreas Jaekel 301c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 30263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 303c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 30463aba447SAndreas Jaekel } 30563aba447SAndreas Jaekel 30663aba447SAndreas Jaekel static void 30763aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 30863aba447SAndreas Jaekel { 30963aba447SAndreas Jaekel zev_print_znode_setattr(buf); 31063aba447SAndreas Jaekel } 31163aba447SAndreas Jaekel 31263aba447SAndreas Jaekel static void 3139193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 3149193e9c2SAndreas Jaekel { 31563aba447SAndreas Jaekel int record_len; 31663aba447SAndreas Jaekel int op; 3179193e9c2SAndreas Jaekel 31863aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 31963aba447SAndreas Jaekel if (record_len != len) { 32063aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 32163aba447SAndreas Jaekel record_len, len); 3229193e9c2SAndreas Jaekel exit(1); 3239193e9c2SAndreas Jaekel } 32463aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 3259193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 32663aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3279193e9c2SAndreas Jaekel exit(1); 3289193e9c2SAndreas Jaekel } 32963aba447SAndreas Jaekel switch (op) { 33063aba447SAndreas Jaekel case ZEV_OP_ERROR: 33163aba447SAndreas Jaekel zev_print_error(buf); 3329193e9c2SAndreas Jaekel break; 33301c2c787SAndreas Jaekel case ZEV_OP_MARK: 33401c2c787SAndreas Jaekel zev_print_mark(buf); 33501c2c787SAndreas Jaekel break; 33663aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 33763aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3389193e9c2SAndreas Jaekel break; 33963aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 34063aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3419193e9c2SAndreas Jaekel break; 34263aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 34363aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3449193e9c2SAndreas Jaekel break; 34563aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 34663aba447SAndreas Jaekel zev_print_zvol_write(buf); 34763aba447SAndreas Jaekel break; 34863aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 34963aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 35063aba447SAndreas Jaekel break; 35163aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 35263aba447SAndreas Jaekel zev_print_znode_create(buf); 35363aba447SAndreas Jaekel break; 35463aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 35563aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 35663aba447SAndreas Jaekel break; 35763aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 35863aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 35963aba447SAndreas Jaekel break; 36063aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 36163aba447SAndreas Jaekel zev_print_znode_remove(buf); 36263aba447SAndreas Jaekel break; 36363aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 36463aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 36563aba447SAndreas Jaekel break; 36663aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 36763aba447SAndreas Jaekel zev_print_znode_link(buf); 36863aba447SAndreas Jaekel break; 36963aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 37063aba447SAndreas Jaekel zev_print_znode_symlink(buf); 37163aba447SAndreas Jaekel break; 37263aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 37363aba447SAndreas Jaekel zev_print_znode_rename(buf); 37463aba447SAndreas Jaekel break; 37563aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 37663aba447SAndreas Jaekel zev_print_znode_write(buf); 37763aba447SAndreas Jaekel break; 37863aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 37963aba447SAndreas Jaekel zev_print_znode_truncate(buf); 38063aba447SAndreas Jaekel break; 38163aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 38263aba447SAndreas Jaekel zev_print_znode_setattr(buf); 38363aba447SAndreas Jaekel break; 38463aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 38563aba447SAndreas Jaekel zev_print_znode_acl(buf); 3869193e9c2SAndreas Jaekel break; 3879193e9c2SAndreas Jaekel default: 38863aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 3899193e9c2SAndreas Jaekel exit(1); 3909193e9c2SAndreas Jaekel } 3919193e9c2SAndreas Jaekel } 3929193e9c2SAndreas Jaekel 393*e9a5e479SAndreas Jaekel static int 3942bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 3952bb8e5e2SAndreas Jaekel { 3962bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 3972bb8e5e2SAndreas Jaekel int ret; 3989193e9c2SAndreas Jaekel char buf[4096]; 39968a46c64SAndreas Jaekel zev_event_t *ev; 40068a46c64SAndreas Jaekel int off = 0; 401*e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 402*e9a5e479SAndreas Jaekel int q_fd; 403*e9a5e479SAndreas Jaekel 404*e9a5e479SAndreas Jaekel /* create temporary queue */ 405*e9a5e479SAndreas Jaekel aq.zev_max_queue_len = 0; 406*e9a5e479SAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 407*e9a5e479SAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 408*e9a5e479SAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 409*e9a5e479SAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 410*e9a5e479SAndreas Jaekel 411*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 412*e9a5e479SAndreas Jaekel perror("adding temporary queue failed"); 413*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 414*e9a5e479SAndreas Jaekel } 415*e9a5e479SAndreas Jaekel 416*e9a5e479SAndreas Jaekel snprintf(buf, sizeof(buf), "/devices/pseudo/zev@0:%s", aq.zev_name); 417*e9a5e479SAndreas Jaekel q_fd = open(buf, O_RDONLY); 418*e9a5e479SAndreas Jaekel if (q_fd < 0) { 419*e9a5e479SAndreas Jaekel perror("opening queue device failed"); 420*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 421*e9a5e479SAndreas Jaekel } 422*e9a5e479SAndreas Jaekel 4232bb8e5e2SAndreas Jaekel while (1) { 424*e9a5e479SAndreas Jaekel pfd[0].fd = q_fd; 4252bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 4262bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 4272bb8e5e2SAndreas Jaekel if (ret < 0) { 4282bb8e5e2SAndreas Jaekel perror("poll failed"); 429*e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 4302bb8e5e2SAndreas Jaekel } 4312bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 4322bb8e5e2SAndreas Jaekel continue; 4332bb8e5e2SAndreas Jaekel /* data available */ 434*e9a5e479SAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 4352bb8e5e2SAndreas Jaekel if (ret < 0) { 4362bb8e5e2SAndreas Jaekel perror("read failed"); 437*e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 4382bb8e5e2SAndreas Jaekel } 4392bb8e5e2SAndreas Jaekel if (ret == 0) 4402bb8e5e2SAndreas Jaekel continue; 44168a46c64SAndreas Jaekel while (ret > off) { 44268a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 44368a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 44468a46c64SAndreas Jaekel off += ev->header.record_len; 44568a46c64SAndreas Jaekel } 446108668daSAndreas Jaekel off = 0; 4472bb8e5e2SAndreas Jaekel } 448*e9a5e479SAndreas Jaekel close(q_fd); 449*e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 4502bb8e5e2SAndreas Jaekel } 4512bb8e5e2SAndreas Jaekel 4522bb8e5e2SAndreas Jaekel static void 4532bb8e5e2SAndreas Jaekel usage(char *progname) 4542bb8e5e2SAndreas Jaekel { 455*e9a5e479SAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 456*e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 457*e9a5e479SAndreas Jaekel fprintf(stderr, " Status information:\n"); 4582bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 4592bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 460*e9a5e479SAndreas Jaekel fprintf(stderr, " -D print zev module debug " 461*e9a5e479SAndreas Jaekel "information\n"); 462*e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 463*e9a5e479SAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 464*e9a5e479SAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 465*e9a5e479SAndreas Jaekel "length\n"); 466*e9a5e479SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 467*e9a5e479SAndreas Jaekel "this pool\n"); 4682bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 469*e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 470*e9a5e479SAndreas Jaekel fprintf(stderr, " Queue management:\n"); 471*e9a5e479SAndreas Jaekel fprintf(stderr, " -l list queues\n"); 472*e9a5e479SAndreas Jaekel fprintf(stderr, " -a <name> add queue\n"); 473*e9a5e479SAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 474*e9a5e479SAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 475*e9a5e479SAndreas Jaekel "(default)\n"); 476*e9a5e479SAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 477*e9a5e479SAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 478*e9a5e479SAndreas Jaekel fprintf(stderr, " -q <name> <bytes> set maximum event queue " 479*e9a5e479SAndreas Jaekel "length\n"); 480*e9a5e479SAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 481*e9a5e479SAndreas Jaekel "throttle\n"); 482*e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 483*e9a5e479SAndreas Jaekel fprintf(stderr, " Other options:\n"); 484*e9a5e479SAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 485*e9a5e479SAndreas Jaekel "('%s')\n", ZEV_DEVICE); 48601c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 4872bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 4882bb8e5e2SAndreas Jaekel } 4892bb8e5e2SAndreas Jaekel 4902bb8e5e2SAndreas Jaekel static int 491*e9a5e479SAndreas Jaekel zev_add_queue(int fd, char *arg) 4922bb8e5e2SAndreas Jaekel { 493*e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 494*e9a5e479SAndreas Jaekel int namelen; 4952bb8e5e2SAndreas Jaekel 496*e9a5e479SAndreas Jaekel namelen = strlen(arg); 497*e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 498*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 4992bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5002bb8e5e2SAndreas Jaekel } 501*e9a5e479SAndreas Jaekel 502*e9a5e479SAndreas Jaekel aq.zev_namelen = namelen; 503*e9a5e479SAndreas Jaekel strcpy(aq.zev_name, arg); 504*e9a5e479SAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; /* non-blocking, but persistent */ 505*e9a5e479SAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 506*e9a5e479SAndreas Jaekel 507*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 508*e9a5e479SAndreas Jaekel perror("adding queue failed"); 5092bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5102bb8e5e2SAndreas Jaekel } 5112bb8e5e2SAndreas Jaekel return (0); 5122bb8e5e2SAndreas Jaekel } 5132bb8e5e2SAndreas Jaekel 5142bb8e5e2SAndreas Jaekel static int 515*e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg) 516205a9bc9SAndreas Jaekel { 517*e9a5e479SAndreas Jaekel zev_ioctl_remove_queue_t aq; 518*e9a5e479SAndreas Jaekel int namelen; 519205a9bc9SAndreas Jaekel 520*e9a5e479SAndreas Jaekel namelen = strlen(arg); 521*e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 522*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 523205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 524205a9bc9SAndreas Jaekel } 525*e9a5e479SAndreas Jaekel 526*e9a5e479SAndreas Jaekel aq.zev_namelen = namelen; 527*e9a5e479SAndreas Jaekel strcpy(aq.zev_name, arg); 528*e9a5e479SAndreas Jaekel 529*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 530*e9a5e479SAndreas Jaekel perror("removing queue failed"); 531*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 532*e9a5e479SAndreas Jaekel } 533*e9a5e479SAndreas Jaekel return (0); 534*e9a5e479SAndreas Jaekel } 535*e9a5e479SAndreas Jaekel 536*e9a5e479SAndreas Jaekel static int 537*e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 538*e9a5e479SAndreas Jaekel { 539*e9a5e479SAndreas Jaekel uint64_t maxqueuelen; 540*e9a5e479SAndreas Jaekel 541*e9a5e479SAndreas Jaekel errno = 0; 542*e9a5e479SAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 543*e9a5e479SAndreas Jaekel if (errno) { 544*e9a5e479SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 545*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 546*e9a5e479SAndreas Jaekel } 547*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 548*e9a5e479SAndreas Jaekel perror("setting max queue length failed"); 549205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 550205a9bc9SAndreas Jaekel } 551205a9bc9SAndreas Jaekel return (0); 552205a9bc9SAndreas Jaekel } 553205a9bc9SAndreas Jaekel 554205a9bc9SAndreas Jaekel static int 5552bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 5562bb8e5e2SAndreas Jaekel { 5572bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 5582bb8e5e2SAndreas Jaekel int len; 5592bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 5602bb8e5e2SAndreas Jaekel len = strlen(poolname); 5612bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 5622bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 5632bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5642bb8e5e2SAndreas Jaekel } 5652bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 5662bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 5672bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 5682bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 5692bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5702bb8e5e2SAndreas Jaekel } 5712bb8e5e2SAndreas Jaekel return (0); 5722bb8e5e2SAndreas Jaekel } 5732bb8e5e2SAndreas Jaekel 5742bb8e5e2SAndreas Jaekel int 5752bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 5762bb8e5e2SAndreas Jaekel { 5772bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 5782bb8e5e2SAndreas Jaekel } 5792bb8e5e2SAndreas Jaekel 5802bb8e5e2SAndreas Jaekel int 5812bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 5822bb8e5e2SAndreas Jaekel { 5832bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 5842bb8e5e2SAndreas Jaekel } 5852bb8e5e2SAndreas Jaekel 58601c2c787SAndreas Jaekel static int 587*e9a5e479SAndreas Jaekel zev_debug_info(int fd) 588*e9a5e479SAndreas Jaekel { 589*e9a5e479SAndreas Jaekel zev_ioctl_debug_info_t di; 590*e9a5e479SAndreas Jaekel 591*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 592*e9a5e479SAndreas Jaekel perror("getting zev debug info failed"); 593*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 594*e9a5e479SAndreas Jaekel } 595*e9a5e479SAndreas Jaekel 596*e9a5e479SAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 597*e9a5e479SAndreas Jaekel return 0; 598*e9a5e479SAndreas Jaekel } 599*e9a5e479SAndreas Jaekel 600*e9a5e479SAndreas Jaekel static int 60101c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 60201c2c787SAndreas Jaekel { 60301c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 60401c2c787SAndreas Jaekel uint64_t guid; 60501c2c787SAndreas Jaekel int len; 60601c2c787SAndreas Jaekel char *p; 60701c2c787SAndreas Jaekel 60801c2c787SAndreas Jaekel p = strchr(arg, ':'); 60901c2c787SAndreas Jaekel if (!p) { 61001c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 61101c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 61201c2c787SAndreas Jaekel exit (EXIT_FAILURE); 61301c2c787SAndreas Jaekel } 61401c2c787SAndreas Jaekel *p = '\n'; 61501c2c787SAndreas Jaekel p++; 61601c2c787SAndreas Jaekel 61701c2c787SAndreas Jaekel errno = 0; 618*e9a5e479SAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 61901c2c787SAndreas Jaekel if (errno) { 62001c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 62101c2c787SAndreas Jaekel exit (EXIT_FAILURE); 62201c2c787SAndreas Jaekel } 62301c2c787SAndreas Jaekel 62401c2c787SAndreas Jaekel len = strlen(p); 62501c2c787SAndreas Jaekel 62601c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 62701c2c787SAndreas Jaekel if (!mark) { 62801c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 62901c2c787SAndreas Jaekel strerror(errno)); 63001c2c787SAndreas Jaekel exit (EXIT_FAILURE); 63101c2c787SAndreas Jaekel } 63201c2c787SAndreas Jaekel mark->zev_guid = guid; 63301c2c787SAndreas Jaekel mark->zev_mark_id = 0; 63401c2c787SAndreas Jaekel mark->zev_payload_len = len; 63501c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 63601c2c787SAndreas Jaekel 63701c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 63801c2c787SAndreas Jaekel perror("queueing mark failed"); 63901c2c787SAndreas Jaekel return (EXIT_FAILURE); 64001c2c787SAndreas Jaekel } 64101c2c787SAndreas Jaekel 64201c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 64301c2c787SAndreas Jaekel return (0); 64401c2c787SAndreas Jaekel } 64501c2c787SAndreas Jaekel 646*e9a5e479SAndreas Jaekel static int 647*e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 648*e9a5e479SAndreas Jaekel { 649*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 650*e9a5e479SAndreas Jaekel 651*e9a5e479SAndreas Jaekel gqp.zev_namelen = strlen(arg); 652*e9a5e479SAndreas Jaekel if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 653*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 654*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 655*e9a5e479SAndreas Jaekel } 656*e9a5e479SAndreas Jaekel strcpy(gqp.zev_name, arg); 657*e9a5e479SAndreas Jaekel 658*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 659*e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 660*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 661*e9a5e479SAndreas Jaekel } 662*e9a5e479SAndreas Jaekel if (block) { 663*e9a5e479SAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 664*e9a5e479SAndreas Jaekel } else { 665*e9a5e479SAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 666*e9a5e479SAndreas Jaekel } 667*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 668*e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 669*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 670*e9a5e479SAndreas Jaekel } 671*e9a5e479SAndreas Jaekel return (0); 672*e9a5e479SAndreas Jaekel } 673*e9a5e479SAndreas Jaekel 674*e9a5e479SAndreas Jaekel static int 675*e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 676*e9a5e479SAndreas Jaekel { 677*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 678*e9a5e479SAndreas Jaekel 679*e9a5e479SAndreas Jaekel if (!len) { 680*e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 681*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 682*e9a5e479SAndreas Jaekel } 683*e9a5e479SAndreas Jaekel 684*e9a5e479SAndreas Jaekel gqp.zev_namelen = strlen(arg); 685*e9a5e479SAndreas Jaekel if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 686*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 687*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 688*e9a5e479SAndreas Jaekel } 689*e9a5e479SAndreas Jaekel strcpy(gqp.zev_name, arg); 690*e9a5e479SAndreas Jaekel 691*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 692*e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 693*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 694*e9a5e479SAndreas Jaekel } 695*e9a5e479SAndreas Jaekel gqp.zev_max_queue_len = atol(len); 696*e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 697*e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 698*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 699*e9a5e479SAndreas Jaekel } 700*e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 701*e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 702*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 703*e9a5e479SAndreas Jaekel } 704*e9a5e479SAndreas Jaekel 705*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 706*e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 707*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 708*e9a5e479SAndreas Jaekel } 709*e9a5e479SAndreas Jaekel return (0); 710*e9a5e479SAndreas Jaekel } 711*e9a5e479SAndreas Jaekel 712*e9a5e479SAndreas Jaekel static int 713*e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 714*e9a5e479SAndreas Jaekel { 715*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 716*e9a5e479SAndreas Jaekel 717*e9a5e479SAndreas Jaekel if (!len) { 718*e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 719*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 720*e9a5e479SAndreas Jaekel } 721*e9a5e479SAndreas Jaekel 722*e9a5e479SAndreas Jaekel gqp.zev_namelen = strlen(arg); 723*e9a5e479SAndreas Jaekel if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 724*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 725*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 726*e9a5e479SAndreas Jaekel } 727*e9a5e479SAndreas Jaekel strcpy(gqp.zev_name, arg); 728*e9a5e479SAndreas Jaekel 729*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 730*e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 731*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 732*e9a5e479SAndreas Jaekel } 733*e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 734*e9a5e479SAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 735*e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 736*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 737*e9a5e479SAndreas Jaekel } 738*e9a5e479SAndreas Jaekel if ((gqp.zev_poll_wakeup_threshold < ZEV_MIN_POLL_WAKEUP_QUEUE_LEN) || 739*e9a5e479SAndreas Jaekel (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN)) { 740*e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 741*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 742*e9a5e479SAndreas Jaekel } 743*e9a5e479SAndreas Jaekel 744*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 745*e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 746*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 747*e9a5e479SAndreas Jaekel } 748*e9a5e479SAndreas Jaekel return (0); 749*e9a5e479SAndreas Jaekel } 750*e9a5e479SAndreas Jaekel 751*e9a5e479SAndreas Jaekel static int 752*e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg) 753*e9a5e479SAndreas Jaekel { 754*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 755*e9a5e479SAndreas Jaekel 756*e9a5e479SAndreas Jaekel gqp.zev_namelen = strlen(arg); 757*e9a5e479SAndreas Jaekel if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 758*e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 759*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 760*e9a5e479SAndreas Jaekel } 761*e9a5e479SAndreas Jaekel strcpy(gqp.zev_name, arg); 762*e9a5e479SAndreas Jaekel 763*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 764*e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 765*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 766*e9a5e479SAndreas Jaekel } 767*e9a5e479SAndreas Jaekel 768*e9a5e479SAndreas Jaekel printf("queue : %s\n", arg); 769*e9a5e479SAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 770*e9a5e479SAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 771*e9a5e479SAndreas Jaekel printf("persistent : %s\n", 772*e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 773*e9a5e479SAndreas Jaekel printf("blocking : %s\n", 774*e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 775*e9a5e479SAndreas Jaekel 776*e9a5e479SAndreas Jaekel return (0); 777*e9a5e479SAndreas Jaekel } 778*e9a5e479SAndreas Jaekel 779*e9a5e479SAndreas Jaekel static int 780*e9a5e479SAndreas Jaekel zev_list_queues(int fd) 781*e9a5e479SAndreas Jaekel { 782*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 783*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_list_t gql; 784*e9a5e479SAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 785*e9a5e479SAndreas Jaekel uint64_t i; 786*e9a5e479SAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 787*e9a5e479SAndreas Jaekel 788*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 789*e9a5e479SAndreas Jaekel perror("getting queue list failed"); 790*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 791*e9a5e479SAndreas Jaekel } 792*e9a5e479SAndreas Jaekel 793*e9a5e479SAndreas Jaekel printf("Name Size " 794*e9a5e479SAndreas Jaekel "Max Size Wakeup Per Block\n"); 795*e9a5e479SAndreas Jaekel 796*e9a5e479SAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 797*e9a5e479SAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 798*e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 799*e9a5e479SAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 800*e9a5e479SAndreas Jaekel 801*e9a5e479SAndreas Jaekel memcpy(gqp.zev_name, gql.zev_queue_name[i].zev_name, 802*e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 803*e9a5e479SAndreas Jaekel gqp.zev_namelen = gql.zev_queue_name[i].zev_namelen; 804*e9a5e479SAndreas Jaekel 805*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 806*e9a5e479SAndreas Jaekel if (errno == ENOENT) 807*e9a5e479SAndreas Jaekel continue; 808*e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 809*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 810*e9a5e479SAndreas Jaekel } 811*e9a5e479SAndreas Jaekel 812*e9a5e479SAndreas Jaekel memcpy(gs.zev_name, gql.zev_queue_name[i].zev_name, 813*e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 814*e9a5e479SAndreas Jaekel gs.zev_namelen = gql.zev_queue_name[i].zev_namelen; 815*e9a5e479SAndreas Jaekel 816*e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 817*e9a5e479SAndreas Jaekel if (errno == ENOENT) 818*e9a5e479SAndreas Jaekel continue; 819*e9a5e479SAndreas Jaekel perror("getting statistics data failed"); 820*e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 821*e9a5e479SAndreas Jaekel } 822*e9a5e479SAndreas Jaekel 823*e9a5e479SAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 824*e9a5e479SAndreas Jaekel " %-3s %-3s\n", 825*e9a5e479SAndreas Jaekel name, 826*e9a5e479SAndreas Jaekel gs.zev_statistics.zev_queue_len, 827*e9a5e479SAndreas Jaekel gqp.zev_max_queue_len, 828*e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold, 829*e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 830*e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 831*e9a5e479SAndreas Jaekel "yes" : "no"); 832*e9a5e479SAndreas Jaekel } 833*e9a5e479SAndreas Jaekel 834*e9a5e479SAndreas Jaekel return (0); 835*e9a5e479SAndreas Jaekel } 836*e9a5e479SAndreas Jaekel 8372bb8e5e2SAndreas Jaekel int 8382bb8e5e2SAndreas Jaekel main(int argc, char **argv) 8392bb8e5e2SAndreas Jaekel { 8402bb8e5e2SAndreas Jaekel int fd; 8412bb8e5e2SAndreas Jaekel int c; 8422bb8e5e2SAndreas Jaekel extern char *optarg; 8432bb8e5e2SAndreas Jaekel 8442bb8e5e2SAndreas Jaekel /* open device */ 8452bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 8462bb8e5e2SAndreas Jaekel if (fd < 0) { 8472bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 8482bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 8492bb8e5e2SAndreas Jaekel } 850*e9a5e479SAndreas Jaekel while ((c = getopt(argc, argv, "spd:Dlk:q:Qt:m:M:a:r:P:b:B:h?")) != -1){ 8512bb8e5e2SAndreas Jaekel switch(c) { 8522bb8e5e2SAndreas Jaekel case 's': 853*e9a5e479SAndreas Jaekel return zev_statistics(fd); 8542bb8e5e2SAndreas Jaekel case 'p': 855*e9a5e479SAndreas Jaekel return zev_poll_events(fd); 856*e9a5e479SAndreas Jaekel case 'D': 857*e9a5e479SAndreas Jaekel return zev_debug_info(fd); 8582bb8e5e2SAndreas Jaekel case 'd': 859*e9a5e479SAndreas Jaekel close(fd); 8602bb8e5e2SAndreas Jaekel zev_device = optarg; 861*e9a5e479SAndreas Jaekel fd = open(zev_device, O_RDONLY); 862*e9a5e479SAndreas Jaekel if (fd < 0) { 863*e9a5e479SAndreas Jaekel perror("opening zev device failed"); 864*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 865*e9a5e479SAndreas Jaekel } 8662bb8e5e2SAndreas Jaekel break; 867*e9a5e479SAndreas Jaekel case 'l': 868*e9a5e479SAndreas Jaekel return zev_list_queues(fd); 869*e9a5e479SAndreas Jaekel case 'Q': 870*e9a5e479SAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 8712bb8e5e2SAndreas Jaekel case 'q': 872*e9a5e479SAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 873205a9bc9SAndreas Jaekel case 't': 874*e9a5e479SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 875*e9a5e479SAndreas Jaekel argv[optind]); 8762bb8e5e2SAndreas Jaekel case 'm': 8772bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 8782bb8e5e2SAndreas Jaekel case 'M': 8792bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 88001c2c787SAndreas Jaekel case 'k': 88101c2c787SAndreas Jaekel return zev_mark(fd, optarg); 882*e9a5e479SAndreas Jaekel case 'a': 883*e9a5e479SAndreas Jaekel return zev_add_queue(fd, optarg); 884*e9a5e479SAndreas Jaekel case 'r': 885*e9a5e479SAndreas Jaekel return zev_remove_queue(fd, optarg); 886*e9a5e479SAndreas Jaekel case 'b': 887*e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 888*e9a5e479SAndreas Jaekel case 'B': 889*e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 890*e9a5e479SAndreas Jaekel case 'P': 891*e9a5e479SAndreas Jaekel return zev_queue_properties(fd, optarg); 8922bb8e5e2SAndreas Jaekel case 'h': 8932bb8e5e2SAndreas Jaekel case '?': 8942bb8e5e2SAndreas Jaekel default: 8952bb8e5e2SAndreas Jaekel usage(argv[0]); 8962bb8e5e2SAndreas Jaekel } 8972bb8e5e2SAndreas Jaekel } 8982bb8e5e2SAndreas Jaekel usage(argv[0]); 8992bb8e5e2SAndreas Jaekel close(fd); 900*e9a5e479SAndreas Jaekel return EXIT_FAILURE; 9012bb8e5e2SAndreas Jaekel } 9022bb8e5e2SAndreas Jaekel 903