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) 16e9a5e479SAndreas Jaekel #define OP_DEBUG_INFO (1 << 5) 172bb8e5e2SAndreas Jaekel 18e9a5e479SAndreas 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*5e286361SAndreas Jaekel static int verbose = 0; 46*5e286361SAndreas Jaekel 47e9a5e479SAndreas Jaekel static int 482bb8e5e2SAndreas Jaekel zev_statistics(int fd) 492bb8e5e2SAndreas Jaekel { 502bb8e5e2SAndreas Jaekel zev_statistics_t zs; 51e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 522bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 53e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 542bb8e5e2SAndreas Jaekel } 552bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 562bb8e5e2SAndreas Jaekel 572bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 582bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 592bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 602bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 612bb8e5e2SAndreas Jaekel 62e9a5e479SAndreas Jaekel printf(" discarded events : %lu\n", 63e9a5e479SAndreas Jaekel zs.zev_cnt_discarded_events); 64e9a5e479SAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 65e9a5e479SAndreas Jaekel 662bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 672bb8e5e2SAndreas Jaekel 682bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 692bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 702bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 712bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 722bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 732bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 742bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 752bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 762bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 772bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 782bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 792bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 802bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 812bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 822bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 832bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 842bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 85e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 862bb8e5e2SAndreas Jaekel } 872bb8e5e2SAndreas Jaekel 882bb8e5e2SAndreas Jaekel static void 8963aba447SAndreas Jaekel zev_print_error(char *buf) 9063aba447SAndreas Jaekel { 9163aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 9263aba447SAndreas Jaekel time_t op_time = rec->op_time; 9363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 9463aba447SAndreas Jaekel 9563aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 9663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 9763aba447SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 9863aba447SAndreas Jaekel } 9963aba447SAndreas Jaekel 10063aba447SAndreas Jaekel static void 10101c2c787SAndreas Jaekel zev_print_mark(char *buf) 10201c2c787SAndreas Jaekel { 10301c2c787SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 10401c2c787SAndreas Jaekel time_t op_time = rec->op_time; 10501c2c787SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 10601c2c787SAndreas Jaekel 10701c2c787SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 10801c2c787SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id, 10901c2c787SAndreas Jaekel rec->payload_len); 11001c2c787SAndreas Jaekel } 11101c2c787SAndreas Jaekel 11201c2c787SAndreas Jaekel static void 11363aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 11463aba447SAndreas Jaekel { 11563aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 11663aba447SAndreas Jaekel time_t op_time = rec->op_time; 11763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 11863aba447SAndreas Jaekel 11963aba447SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 12063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 12163aba447SAndreas Jaekel rec->guid, 12263aba447SAndreas Jaekel rec->remount ? "true" : "false", 12363aba447SAndreas Jaekel ZEV_DATASET(rec), 12463aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 12563aba447SAndreas Jaekel } 12663aba447SAndreas Jaekel 12763aba447SAndreas Jaekel static void 12863aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 12963aba447SAndreas Jaekel { 13063aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 13163aba447SAndreas Jaekel time_t op_time = rec->op_time; 13263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 13363aba447SAndreas Jaekel 13463aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 13563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 13663aba447SAndreas Jaekel rec->guid); 13763aba447SAndreas Jaekel } 13863aba447SAndreas Jaekel 13963aba447SAndreas Jaekel static void 14063aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 14163aba447SAndreas Jaekel { 14263aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 14363aba447SAndreas Jaekel time_t op_time = rec->op_time; 14463aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 14563aba447SAndreas Jaekel 14663aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 14763aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 14863aba447SAndreas Jaekel rec->guid, 14963aba447SAndreas Jaekel rec->offset, 15063aba447SAndreas Jaekel rec->length); 15163aba447SAndreas Jaekel } 15263aba447SAndreas Jaekel 15363aba447SAndreas Jaekel static void 15463aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 15563aba447SAndreas Jaekel { 15663aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 15763aba447SAndreas Jaekel } 15863aba447SAndreas Jaekel 15963aba447SAndreas Jaekel static void 16063aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 16163aba447SAndreas Jaekel { 16263aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 16363aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 16463aba447SAndreas Jaekel time_t op_time = rec->op_time; 16563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 16663aba447SAndreas Jaekel 16763aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 16863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 16963aba447SAndreas Jaekel rec->guid, 17063aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 17163aba447SAndreas Jaekel } 17263aba447SAndreas Jaekel 17363aba447SAndreas Jaekel static void 17463aba447SAndreas Jaekel zev_print_znode_create(char *buf) 17563aba447SAndreas Jaekel { 17663aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 17763aba447SAndreas Jaekel time_t op_time = rec->op_time; 17863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 17963aba447SAndreas Jaekel 180c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 181c035b1e8SAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 18263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 18363aba447SAndreas Jaekel rec->guid, 18463aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 18563aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 186c035b1e8SAndreas Jaekel rec->file.mtime, rec->parent.mtime, 18763aba447SAndreas Jaekel ZEV_NAME(rec)); 18863aba447SAndreas Jaekel } 18963aba447SAndreas Jaekel 19063aba447SAndreas Jaekel static void 19163aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 19263aba447SAndreas Jaekel { 19363aba447SAndreas Jaekel zev_print_znode_create(buf); 19463aba447SAndreas Jaekel } 19563aba447SAndreas Jaekel 19663aba447SAndreas Jaekel static void 19763aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 19863aba447SAndreas Jaekel { 19963aba447SAndreas Jaekel zev_print_znode_create(buf); 20063aba447SAndreas Jaekel } 20163aba447SAndreas Jaekel 20263aba447SAndreas Jaekel static void 20363aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 20463aba447SAndreas Jaekel { 20563aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 20663aba447SAndreas Jaekel time_t op_time = rec->op_time; 20763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 20863aba447SAndreas Jaekel 2096db5d4ecSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n", 21063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 21163aba447SAndreas Jaekel rec->guid, 21263aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 2136db5d4ecSAndreas Jaekel rec->file.mtime, 21463aba447SAndreas Jaekel ZEV_NAME(rec)); 21563aba447SAndreas Jaekel } 21663aba447SAndreas Jaekel 21763aba447SAndreas Jaekel static void 21863aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 21963aba447SAndreas Jaekel { 22063aba447SAndreas Jaekel zev_print_znode_remove(buf); 22163aba447SAndreas Jaekel } 22263aba447SAndreas Jaekel 22363aba447SAndreas Jaekel static void 22463aba447SAndreas Jaekel zev_print_znode_link(char *buf) 22563aba447SAndreas Jaekel { 22663aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 22763aba447SAndreas Jaekel time_t op_time = rec->op_time; 22863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 22963aba447SAndreas Jaekel 23003101f54SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 23103101f54SAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 23263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 23363aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 23463aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 23503101f54SAndreas Jaekel rec->file.ctime, rec->parent.ctime, 23663aba447SAndreas Jaekel ZEV_NAME(rec)); 23763aba447SAndreas Jaekel printf("links: %d\n", rec->file.links); 23863aba447SAndreas Jaekel } 23963aba447SAndreas Jaekel 24063aba447SAndreas Jaekel static void 24163aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 24263aba447SAndreas Jaekel { 24363aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 24463aba447SAndreas Jaekel time_t op_time = rec->op_time; 24563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 24663aba447SAndreas Jaekel 24763aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 24863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 24963aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 25063aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 25163aba447SAndreas Jaekel ZEV_NAME(rec), 25263aba447SAndreas Jaekel ZEV_LINK(rec)); 25363aba447SAndreas Jaekel } 25463aba447SAndreas Jaekel 25563aba447SAndreas Jaekel static void 25663aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 25763aba447SAndreas Jaekel { 25863aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 25963aba447SAndreas Jaekel time_t op_time = rec->op_time; 26063aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 26163aba447SAndreas Jaekel 26263aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 263c035b1e8SAndreas Jaekel "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 264c035b1e8SAndreas Jaekel "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 26563aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 26663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 26763aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 26863aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 26963aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 270c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 271c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 272c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 27363aba447SAndreas Jaekel ZEV_SRCNAME(rec), 27463aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 27563aba447SAndreas Jaekel } 27663aba447SAndreas Jaekel 27763aba447SAndreas Jaekel static void 278*5e286361SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 279*5e286361SAndreas Jaekel { 280*5e286361SAndreas Jaekel int i; 281*5e286361SAndreas Jaekel 282*5e286361SAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 283*5e286361SAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 284*5e286361SAndreas Jaekel } 285*5e286361SAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 286*5e286361SAndreas Jaekel } 287*5e286361SAndreas Jaekel 288*5e286361SAndreas Jaekel static void 28963aba447SAndreas Jaekel zev_print_znode_write(char *buf) 29063aba447SAndreas Jaekel { 29163aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 29263aba447SAndreas Jaekel time_t op_time = rec->op_time; 29363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 294*5e286361SAndreas Jaekel zev_sig_t *sig; 295*5e286361SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 296*5e286361SAndreas Jaekel int i; 29763aba447SAndreas Jaekel 29863aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 29963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 30063aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 30163aba447SAndreas Jaekel rec->offset, rec->length); 302*5e286361SAndreas Jaekel if (verbose) { 303*5e286361SAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 304*5e286361SAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 305*5e286361SAndreas Jaekel sig += i; 306*5e286361SAndreas Jaekel sig2hex_direct(sig->value, sigval); 307*5e286361SAndreas Jaekel printf(" sig: level %d, offset %llu, value %s\n", 308*5e286361SAndreas Jaekel sig->level, sig->block_offset, sigval); 309*5e286361SAndreas Jaekel } 310*5e286361SAndreas Jaekel } 31163aba447SAndreas Jaekel } 31263aba447SAndreas Jaekel 31363aba447SAndreas Jaekel static void 31463aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 31563aba447SAndreas Jaekel { 31663aba447SAndreas Jaekel zev_print_znode_write(buf); 31763aba447SAndreas Jaekel } 31863aba447SAndreas Jaekel 31963aba447SAndreas Jaekel static void 32063aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 32163aba447SAndreas Jaekel { 32263aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 32363aba447SAndreas Jaekel time_t op_time = rec->op_time; 32463aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 32563aba447SAndreas Jaekel 326c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 32763aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 328c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 32963aba447SAndreas Jaekel } 33063aba447SAndreas Jaekel 33163aba447SAndreas Jaekel static void 33263aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 33363aba447SAndreas Jaekel { 33463aba447SAndreas Jaekel zev_print_znode_setattr(buf); 33563aba447SAndreas Jaekel } 33663aba447SAndreas Jaekel 33763aba447SAndreas Jaekel static void 3389193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 3399193e9c2SAndreas Jaekel { 34063aba447SAndreas Jaekel int record_len; 34163aba447SAndreas Jaekel int op; 3429193e9c2SAndreas Jaekel 34363aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 34463aba447SAndreas Jaekel if (record_len != len) { 34563aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 34663aba447SAndreas Jaekel record_len, len); 3479193e9c2SAndreas Jaekel exit(1); 3489193e9c2SAndreas Jaekel } 34963aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 3509193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 35163aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3529193e9c2SAndreas Jaekel exit(1); 3539193e9c2SAndreas Jaekel } 35463aba447SAndreas Jaekel switch (op) { 35563aba447SAndreas Jaekel case ZEV_OP_ERROR: 35663aba447SAndreas Jaekel zev_print_error(buf); 3579193e9c2SAndreas Jaekel break; 35801c2c787SAndreas Jaekel case ZEV_OP_MARK: 35901c2c787SAndreas Jaekel zev_print_mark(buf); 36001c2c787SAndreas Jaekel break; 36163aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 36263aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3639193e9c2SAndreas Jaekel break; 36463aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 36563aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3669193e9c2SAndreas Jaekel break; 36763aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 36863aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3699193e9c2SAndreas Jaekel break; 37063aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 37163aba447SAndreas Jaekel zev_print_zvol_write(buf); 37263aba447SAndreas Jaekel break; 37363aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 37463aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 37563aba447SAndreas Jaekel break; 37663aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 37763aba447SAndreas Jaekel zev_print_znode_create(buf); 37863aba447SAndreas Jaekel break; 37963aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 38063aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 38163aba447SAndreas Jaekel break; 38263aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 38363aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 38463aba447SAndreas Jaekel break; 38563aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 38663aba447SAndreas Jaekel zev_print_znode_remove(buf); 38763aba447SAndreas Jaekel break; 38863aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 38963aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 39063aba447SAndreas Jaekel break; 39163aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 39263aba447SAndreas Jaekel zev_print_znode_link(buf); 39363aba447SAndreas Jaekel break; 39463aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 39563aba447SAndreas Jaekel zev_print_znode_symlink(buf); 39663aba447SAndreas Jaekel break; 39763aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 39863aba447SAndreas Jaekel zev_print_znode_rename(buf); 39963aba447SAndreas Jaekel break; 40063aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 40163aba447SAndreas Jaekel zev_print_znode_write(buf); 40263aba447SAndreas Jaekel break; 40363aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 40463aba447SAndreas Jaekel zev_print_znode_truncate(buf); 40563aba447SAndreas Jaekel break; 40663aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 40763aba447SAndreas Jaekel zev_print_znode_setattr(buf); 40863aba447SAndreas Jaekel break; 40963aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 41063aba447SAndreas Jaekel zev_print_znode_acl(buf); 4119193e9c2SAndreas Jaekel break; 4129193e9c2SAndreas Jaekel default: 41363aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 4149193e9c2SAndreas Jaekel exit(1); 4159193e9c2SAndreas Jaekel } 4169193e9c2SAndreas Jaekel } 4179193e9c2SAndreas Jaekel 418e9a5e479SAndreas Jaekel static int 4194ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 4202bb8e5e2SAndreas Jaekel { 4212bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 4222bb8e5e2SAndreas Jaekel int ret; 4239193e9c2SAndreas Jaekel char buf[4096]; 42468a46c64SAndreas Jaekel zev_event_t *ev; 42568a46c64SAndreas Jaekel int off = 0; 426e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 427e9a5e479SAndreas Jaekel int q_fd; 428e9a5e479SAndreas Jaekel 4294ca7dd5eSAndreas Jaekel if (create_tmp_queue) { 430e9a5e479SAndreas Jaekel aq.zev_max_queue_len = 0; 431e9a5e479SAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 432e9a5e479SAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 433e9a5e479SAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 434e9a5e479SAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 435e9a5e479SAndreas Jaekel 436e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 437e9a5e479SAndreas Jaekel perror("adding temporary queue failed"); 438e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 439e9a5e479SAndreas Jaekel } 440e9a5e479SAndreas Jaekel 4414ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 4424ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 443e9a5e479SAndreas Jaekel q_fd = open(buf, O_RDONLY); 444e9a5e479SAndreas Jaekel if (q_fd < 0) { 445e9a5e479SAndreas Jaekel perror("opening queue device failed"); 446e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 447e9a5e479SAndreas Jaekel } 4484ca7dd5eSAndreas Jaekel } else { 4494ca7dd5eSAndreas Jaekel q_fd = fd; 4504ca7dd5eSAndreas Jaekel } 451e9a5e479SAndreas Jaekel 4522bb8e5e2SAndreas Jaekel while (1) { 453e9a5e479SAndreas Jaekel pfd[0].fd = q_fd; 4542bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 4552bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 4562bb8e5e2SAndreas Jaekel if (ret < 0) { 4572bb8e5e2SAndreas Jaekel perror("poll failed"); 4584ca7dd5eSAndreas Jaekel close(q_fd); 459e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 4602bb8e5e2SAndreas Jaekel } 4612bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 4622bb8e5e2SAndreas Jaekel continue; 4632bb8e5e2SAndreas Jaekel /* data available */ 464e9a5e479SAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 4652bb8e5e2SAndreas Jaekel if (ret < 0) { 4662bb8e5e2SAndreas Jaekel perror("read failed"); 4674ca7dd5eSAndreas Jaekel close(q_fd); 468e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 4692bb8e5e2SAndreas Jaekel } 4702bb8e5e2SAndreas Jaekel if (ret == 0) 4712bb8e5e2SAndreas Jaekel continue; 47268a46c64SAndreas Jaekel while (ret > off) { 47368a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 47468a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 47568a46c64SAndreas Jaekel off += ev->header.record_len; 47668a46c64SAndreas Jaekel } 477108668daSAndreas Jaekel off = 0; 4782bb8e5e2SAndreas Jaekel } 4794ca7dd5eSAndreas Jaekel if (create_tmp_queue) 480e9a5e479SAndreas Jaekel close(q_fd); 481e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 4822bb8e5e2SAndreas Jaekel } 4832bb8e5e2SAndreas Jaekel 4842bb8e5e2SAndreas Jaekel static void 4852bb8e5e2SAndreas Jaekel usage(char *progname) 4862bb8e5e2SAndreas Jaekel { 487e9a5e479SAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 488e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 489e9a5e479SAndreas Jaekel fprintf(stderr, " Status information:\n"); 4902bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 4912bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 492e9a5e479SAndreas Jaekel fprintf(stderr, " -D print zev module debug " 493e9a5e479SAndreas Jaekel "information\n"); 494e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 495e9a5e479SAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 496e9a5e479SAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 497e9a5e479SAndreas Jaekel "length\n"); 498e9a5e479SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 499e9a5e479SAndreas Jaekel "this pool\n"); 5002bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 501e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 502e9a5e479SAndreas Jaekel fprintf(stderr, " Queue management:\n"); 503e9a5e479SAndreas Jaekel fprintf(stderr, " -l list queues\n"); 5044ca7dd5eSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 5054ca7dd5eSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 506e9a5e479SAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 507e9a5e479SAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 508e9a5e479SAndreas Jaekel "(default)\n"); 509e9a5e479SAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 510e9a5e479SAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 5114ca7dd5eSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 512e9a5e479SAndreas Jaekel "length\n"); 513e9a5e479SAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 514e9a5e479SAndreas Jaekel "throttle\n"); 515e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 516e9a5e479SAndreas Jaekel fprintf(stderr, " Other options:\n"); 517e9a5e479SAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 518e9a5e479SAndreas Jaekel "('%s')\n", ZEV_DEVICE); 5194ca7dd5eSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 5204ca7dd5eSAndreas Jaekel "queue name\n"); 52101c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 522*5e286361SAndreas Jaekel fprintf(stderr, " -v verbose: addition output " 523*5e286361SAndreas Jaekel "for some operations\n"); 5242bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 5252bb8e5e2SAndreas Jaekel } 5262bb8e5e2SAndreas Jaekel 5272bb8e5e2SAndreas Jaekel static int 5284ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 5292bb8e5e2SAndreas Jaekel { 530e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 531e9a5e479SAndreas Jaekel int namelen; 5322bb8e5e2SAndreas Jaekel 533e9a5e479SAndreas Jaekel namelen = strlen(arg); 534e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 535e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 5362bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5372bb8e5e2SAndreas Jaekel } 538e9a5e479SAndreas Jaekel 539e9a5e479SAndreas Jaekel aq.zev_namelen = namelen; 540e9a5e479SAndreas Jaekel strcpy(aq.zev_name, arg); 5414ca7dd5eSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 5424ca7dd5eSAndreas Jaekel if (blocking) { 5434ca7dd5eSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 5444ca7dd5eSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 5454ca7dd5eSAndreas Jaekel } else { 546e9a5e479SAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 5474ca7dd5eSAndreas Jaekel } 548e9a5e479SAndreas Jaekel 549e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 550e9a5e479SAndreas Jaekel perror("adding queue failed"); 5512bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 5522bb8e5e2SAndreas Jaekel } 5532bb8e5e2SAndreas Jaekel return (0); 5542bb8e5e2SAndreas Jaekel } 5552bb8e5e2SAndreas Jaekel 5562bb8e5e2SAndreas Jaekel static int 557e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg) 558205a9bc9SAndreas Jaekel { 559e9a5e479SAndreas Jaekel zev_ioctl_remove_queue_t aq; 560e9a5e479SAndreas Jaekel int namelen; 561205a9bc9SAndreas Jaekel 562e9a5e479SAndreas Jaekel namelen = strlen(arg); 563e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 564e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 565205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 566205a9bc9SAndreas Jaekel } 567e9a5e479SAndreas Jaekel 5684ca7dd5eSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 5694ca7dd5eSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 570e9a5e479SAndreas Jaekel 571e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 572e9a5e479SAndreas Jaekel perror("removing queue failed"); 573e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 574e9a5e479SAndreas Jaekel } 575e9a5e479SAndreas Jaekel return (0); 576e9a5e479SAndreas Jaekel } 577e9a5e479SAndreas Jaekel 578e9a5e479SAndreas Jaekel static int 579e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 580e9a5e479SAndreas Jaekel { 581e9a5e479SAndreas Jaekel uint64_t maxqueuelen; 582e9a5e479SAndreas Jaekel 583e9a5e479SAndreas Jaekel errno = 0; 584e9a5e479SAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 585e9a5e479SAndreas Jaekel if (errno) { 586e9a5e479SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 587e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 588e9a5e479SAndreas Jaekel } 589e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 590e9a5e479SAndreas Jaekel perror("setting max queue length failed"); 591205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 592205a9bc9SAndreas Jaekel } 593205a9bc9SAndreas Jaekel return (0); 594205a9bc9SAndreas Jaekel } 595205a9bc9SAndreas Jaekel 596205a9bc9SAndreas Jaekel static int 5972bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 5982bb8e5e2SAndreas Jaekel { 5992bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 6002bb8e5e2SAndreas Jaekel int len; 6012bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 6022bb8e5e2SAndreas Jaekel len = strlen(poolname); 6032bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 6042bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 6052bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 6062bb8e5e2SAndreas Jaekel } 6072bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 6082bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 6092bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 6102bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 6112bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 6122bb8e5e2SAndreas Jaekel } 6132bb8e5e2SAndreas Jaekel return (0); 6142bb8e5e2SAndreas Jaekel } 6152bb8e5e2SAndreas Jaekel 6162bb8e5e2SAndreas Jaekel int 6172bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 6182bb8e5e2SAndreas Jaekel { 6192bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 6202bb8e5e2SAndreas Jaekel } 6212bb8e5e2SAndreas Jaekel 6222bb8e5e2SAndreas Jaekel int 6232bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 6242bb8e5e2SAndreas Jaekel { 6252bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 6262bb8e5e2SAndreas Jaekel } 6272bb8e5e2SAndreas Jaekel 62801c2c787SAndreas Jaekel static int 629e9a5e479SAndreas Jaekel zev_debug_info(int fd) 630e9a5e479SAndreas Jaekel { 631e9a5e479SAndreas Jaekel zev_ioctl_debug_info_t di; 632e9a5e479SAndreas Jaekel 633e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 634e9a5e479SAndreas Jaekel perror("getting zev debug info failed"); 635e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 636e9a5e479SAndreas Jaekel } 637e9a5e479SAndreas Jaekel 638e9a5e479SAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 639*5e286361SAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 640*5e286361SAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 641*5e286361SAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 642e9a5e479SAndreas Jaekel return 0; 643e9a5e479SAndreas Jaekel } 644e9a5e479SAndreas Jaekel 645e9a5e479SAndreas Jaekel static int 64601c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 64701c2c787SAndreas Jaekel { 64801c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 64901c2c787SAndreas Jaekel uint64_t guid; 65001c2c787SAndreas Jaekel int len; 65101c2c787SAndreas Jaekel char *p; 65201c2c787SAndreas Jaekel 65301c2c787SAndreas Jaekel p = strchr(arg, ':'); 65401c2c787SAndreas Jaekel if (!p) { 65501c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 65601c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 65701c2c787SAndreas Jaekel exit (EXIT_FAILURE); 65801c2c787SAndreas Jaekel } 65901c2c787SAndreas Jaekel *p = '\n'; 66001c2c787SAndreas Jaekel p++; 66101c2c787SAndreas Jaekel 66201c2c787SAndreas Jaekel errno = 0; 663e9a5e479SAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 66401c2c787SAndreas Jaekel if (errno) { 66501c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 66601c2c787SAndreas Jaekel exit (EXIT_FAILURE); 66701c2c787SAndreas Jaekel } 66801c2c787SAndreas Jaekel 66901c2c787SAndreas Jaekel len = strlen(p); 67001c2c787SAndreas Jaekel 67101c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 67201c2c787SAndreas Jaekel if (!mark) { 67301c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 67401c2c787SAndreas Jaekel strerror(errno)); 67501c2c787SAndreas Jaekel exit (EXIT_FAILURE); 67601c2c787SAndreas Jaekel } 67701c2c787SAndreas Jaekel mark->zev_guid = guid; 67801c2c787SAndreas Jaekel mark->zev_mark_id = 0; 67901c2c787SAndreas Jaekel mark->zev_payload_len = len; 68001c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 68101c2c787SAndreas Jaekel 68201c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 68301c2c787SAndreas Jaekel perror("queueing mark failed"); 68401c2c787SAndreas Jaekel return (EXIT_FAILURE); 68501c2c787SAndreas Jaekel } 68601c2c787SAndreas Jaekel 68701c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 68801c2c787SAndreas Jaekel return (0); 68901c2c787SAndreas Jaekel } 69001c2c787SAndreas Jaekel 691e9a5e479SAndreas Jaekel static int 692e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 693e9a5e479SAndreas Jaekel { 694e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 695e9a5e479SAndreas Jaekel 6964ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 6974ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 698e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 699e9a5e479SAndreas Jaekel return EXIT_FAILURE; 700e9a5e479SAndreas Jaekel } 7014ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 702e9a5e479SAndreas Jaekel 703e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 704e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 705e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 706e9a5e479SAndreas Jaekel } 707e9a5e479SAndreas Jaekel if (block) { 708e9a5e479SAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 709e9a5e479SAndreas Jaekel } else { 710e9a5e479SAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 711e9a5e479SAndreas Jaekel } 712e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 713e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 714e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 715e9a5e479SAndreas Jaekel } 716e9a5e479SAndreas Jaekel return (0); 717e9a5e479SAndreas Jaekel } 718e9a5e479SAndreas Jaekel 719e9a5e479SAndreas Jaekel static int 720e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 721e9a5e479SAndreas Jaekel { 722e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 723e9a5e479SAndreas Jaekel 724e9a5e479SAndreas Jaekel if (!len) { 725e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 726e9a5e479SAndreas Jaekel return EXIT_FAILURE; 727e9a5e479SAndreas Jaekel } 728e9a5e479SAndreas Jaekel 7294ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 7304ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 731e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 732e9a5e479SAndreas Jaekel return EXIT_FAILURE; 733e9a5e479SAndreas Jaekel } 7344ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 735e9a5e479SAndreas Jaekel 736e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 737e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 738e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 739e9a5e479SAndreas Jaekel } 740e9a5e479SAndreas Jaekel gqp.zev_max_queue_len = atol(len); 741e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 742e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 743e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 744e9a5e479SAndreas Jaekel } 745e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 746e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 747e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 748e9a5e479SAndreas Jaekel } 749e9a5e479SAndreas Jaekel 750e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 751e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 752e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 753e9a5e479SAndreas Jaekel } 754e9a5e479SAndreas Jaekel return (0); 755e9a5e479SAndreas Jaekel } 756e9a5e479SAndreas Jaekel 757e9a5e479SAndreas Jaekel static int 758e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 759e9a5e479SAndreas Jaekel { 760e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 761e9a5e479SAndreas Jaekel 762e9a5e479SAndreas Jaekel if (!len) { 763e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 764e9a5e479SAndreas Jaekel return EXIT_FAILURE; 765e9a5e479SAndreas Jaekel } 766e9a5e479SAndreas Jaekel 7674ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 7684ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 769e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 770e9a5e479SAndreas Jaekel return EXIT_FAILURE; 771e9a5e479SAndreas Jaekel } 7724ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 773e9a5e479SAndreas Jaekel 774e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 775e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 776e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 777e9a5e479SAndreas Jaekel } 778e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 779e9a5e479SAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 780e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 781e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 782e9a5e479SAndreas Jaekel } 7834ca7dd5eSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 784e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 785e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 786e9a5e479SAndreas Jaekel } 787e9a5e479SAndreas Jaekel 788e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 789e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 790e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 791e9a5e479SAndreas Jaekel } 792e9a5e479SAndreas Jaekel return (0); 793e9a5e479SAndreas Jaekel } 794e9a5e479SAndreas Jaekel 795e9a5e479SAndreas Jaekel static int 796e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg) 797e9a5e479SAndreas Jaekel { 798e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 799e9a5e479SAndreas Jaekel 8004ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 8014ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 802e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 803e9a5e479SAndreas Jaekel return EXIT_FAILURE; 804e9a5e479SAndreas Jaekel } 8054ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 806e9a5e479SAndreas Jaekel 807e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 808e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 809e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 810e9a5e479SAndreas Jaekel } 811e9a5e479SAndreas Jaekel 812e9a5e479SAndreas Jaekel printf("queue : %s\n", arg); 813e9a5e479SAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 814e9a5e479SAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 815e9a5e479SAndreas Jaekel printf("persistent : %s\n", 816e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 817e9a5e479SAndreas Jaekel printf("blocking : %s\n", 818e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 819e9a5e479SAndreas Jaekel 820e9a5e479SAndreas Jaekel return (0); 821e9a5e479SAndreas Jaekel } 822e9a5e479SAndreas Jaekel 823e9a5e479SAndreas Jaekel static int 824e9a5e479SAndreas Jaekel zev_list_queues(int fd) 825e9a5e479SAndreas Jaekel { 826e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 827e9a5e479SAndreas Jaekel zev_ioctl_get_queue_list_t gql; 828e9a5e479SAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 829e9a5e479SAndreas Jaekel uint64_t i; 830e9a5e479SAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 831e9a5e479SAndreas Jaekel 832e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 833e9a5e479SAndreas Jaekel perror("getting queue list failed"); 834e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 835e9a5e479SAndreas Jaekel } 836e9a5e479SAndreas Jaekel 837e9a5e479SAndreas Jaekel printf("Name Size " 838e9a5e479SAndreas Jaekel "Max Size Wakeup Per Block\n"); 839e9a5e479SAndreas Jaekel 840e9a5e479SAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 841e9a5e479SAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 842e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 843e9a5e479SAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 844e9a5e479SAndreas Jaekel 8454ca7dd5eSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 8464ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 8474ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 8484ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 849e9a5e479SAndreas Jaekel 850e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 851e9a5e479SAndreas Jaekel if (errno == ENOENT) 852e9a5e479SAndreas Jaekel continue; 853e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 854e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 855e9a5e479SAndreas Jaekel } 856e9a5e479SAndreas Jaekel 8574ca7dd5eSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 8584ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 8594ca7dd5eSAndreas Jaekel gs.zev_queue_name.zev_namelen = 8604ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 861e9a5e479SAndreas Jaekel 862e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 863e9a5e479SAndreas Jaekel if (errno == ENOENT) 864e9a5e479SAndreas Jaekel continue; 865e9a5e479SAndreas Jaekel perror("getting statistics data failed"); 866e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 867e9a5e479SAndreas Jaekel } 868e9a5e479SAndreas Jaekel 869e9a5e479SAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 870e9a5e479SAndreas Jaekel " %-3s %-3s\n", 871e9a5e479SAndreas Jaekel name, 872e9a5e479SAndreas Jaekel gs.zev_statistics.zev_queue_len, 873e9a5e479SAndreas Jaekel gqp.zev_max_queue_len, 874e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold, 875e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 876e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 877e9a5e479SAndreas Jaekel "yes" : "no"); 878e9a5e479SAndreas Jaekel } 879e9a5e479SAndreas Jaekel 880e9a5e479SAndreas Jaekel return (0); 881e9a5e479SAndreas Jaekel } 882e9a5e479SAndreas Jaekel 8832bb8e5e2SAndreas Jaekel int 8842bb8e5e2SAndreas Jaekel main(int argc, char **argv) 8852bb8e5e2SAndreas Jaekel { 8862bb8e5e2SAndreas Jaekel int fd; 8872bb8e5e2SAndreas Jaekel int c; 8882bb8e5e2SAndreas Jaekel extern char *optarg; 8894ca7dd5eSAndreas Jaekel int create_tmp_queue = 1; 8904ca7dd5eSAndreas Jaekel char buf[MAXPATHLEN]; 8912bb8e5e2SAndreas Jaekel 8922bb8e5e2SAndreas Jaekel /* open device */ 8932bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 8942bb8e5e2SAndreas Jaekel if (fd < 0) { 8952bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 8962bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 8972bb8e5e2SAndreas Jaekel } 8984ca7dd5eSAndreas Jaekel while ((c = getopt(argc, argv, 899*5e286361SAndreas Jaekel "vspd:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 9002bb8e5e2SAndreas Jaekel switch(c) { 901*5e286361SAndreas Jaekel case 'v': 902*5e286361SAndreas Jaekel verbose++; 903*5e286361SAndreas Jaekel break; 9042bb8e5e2SAndreas Jaekel case 's': 905e9a5e479SAndreas Jaekel return zev_statistics(fd); 9062bb8e5e2SAndreas Jaekel case 'p': 9074ca7dd5eSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 908e9a5e479SAndreas Jaekel case 'D': 909e9a5e479SAndreas Jaekel return zev_debug_info(fd); 9102bb8e5e2SAndreas Jaekel case 'd': 911e9a5e479SAndreas Jaekel close(fd); 9122bb8e5e2SAndreas Jaekel zev_device = optarg; 913e9a5e479SAndreas Jaekel fd = open(zev_device, O_RDONLY); 914e9a5e479SAndreas Jaekel if (fd < 0) { 915e9a5e479SAndreas Jaekel perror("opening zev device failed"); 916e9a5e479SAndreas Jaekel return EXIT_FAILURE; 917e9a5e479SAndreas Jaekel } 9184ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 9194ca7dd5eSAndreas Jaekel break; 9204ca7dd5eSAndreas Jaekel case 'q': 9214ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 9224ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 9234ca7dd5eSAndreas Jaekel close(fd); 9244ca7dd5eSAndreas Jaekel zev_device = buf; 9254ca7dd5eSAndreas Jaekel fd = open(zev_device, O_RDONLY); 9264ca7dd5eSAndreas Jaekel if (fd < 0) { 9274ca7dd5eSAndreas Jaekel perror("opening zev device failed"); 9284ca7dd5eSAndreas Jaekel return EXIT_FAILURE; 9294ca7dd5eSAndreas Jaekel } 9304ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 9312bb8e5e2SAndreas Jaekel break; 932e9a5e479SAndreas Jaekel case 'l': 933e9a5e479SAndreas Jaekel return zev_list_queues(fd); 934e9a5e479SAndreas Jaekel case 'Q': 935e9a5e479SAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 9364ca7dd5eSAndreas Jaekel case 'L': 937e9a5e479SAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 938205a9bc9SAndreas Jaekel case 't': 939e9a5e479SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 940e9a5e479SAndreas Jaekel argv[optind]); 9412bb8e5e2SAndreas Jaekel case 'm': 9422bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 9432bb8e5e2SAndreas Jaekel case 'M': 9442bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 94501c2c787SAndreas Jaekel case 'k': 94601c2c787SAndreas Jaekel return zev_mark(fd, optarg); 947e9a5e479SAndreas Jaekel case 'a': 9484ca7dd5eSAndreas Jaekel return zev_add_queue(fd, optarg, 0); 9494ca7dd5eSAndreas Jaekel case 'A': 9504ca7dd5eSAndreas Jaekel return zev_add_queue(fd, optarg, 1); 951e9a5e479SAndreas Jaekel case 'r': 952e9a5e479SAndreas Jaekel return zev_remove_queue(fd, optarg); 953e9a5e479SAndreas Jaekel case 'b': 954e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 955e9a5e479SAndreas Jaekel case 'B': 956e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 957e9a5e479SAndreas Jaekel case 'P': 958e9a5e479SAndreas Jaekel return zev_queue_properties(fd, optarg); 9592bb8e5e2SAndreas Jaekel case 'h': 9602bb8e5e2SAndreas Jaekel case '?': 9612bb8e5e2SAndreas Jaekel default: 9622bb8e5e2SAndreas Jaekel usage(argv[0]); 9632bb8e5e2SAndreas Jaekel } 9642bb8e5e2SAndreas Jaekel } 9652bb8e5e2SAndreas Jaekel usage(argv[0]); 9662bb8e5e2SAndreas Jaekel close(fd); 967e9a5e479SAndreas Jaekel return EXIT_FAILURE; 9682bb8e5e2SAndreas Jaekel } 9692bb8e5e2SAndreas Jaekel 970