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> 10b9710123SAndreas Jaekel #include <sys/sysmacros.h> 11d65b2fffSAndreas Jaekel #include <stdarg.h> 120abdde4aSAndreas Jaekel #include <sys/avl.h> 132bb8e5e2SAndreas Jaekel 14e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 152bb8e5e2SAndreas Jaekel 160abdde4aSAndreas Jaekel #if !defined(offsetof) 170abdde4aSAndreas Jaekel #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) 180abdde4aSAndreas Jaekel #endif 190abdde4aSAndreas Jaekel 202bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 212bb8e5e2SAndreas Jaekel 229193e9c2SAndreas Jaekel static char *zev_op_name[] = { 23d65b2fffSAndreas Jaekel "ERROR", 24d65b2fffSAndreas Jaekel "MARK", 25d65b2fffSAndreas Jaekel "ZFS_MOUNT", 26d65b2fffSAndreas Jaekel "ZFS_UMOUNT", 27d65b2fffSAndreas Jaekel "ZVOL_WRITE", 28d65b2fffSAndreas Jaekel "ZVOL_TRUNCATE", 29d65b2fffSAndreas Jaekel "ZNODE_CLOSE_AFTER_UPDATE", 30d65b2fffSAndreas Jaekel "ZNODE_CREATE", 31d65b2fffSAndreas Jaekel "ZNODE_MKDIR", 32d65b2fffSAndreas Jaekel "ZNODE_MAKE_XATTR_DIR", 33d65b2fffSAndreas Jaekel "ZNODE_REMOVE", 34d65b2fffSAndreas Jaekel "ZNODE_RMDIR", 35d65b2fffSAndreas Jaekel "ZNODE_LINK", 36d65b2fffSAndreas Jaekel "ZNODE_SYMLINK", 37d65b2fffSAndreas Jaekel "ZNODE_RENAME", 38d65b2fffSAndreas Jaekel "ZNODE_WRITE", 39d65b2fffSAndreas Jaekel "ZNODE_TRUNCATE", 40d65b2fffSAndreas Jaekel "ZNODE_SETATTR", 41d65b2fffSAndreas Jaekel "ZNODE_ACL", 429193e9c2SAndreas Jaekel NULL 439193e9c2SAndreas Jaekel }; 449193e9c2SAndreas Jaekel 456a3d43bfSAndreas Jaekel #define MD_STATISTICS 1 466a3d43bfSAndreas Jaekel #define MD_POLL_EVENTS 2 476a3d43bfSAndreas Jaekel #define MD_CHECKSUMS 3 486a3d43bfSAndreas Jaekel #define MD_DEBUG_INFO 4 496a3d43bfSAndreas Jaekel #define MD_LIST_QUEUES 5 506a3d43bfSAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN 6 516a3d43bfSAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN 7 526a3d43bfSAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN 8 536a3d43bfSAndreas Jaekel #define MD_MUTE_POOL 9 546a3d43bfSAndreas Jaekel #define MD_UNMUTE_POOL 10 556a3d43bfSAndreas Jaekel #define MD_MARK 11 566a3d43bfSAndreas Jaekel #define MD_ADD_QUEUE 12 576a3d43bfSAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE 13 586a3d43bfSAndreas Jaekel #define MD_REMOVE_QUEUE 14 596a3d43bfSAndreas Jaekel #define MD_QUEUE_BLOCKING 15 606a3d43bfSAndreas Jaekel #define MD_QUEUE_NONBLOCKING 16 616a3d43bfSAndreas Jaekel #define MD_QUEUE_PROPERTIES 17 620abdde4aSAndreas Jaekel #define MD_ZEVSTAT 18 636a3d43bfSAndreas Jaekel 645e286361SAndreas Jaekel static int verbose = 0; 65d65b2fffSAndreas Jaekel static int grep_friendly = 0; 66d65b2fffSAndreas Jaekel 67d65b2fffSAndreas Jaekel static void 68d65b2fffSAndreas Jaekel zpf(char *fmt, ...) 69d65b2fffSAndreas Jaekel { 70d65b2fffSAndreas Jaekel va_list ap; 71d65b2fffSAndreas Jaekel 72d65b2fffSAndreas Jaekel va_start(ap, fmt); 73d65b2fffSAndreas Jaekel vprintf(fmt, ap); 74d65b2fffSAndreas Jaekel va_end(ap); 75d65b2fffSAndreas Jaekel if (grep_friendly) { 76d65b2fffSAndreas Jaekel printf(" "); 77d65b2fffSAndreas Jaekel } else { 78d65b2fffSAndreas Jaekel printf("\n"); 79d65b2fffSAndreas Jaekel } 80d65b2fffSAndreas Jaekel } 81d65b2fffSAndreas Jaekel 82d65b2fffSAndreas Jaekel static void 83d65b2fffSAndreas Jaekel znl(void) 84d65b2fffSAndreas Jaekel { 85d65b2fffSAndreas Jaekel if (grep_friendly) 86d65b2fffSAndreas Jaekel printf("\n"); 87d65b2fffSAndreas Jaekel } 885e286361SAndreas Jaekel 891ca5a13bSAndreas Jaekel static void 901ca5a13bSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 911ca5a13bSAndreas Jaekel { 921ca5a13bSAndreas Jaekel int i; 931ca5a13bSAndreas Jaekel 941ca5a13bSAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 951ca5a13bSAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 961ca5a13bSAndreas Jaekel } 971ca5a13bSAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 981ca5a13bSAndreas Jaekel } 991ca5a13bSAndreas Jaekel 100e9a5e479SAndreas Jaekel static int 1012bb8e5e2SAndreas Jaekel zev_statistics(int fd) 1022bb8e5e2SAndreas Jaekel { 1032bb8e5e2SAndreas Jaekel zev_statistics_t zs; 104e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 1052bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 106e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1072bb8e5e2SAndreas Jaekel } 1082bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 1092bb8e5e2SAndreas Jaekel 1102bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 1112bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 1122bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 1132bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 1142bb8e5e2SAndreas Jaekel 115e9a5e479SAndreas Jaekel printf(" discarded events : %lu\n", 116e9a5e479SAndreas Jaekel zs.zev_cnt_discarded_events); 117e9a5e479SAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 118e9a5e479SAndreas Jaekel 1192bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 1202bb8e5e2SAndreas Jaekel 1212bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 1222bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 1232bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 1242bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 1252bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 1262bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 1272bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 1282bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 1292bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 1302bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 1312bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 1322bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 1332bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 1342bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 1352bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 1362bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 1372bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 138e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 1392bb8e5e2SAndreas Jaekel } 1402bb8e5e2SAndreas Jaekel 1412bb8e5e2SAndreas Jaekel static void 142d65b2fffSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info) 143d65b2fffSAndreas Jaekel { 144d65b2fffSAndreas Jaekel zpf(" %s.inode: %llu", name, info->ino); 145d65b2fffSAndreas Jaekel zpf(" %s.gen: %llu", name, info->gen); 146d65b2fffSAndreas Jaekel zpf(" %s.mtime: %llu", name, info->mtime); 147d65b2fffSAndreas Jaekel zpf(" %s.ctime: %llu", name, info->ctime); 148d65b2fffSAndreas Jaekel zpf(" %s.size: %llu", name, info->size); 149d65b2fffSAndreas Jaekel zpf(" %s.mode: %llo", name, info->mode); 150d65b2fffSAndreas Jaekel zpf(" %s.links: %llu", name, info->links); 151d65b2fffSAndreas Jaekel zpf(" %s.type: %lu", name, info->type); 152d65b2fffSAndreas Jaekel zpf(" %s.flags: %lu", name, info->flags); 153d65b2fffSAndreas Jaekel } 154d65b2fffSAndreas Jaekel 155d65b2fffSAndreas Jaekel static void 156d65b2fffSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec) 157d65b2fffSAndreas Jaekel { 158d65b2fffSAndreas Jaekel int i; 159d65b2fffSAndreas Jaekel int j; 160d65b2fffSAndreas Jaekel uint8_t *p; 161d65b2fffSAndreas Jaekel char c; 162d65b2fffSAndreas Jaekel 163d65b2fffSAndreas Jaekel zpf(" payload:"); 164d65b2fffSAndreas Jaekel p = (uint8_t *)ZEV_PAYLOAD(rec); 165d65b2fffSAndreas Jaekel for (i=0; i<rec->payload_len; i+=16) { 166d65b2fffSAndreas Jaekel printf(" "); 167d65b2fffSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 168d65b2fffSAndreas Jaekel printf("%02x ", p[j]); 169d65b2fffSAndreas Jaekel if (j == i + 7) 170d65b2fffSAndreas Jaekel printf(" "); 171d65b2fffSAndreas Jaekel } 172d65b2fffSAndreas Jaekel if (grep_friendly) 173d65b2fffSAndreas Jaekel continue; 174d65b2fffSAndreas Jaekel for (; j<i+16; j++) { 175d65b2fffSAndreas Jaekel printf(" "); 176d65b2fffSAndreas Jaekel if (j == i + 7) 177d65b2fffSAndreas Jaekel printf(" "); 178d65b2fffSAndreas Jaekel } 179d65b2fffSAndreas Jaekel printf(" "); 180d65b2fffSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 181d65b2fffSAndreas Jaekel c = '.'; 182d65b2fffSAndreas Jaekel if (p[j] >= ' ' && p[j] <= '~') 183d65b2fffSAndreas Jaekel c = p[j]; 184d65b2fffSAndreas Jaekel printf("%c", c); 185d65b2fffSAndreas Jaekel if (j == i + 7) 186d65b2fffSAndreas Jaekel printf(" "); 187d65b2fffSAndreas Jaekel } 188d65b2fffSAndreas Jaekel printf("\n"); 189d65b2fffSAndreas Jaekel } 190d65b2fffSAndreas Jaekel } 191d65b2fffSAndreas Jaekel 192d65b2fffSAndreas Jaekel static void 19363aba447SAndreas Jaekel zev_print_error(char *buf) 19463aba447SAndreas Jaekel { 19563aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 19663aba447SAndreas Jaekel time_t op_time = rec->op_time; 19763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 19863aba447SAndreas Jaekel 199d65b2fffSAndreas Jaekel if (verbose) { 200d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 201d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 202d65b2fffSAndreas Jaekel zpf(" failed.op: %s", 203d65b2fffSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN]); 204d65b2fffSAndreas Jaekel zpf(" message: %s", ZEV_ERRSTR(rec)); 205d65b2fffSAndreas Jaekel znl(); 206d65b2fffSAndreas Jaekel } else { 20763aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 20863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 209d65b2fffSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], 210d65b2fffSAndreas Jaekel ZEV_ERRSTR(rec)); 211d65b2fffSAndreas Jaekel } 21263aba447SAndreas Jaekel } 21363aba447SAndreas Jaekel 21463aba447SAndreas Jaekel static void 21501c2c787SAndreas Jaekel zev_print_mark(char *buf) 21601c2c787SAndreas Jaekel { 21701c2c787SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 21801c2c787SAndreas Jaekel time_t op_time = rec->op_time; 21901c2c787SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 22001c2c787SAndreas Jaekel 221d65b2fffSAndreas Jaekel if (verbose) { 222d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 223d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 224d65b2fffSAndreas Jaekel zpf(" mark.id: %llu", rec->mark_id); 225d65b2fffSAndreas Jaekel zpf(" payload.len: %llu", rec->payload_len); 226d65b2fffSAndreas Jaekel if (rec->payload_len) 227d65b2fffSAndreas Jaekel zev_print_mark_payload(rec); 228d65b2fffSAndreas Jaekel znl(); 229d65b2fffSAndreas Jaekel } else { 23001c2c787SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 231d65b2fffSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 232d65b2fffSAndreas Jaekel rec->mark_id, rec->payload_len); 233d65b2fffSAndreas Jaekel } 23401c2c787SAndreas Jaekel } 23501c2c787SAndreas Jaekel 23601c2c787SAndreas Jaekel static void 23763aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 23863aba447SAndreas Jaekel { 23963aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 24063aba447SAndreas Jaekel time_t op_time = rec->op_time; 24163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 24263aba447SAndreas Jaekel 243d65b2fffSAndreas Jaekel if (verbose) { 244d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 245d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 246d65b2fffSAndreas Jaekel zpf(" dataset: %s", ZEV_DATASET(rec)); 247d65b2fffSAndreas Jaekel zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 248d65b2fffSAndreas Jaekel zpf(" remount: %s", rec->remount ? "true" : "false"); 249d65b2fffSAndreas Jaekel zev_print_inode_info("root", &rec->root); 250d65b2fffSAndreas Jaekel znl(); 251d65b2fffSAndreas Jaekel } else { 252d65b2fffSAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' " 253d65b2fffSAndreas Jaekel "mountpoint='%s'\n", 25463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 25563aba447SAndreas Jaekel rec->guid, 25663aba447SAndreas Jaekel rec->remount ? "true" : "false", 25763aba447SAndreas Jaekel ZEV_DATASET(rec), 25863aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 25963aba447SAndreas Jaekel } 260d65b2fffSAndreas Jaekel } 26163aba447SAndreas Jaekel 26263aba447SAndreas Jaekel static void 26363aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 26463aba447SAndreas Jaekel { 26563aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 26663aba447SAndreas Jaekel time_t op_time = rec->op_time; 26763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 26863aba447SAndreas Jaekel 269d65b2fffSAndreas Jaekel if (verbose) { 270d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 271d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 272d65b2fffSAndreas Jaekel znl(); 273d65b2fffSAndreas Jaekel } else { 27463aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 27563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 27663aba447SAndreas Jaekel rec->guid); 27763aba447SAndreas Jaekel } 278d65b2fffSAndreas Jaekel } 27963aba447SAndreas Jaekel 28063aba447SAndreas Jaekel static void 28163aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 28263aba447SAndreas Jaekel { 28363aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 28463aba447SAndreas Jaekel time_t op_time = rec->op_time; 28563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 28663aba447SAndreas Jaekel 287d65b2fffSAndreas Jaekel if (verbose) { 288d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 289d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 290e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 291d65b2fffSAndreas Jaekel zpf(" offset: %llu", rec->offset); 292d65b2fffSAndreas Jaekel zpf(" length: %llu", rec->length); 293d65b2fffSAndreas Jaekel znl(); 294d65b2fffSAndreas Jaekel } else { 29563aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 29663aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 29763aba447SAndreas Jaekel rec->guid, 29863aba447SAndreas Jaekel rec->offset, 29963aba447SAndreas Jaekel rec->length); 30063aba447SAndreas Jaekel } 301d65b2fffSAndreas Jaekel } 30263aba447SAndreas Jaekel 30363aba447SAndreas Jaekel static void 30463aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 30563aba447SAndreas Jaekel { 30663aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 30763aba447SAndreas Jaekel } 30863aba447SAndreas Jaekel 30963aba447SAndreas Jaekel static void 31063aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 31163aba447SAndreas Jaekel { 31263aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 31363aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 31463aba447SAndreas Jaekel time_t op_time = rec->op_time; 31563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 31663aba447SAndreas Jaekel 317d65b2fffSAndreas Jaekel if (verbose) { 318d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 319d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 320d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 321d65b2fffSAndreas Jaekel znl(); 322d65b2fffSAndreas Jaekel } else { 32363aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 32463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 32563aba447SAndreas Jaekel rec->guid, 32663aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 32763aba447SAndreas Jaekel } 328d65b2fffSAndreas Jaekel } 32963aba447SAndreas Jaekel 33063aba447SAndreas Jaekel static void 33163aba447SAndreas Jaekel zev_print_znode_create(char *buf) 33263aba447SAndreas Jaekel { 33363aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 33463aba447SAndreas Jaekel time_t op_time = rec->op_time; 33563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 3361ca5a13bSAndreas Jaekel zev_sig_t *sig; 3371ca5a13bSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 33863aba447SAndreas Jaekel 339d65b2fffSAndreas Jaekel if (verbose) { 340d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 341d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 342e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 343d65b2fffSAndreas Jaekel zpf(" name: '%s'", ZEV_NAME(rec)); 3441ca5a13bSAndreas Jaekel sig = &rec->signature; 3451ca5a13bSAndreas Jaekel sig2hex_direct(sig->value, sigval); 3461ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 3471ca5a13bSAndreas Jaekel sig->level, sig->block_offset, sigval); 348d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 349e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 350d65b2fffSAndreas Jaekel znl(); 351d65b2fffSAndreas Jaekel } else { 352c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 353c035b1e8SAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 35463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 35563aba447SAndreas Jaekel rec->guid, 35663aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 35763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 358c035b1e8SAndreas Jaekel rec->file.mtime, rec->parent.mtime, 35963aba447SAndreas Jaekel ZEV_NAME(rec)); 36063aba447SAndreas Jaekel } 361d65b2fffSAndreas Jaekel } 36263aba447SAndreas Jaekel 36363aba447SAndreas Jaekel static void 36463aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 36563aba447SAndreas Jaekel { 36663aba447SAndreas Jaekel zev_print_znode_create(buf); 36763aba447SAndreas Jaekel } 36863aba447SAndreas Jaekel 36963aba447SAndreas Jaekel static void 37063aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 37163aba447SAndreas Jaekel { 37263aba447SAndreas Jaekel zev_print_znode_create(buf); 37363aba447SAndreas Jaekel } 37463aba447SAndreas Jaekel 37563aba447SAndreas Jaekel static void 37663aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 37763aba447SAndreas Jaekel { 37863aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 37963aba447SAndreas Jaekel time_t op_time = rec->op_time; 38063aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 38163aba447SAndreas Jaekel 382d65b2fffSAndreas Jaekel if (verbose) { 383d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 384d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 385e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 386d65b2fffSAndreas Jaekel zpf(" file.name: '%s'", ZEV_NAME(rec)); 387d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 388e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 389d65b2fffSAndreas Jaekel znl(); 390d65b2fffSAndreas Jaekel } else { 391d65b2fffSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu " 392d65b2fffSAndreas Jaekel "file.mtime=%llu name='%s'\n", 39363aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 39463aba447SAndreas Jaekel rec->guid, 39563aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 3966db5d4ecSAndreas Jaekel rec->file.mtime, 39763aba447SAndreas Jaekel ZEV_NAME(rec)); 39863aba447SAndreas Jaekel } 399d65b2fffSAndreas Jaekel } 40063aba447SAndreas Jaekel 40163aba447SAndreas Jaekel static void 40263aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 40363aba447SAndreas Jaekel { 40463aba447SAndreas Jaekel zev_print_znode_remove(buf); 40563aba447SAndreas Jaekel } 40663aba447SAndreas Jaekel 40763aba447SAndreas Jaekel static void 40863aba447SAndreas Jaekel zev_print_znode_link(char *buf) 40963aba447SAndreas Jaekel { 41063aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 41163aba447SAndreas Jaekel time_t op_time = rec->op_time; 41263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 41363aba447SAndreas Jaekel 414d65b2fffSAndreas Jaekel if (verbose) { 415d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 416d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 417e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 418d65b2fffSAndreas Jaekel zpf(" link.name: '%s'", ZEV_NAME(rec)); 419d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 420e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 421d65b2fffSAndreas Jaekel znl(); 422d65b2fffSAndreas Jaekel } else { 42303101f54SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 42403101f54SAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 42563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 42663aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 42763aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 42803101f54SAndreas Jaekel rec->file.ctime, rec->parent.ctime, 42963aba447SAndreas Jaekel ZEV_NAME(rec)); 430d65b2fffSAndreas Jaekel } 43163aba447SAndreas Jaekel } 43263aba447SAndreas Jaekel 43363aba447SAndreas Jaekel static void 43463aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 43563aba447SAndreas Jaekel { 43663aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 43763aba447SAndreas Jaekel time_t op_time = rec->op_time; 43863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 4391ca5a13bSAndreas Jaekel zev_sig_t *sig; 4401ca5a13bSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 44163aba447SAndreas Jaekel 442d65b2fffSAndreas Jaekel if (verbose) { 443d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 444d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 445e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 446d65b2fffSAndreas Jaekel zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 447d65b2fffSAndreas Jaekel zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 4481ca5a13bSAndreas Jaekel sig = &rec->signature; 4491ca5a13bSAndreas Jaekel sig2hex_direct(sig->value, sigval); 4501ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 4511ca5a13bSAndreas Jaekel sig->level, sig->block_offset, sigval); 452d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 453e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 454d65b2fffSAndreas Jaekel znl(); 455d65b2fffSAndreas Jaekel } else { 456d65b2fffSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 457d65b2fffSAndreas Jaekel "name='%s' link='%s'\n", 45863aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 45963aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 46063aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 46163aba447SAndreas Jaekel ZEV_NAME(rec), 46263aba447SAndreas Jaekel ZEV_LINK(rec)); 46363aba447SAndreas Jaekel } 464d65b2fffSAndreas Jaekel } 46563aba447SAndreas Jaekel 46663aba447SAndreas Jaekel static void 46763aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 46863aba447SAndreas Jaekel { 46963aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 47063aba447SAndreas Jaekel time_t op_time = rec->op_time; 47163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 47263aba447SAndreas Jaekel 473d65b2fffSAndreas Jaekel if (verbose) { 474d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 475d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 476e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 477d65b2fffSAndreas Jaekel zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 478d65b2fffSAndreas Jaekel zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 479d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 480d65b2fffSAndreas Jaekel zev_print_inode_info("srcdir", &rec->srcdir); 481d65b2fffSAndreas Jaekel zev_print_inode_info("dstdir", &rec->dstdir); 482d65b2fffSAndreas Jaekel znl(); 483d65b2fffSAndreas Jaekel } else { 484d65b2fffSAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 485d65b2fffSAndreas Jaekel "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 486d65b2fffSAndreas Jaekel "srcdir.mtime=%llu, srcdir.ctime=%llu, " 487d65b2fffSAndreas Jaekel "dstdir.mtime=%llu, dstdir.ctime=%llu, " 48863aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 48963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 49063aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 49163aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 49263aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 493c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 494c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 495c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 49663aba447SAndreas Jaekel ZEV_SRCNAME(rec), 49763aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 49863aba447SAndreas Jaekel } 499d65b2fffSAndreas Jaekel } 50063aba447SAndreas Jaekel 50163aba447SAndreas Jaekel static void 50263aba447SAndreas Jaekel zev_print_znode_write(char *buf) 50363aba447SAndreas Jaekel { 50463aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 50563aba447SAndreas Jaekel time_t op_time = rec->op_time; 50663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 5075e286361SAndreas Jaekel zev_sig_t *sig; 5085e286361SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 5095e286361SAndreas Jaekel int i; 51063aba447SAndreas Jaekel 5115e286361SAndreas Jaekel if (verbose) { 512d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 513d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 514e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 515d65b2fffSAndreas Jaekel zpf(" offset: %llu", rec->offset); 516d65b2fffSAndreas Jaekel zpf(" length: %llu", rec->length); 517d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 518d65b2fffSAndreas Jaekel znl(); 5195e286361SAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 5205e286361SAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 5215e286361SAndreas Jaekel sig += i; 5225e286361SAndreas Jaekel sig2hex_direct(sig->value, sigval); 5231ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 5245e286361SAndreas Jaekel sig->level, sig->block_offset, sigval); 5255e286361SAndreas Jaekel } 526d65b2fffSAndreas Jaekel } else { 527d65b2fffSAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 528d65b2fffSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 529d65b2fffSAndreas Jaekel rec->file.ino, rec->file.gen, 530d65b2fffSAndreas Jaekel rec->offset, rec->length); 5315e286361SAndreas Jaekel } 53263aba447SAndreas Jaekel } 53363aba447SAndreas Jaekel 53463aba447SAndreas Jaekel static void 53563aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 53663aba447SAndreas Jaekel { 53763aba447SAndreas Jaekel zev_print_znode_write(buf); 53863aba447SAndreas Jaekel } 53963aba447SAndreas Jaekel 54063aba447SAndreas Jaekel static void 54163aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 54263aba447SAndreas Jaekel { 54363aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 54463aba447SAndreas Jaekel time_t op_time = rec->op_time; 54563aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 54663aba447SAndreas Jaekel 547d65b2fffSAndreas Jaekel if (verbose) { 548d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 549d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 550e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 551d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 552d65b2fffSAndreas Jaekel znl(); 553d65b2fffSAndreas Jaekel } else { 554c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 55563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 556c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 55763aba447SAndreas Jaekel } 558d65b2fffSAndreas Jaekel } 55963aba447SAndreas Jaekel 56063aba447SAndreas Jaekel static void 56163aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 56263aba447SAndreas Jaekel { 56363aba447SAndreas Jaekel zev_print_znode_setattr(buf); 56463aba447SAndreas Jaekel } 56563aba447SAndreas Jaekel 56663aba447SAndreas Jaekel static void 5679193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 5689193e9c2SAndreas Jaekel { 56963aba447SAndreas Jaekel int record_len; 57063aba447SAndreas Jaekel int op; 5719193e9c2SAndreas Jaekel 57263aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 57363aba447SAndreas Jaekel if (record_len != len) { 57463aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 57563aba447SAndreas Jaekel record_len, len); 5769193e9c2SAndreas Jaekel exit(1); 5779193e9c2SAndreas Jaekel } 57863aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 5799193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 58063aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 5819193e9c2SAndreas Jaekel exit(1); 5829193e9c2SAndreas Jaekel } 58363aba447SAndreas Jaekel switch (op) { 58463aba447SAndreas Jaekel case ZEV_OP_ERROR: 58563aba447SAndreas Jaekel zev_print_error(buf); 5869193e9c2SAndreas Jaekel break; 58701c2c787SAndreas Jaekel case ZEV_OP_MARK: 58801c2c787SAndreas Jaekel zev_print_mark(buf); 58901c2c787SAndreas Jaekel break; 59063aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 59163aba447SAndreas Jaekel zev_print_zfs_mount(buf); 5929193e9c2SAndreas Jaekel break; 59363aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 59463aba447SAndreas Jaekel zev_print_zfs_umount(buf); 5959193e9c2SAndreas Jaekel break; 59663aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 59763aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 5989193e9c2SAndreas Jaekel break; 59963aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 60063aba447SAndreas Jaekel zev_print_zvol_write(buf); 60163aba447SAndreas Jaekel break; 60263aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 60363aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 60463aba447SAndreas Jaekel break; 60563aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 60663aba447SAndreas Jaekel zev_print_znode_create(buf); 60763aba447SAndreas Jaekel break; 60863aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 60963aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 61063aba447SAndreas Jaekel break; 61163aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 61263aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 61363aba447SAndreas Jaekel break; 61463aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 61563aba447SAndreas Jaekel zev_print_znode_remove(buf); 61663aba447SAndreas Jaekel break; 61763aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 61863aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 61963aba447SAndreas Jaekel break; 62063aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 62163aba447SAndreas Jaekel zev_print_znode_link(buf); 62263aba447SAndreas Jaekel break; 62363aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 62463aba447SAndreas Jaekel zev_print_znode_symlink(buf); 62563aba447SAndreas Jaekel break; 62663aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 62763aba447SAndreas Jaekel zev_print_znode_rename(buf); 62863aba447SAndreas Jaekel break; 62963aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 63063aba447SAndreas Jaekel zev_print_znode_write(buf); 63163aba447SAndreas Jaekel break; 63263aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 63363aba447SAndreas Jaekel zev_print_znode_truncate(buf); 63463aba447SAndreas Jaekel break; 63563aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 63663aba447SAndreas Jaekel zev_print_znode_setattr(buf); 63763aba447SAndreas Jaekel break; 63863aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 63963aba447SAndreas Jaekel zev_print_znode_acl(buf); 6409193e9c2SAndreas Jaekel break; 6419193e9c2SAndreas Jaekel default: 64263aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 6439193e9c2SAndreas Jaekel exit(1); 6449193e9c2SAndreas Jaekel } 6459193e9c2SAndreas Jaekel } 6469193e9c2SAndreas Jaekel 647e9a5e479SAndreas Jaekel static int 6484ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 6492bb8e5e2SAndreas Jaekel { 6502bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 6512bb8e5e2SAndreas Jaekel int ret; 6529193e9c2SAndreas Jaekel char buf[4096]; 65368a46c64SAndreas Jaekel zev_event_t *ev; 65468a46c64SAndreas Jaekel int off = 0; 655e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 656e9a5e479SAndreas Jaekel int q_fd; 657e9a5e479SAndreas Jaekel 6584ca7dd5eSAndreas Jaekel if (create_tmp_queue) { 659e9a5e479SAndreas Jaekel aq.zev_max_queue_len = 0; 660e9a5e479SAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 661e9a5e479SAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 662e9a5e479SAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 663e9a5e479SAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 664e9a5e479SAndreas Jaekel 665e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 666e9a5e479SAndreas Jaekel perror("adding temporary queue failed"); 667e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 668e9a5e479SAndreas Jaekel } 669e9a5e479SAndreas Jaekel 6704ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 6714ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 672e9a5e479SAndreas Jaekel q_fd = open(buf, O_RDONLY); 673e9a5e479SAndreas Jaekel if (q_fd < 0) { 674e9a5e479SAndreas Jaekel perror("opening queue device failed"); 675e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 676e9a5e479SAndreas Jaekel } 6774ca7dd5eSAndreas Jaekel } else { 6784ca7dd5eSAndreas Jaekel q_fd = fd; 6794ca7dd5eSAndreas Jaekel } 680e9a5e479SAndreas Jaekel 6812bb8e5e2SAndreas Jaekel while (1) { 682e9a5e479SAndreas Jaekel pfd[0].fd = q_fd; 6832bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 6842bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 6852bb8e5e2SAndreas Jaekel if (ret < 0) { 6862bb8e5e2SAndreas Jaekel perror("poll failed"); 6874ca7dd5eSAndreas Jaekel close(q_fd); 688e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 6892bb8e5e2SAndreas Jaekel } 6902bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 6912bb8e5e2SAndreas Jaekel continue; 6922bb8e5e2SAndreas Jaekel /* data available */ 693e9a5e479SAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 6942bb8e5e2SAndreas Jaekel if (ret < 0) { 6952bb8e5e2SAndreas Jaekel perror("read failed"); 6964ca7dd5eSAndreas Jaekel close(q_fd); 697e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 6982bb8e5e2SAndreas Jaekel } 6992bb8e5e2SAndreas Jaekel if (ret == 0) 7002bb8e5e2SAndreas Jaekel continue; 70168a46c64SAndreas Jaekel while (ret > off) { 70268a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 70368a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 70468a46c64SAndreas Jaekel off += ev->header.record_len; 70568a46c64SAndreas Jaekel } 706108668daSAndreas Jaekel off = 0; 7072bb8e5e2SAndreas Jaekel } 7084ca7dd5eSAndreas Jaekel if (create_tmp_queue) 709e9a5e479SAndreas Jaekel close(q_fd); 710e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 7112bb8e5e2SAndreas Jaekel } 7122bb8e5e2SAndreas Jaekel 7132bb8e5e2SAndreas Jaekel static void 7142bb8e5e2SAndreas Jaekel usage(char *progname) 7152bb8e5e2SAndreas Jaekel { 716e9a5e479SAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 717e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 718e9a5e479SAndreas Jaekel fprintf(stderr, " Status information:\n"); 7192bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 7202bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 721e9a5e479SAndreas Jaekel fprintf(stderr, " -D print zev module debug " 722e9a5e479SAndreas Jaekel "information\n"); 7230abdde4aSAndreas Jaekel fprintf(stderr, " -T <interval> <cnt> zevstat mode\n"); 724e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 725e9a5e479SAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 726e9a5e479SAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 727e9a5e479SAndreas Jaekel "length\n"); 728e9a5e479SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 729e9a5e479SAndreas Jaekel "this pool\n"); 7302bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 731e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 732e9a5e479SAndreas Jaekel fprintf(stderr, " Queue management:\n"); 733e9a5e479SAndreas Jaekel fprintf(stderr, " -l list queues\n"); 7344ca7dd5eSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 7354ca7dd5eSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 736e9a5e479SAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 737e9a5e479SAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 738e9a5e479SAndreas Jaekel "(default)\n"); 739e9a5e479SAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 740e9a5e479SAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 7414ca7dd5eSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 742e9a5e479SAndreas Jaekel "length\n"); 743e9a5e479SAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 744e9a5e479SAndreas Jaekel "throttle\n"); 745e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 746e9a5e479SAndreas Jaekel fprintf(stderr, " Other options:\n"); 747e9a5e479SAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 748e9a5e479SAndreas Jaekel "('%s')\n", ZEV_DEVICE); 7494ca7dd5eSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 7504ca7dd5eSAndreas Jaekel "queue name\n"); 75101c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 752b9710123SAndreas Jaekel fprintf(stderr, " -c <filename> list file's content " 753b9710123SAndreas Jaekel "checksums\n"); 754d65b2fffSAndreas Jaekel fprintf(stderr, " -v verbose: additional output " 7555e286361SAndreas Jaekel "for some operations\n"); 756d65b2fffSAndreas Jaekel fprintf(stderr, " -g grep-friendly event output, " 757d65b2fffSAndreas Jaekel "one event per line\n"); 7582bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 7592bb8e5e2SAndreas Jaekel } 7602bb8e5e2SAndreas Jaekel 761*29fab2f9SAndreas Jaekel static void 762*29fab2f9SAndreas Jaekel zevstat_usage(char *progname) 763*29fab2f9SAndreas Jaekel { 764*29fab2f9SAndreas Jaekel fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname); 765*29fab2f9SAndreas Jaekel fprintf(stderr, " -v verbose, show counters for all event types\n"); 766*29fab2f9SAndreas Jaekel exit (EXIT_FAILURE); 767*29fab2f9SAndreas Jaekel } 768*29fab2f9SAndreas Jaekel 7692bb8e5e2SAndreas Jaekel static int 7704ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 7712bb8e5e2SAndreas Jaekel { 772e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 773e9a5e479SAndreas Jaekel int namelen; 7742bb8e5e2SAndreas Jaekel 775e9a5e479SAndreas Jaekel namelen = strlen(arg); 776e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 777e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 7782bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 7792bb8e5e2SAndreas Jaekel } 780e9a5e479SAndreas Jaekel 781e9a5e479SAndreas Jaekel aq.zev_namelen = namelen; 782e9a5e479SAndreas Jaekel strcpy(aq.zev_name, arg); 7834ca7dd5eSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 7844ca7dd5eSAndreas Jaekel if (blocking) { 7854ca7dd5eSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 7864ca7dd5eSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 7874ca7dd5eSAndreas Jaekel } else { 788e9a5e479SAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 7894ca7dd5eSAndreas Jaekel } 790e9a5e479SAndreas Jaekel 791e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 792e9a5e479SAndreas Jaekel perror("adding queue failed"); 7932bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 7942bb8e5e2SAndreas Jaekel } 7952bb8e5e2SAndreas Jaekel return (0); 7962bb8e5e2SAndreas Jaekel } 7972bb8e5e2SAndreas Jaekel 7982bb8e5e2SAndreas Jaekel static int 799e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg) 800205a9bc9SAndreas Jaekel { 801e9a5e479SAndreas Jaekel zev_ioctl_remove_queue_t aq; 802e9a5e479SAndreas Jaekel int namelen; 803205a9bc9SAndreas Jaekel 804e9a5e479SAndreas Jaekel namelen = strlen(arg); 805e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 806e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 807205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 808205a9bc9SAndreas Jaekel } 809e9a5e479SAndreas Jaekel 8104ca7dd5eSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 8114ca7dd5eSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 812e9a5e479SAndreas Jaekel 813e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 814e9a5e479SAndreas Jaekel perror("removing queue failed"); 815e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 816e9a5e479SAndreas Jaekel } 817e9a5e479SAndreas Jaekel return (0); 818e9a5e479SAndreas Jaekel } 819e9a5e479SAndreas Jaekel 820e9a5e479SAndreas Jaekel static int 821e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 822e9a5e479SAndreas Jaekel { 823e9a5e479SAndreas Jaekel uint64_t maxqueuelen; 824e9a5e479SAndreas Jaekel 825e9a5e479SAndreas Jaekel errno = 0; 826e9a5e479SAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 827e9a5e479SAndreas Jaekel if (errno) { 828e9a5e479SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 829e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 830e9a5e479SAndreas Jaekel } 831e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 832e9a5e479SAndreas Jaekel perror("setting max queue length failed"); 833205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 834205a9bc9SAndreas Jaekel } 835205a9bc9SAndreas Jaekel return (0); 836205a9bc9SAndreas Jaekel } 837205a9bc9SAndreas Jaekel 838205a9bc9SAndreas Jaekel static int 8392bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 8402bb8e5e2SAndreas Jaekel { 8412bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 8422bb8e5e2SAndreas Jaekel int len; 8432bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 8442bb8e5e2SAndreas Jaekel len = strlen(poolname); 8452bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 8462bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 8472bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 8482bb8e5e2SAndreas Jaekel } 8492bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 8502bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 8512bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 8522bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 8532bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 8542bb8e5e2SAndreas Jaekel } 8552bb8e5e2SAndreas Jaekel return (0); 8562bb8e5e2SAndreas Jaekel } 8572bb8e5e2SAndreas Jaekel 8582bb8e5e2SAndreas Jaekel int 8592bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 8602bb8e5e2SAndreas Jaekel { 8612bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 8622bb8e5e2SAndreas Jaekel } 8632bb8e5e2SAndreas Jaekel 8642bb8e5e2SAndreas Jaekel int 8652bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 8662bb8e5e2SAndreas Jaekel { 8672bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 8682bb8e5e2SAndreas Jaekel } 8692bb8e5e2SAndreas Jaekel 87001c2c787SAndreas Jaekel static int 871e9a5e479SAndreas Jaekel zev_debug_info(int fd) 872e9a5e479SAndreas Jaekel { 873e9a5e479SAndreas Jaekel zev_ioctl_debug_info_t di; 874e9a5e479SAndreas Jaekel 875e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 876e9a5e479SAndreas Jaekel perror("getting zev debug info failed"); 877e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 878e9a5e479SAndreas Jaekel } 879e9a5e479SAndreas Jaekel 880e9a5e479SAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 8815e286361SAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 8825e286361SAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 8835e286361SAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 884e9a5e479SAndreas Jaekel return 0; 885e9a5e479SAndreas Jaekel } 886e9a5e479SAndreas Jaekel 887e9a5e479SAndreas Jaekel static int 88801c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 88901c2c787SAndreas Jaekel { 89001c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 89101c2c787SAndreas Jaekel uint64_t guid; 89201c2c787SAndreas Jaekel int len; 89301c2c787SAndreas Jaekel char *p; 89401c2c787SAndreas Jaekel 89501c2c787SAndreas Jaekel p = strchr(arg, ':'); 89601c2c787SAndreas Jaekel if (!p) { 89701c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 89801c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 89901c2c787SAndreas Jaekel exit (EXIT_FAILURE); 90001c2c787SAndreas Jaekel } 90101c2c787SAndreas Jaekel *p = '\n'; 90201c2c787SAndreas Jaekel p++; 90301c2c787SAndreas Jaekel 90401c2c787SAndreas Jaekel errno = 0; 905e9a5e479SAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 90601c2c787SAndreas Jaekel if (errno) { 90701c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 90801c2c787SAndreas Jaekel exit (EXIT_FAILURE); 90901c2c787SAndreas Jaekel } 91001c2c787SAndreas Jaekel 91101c2c787SAndreas Jaekel len = strlen(p); 91201c2c787SAndreas Jaekel 91301c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 91401c2c787SAndreas Jaekel if (!mark) { 91501c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 91601c2c787SAndreas Jaekel strerror(errno)); 91701c2c787SAndreas Jaekel exit (EXIT_FAILURE); 91801c2c787SAndreas Jaekel } 91901c2c787SAndreas Jaekel mark->zev_guid = guid; 92001c2c787SAndreas Jaekel mark->zev_mark_id = 0; 92101c2c787SAndreas Jaekel mark->zev_payload_len = len; 92201c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 92301c2c787SAndreas Jaekel 92401c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 92501c2c787SAndreas Jaekel perror("queueing mark failed"); 92601c2c787SAndreas Jaekel return (EXIT_FAILURE); 92701c2c787SAndreas Jaekel } 92801c2c787SAndreas Jaekel 92901c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 93001c2c787SAndreas Jaekel return (0); 93101c2c787SAndreas Jaekel } 93201c2c787SAndreas Jaekel 933e9a5e479SAndreas Jaekel static int 934e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 935e9a5e479SAndreas Jaekel { 936e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 937e9a5e479SAndreas Jaekel 9384ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9394ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 940e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 941e9a5e479SAndreas Jaekel return EXIT_FAILURE; 942e9a5e479SAndreas Jaekel } 9434ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 944e9a5e479SAndreas Jaekel 945e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 946e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 947e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 948e9a5e479SAndreas Jaekel } 949e9a5e479SAndreas Jaekel if (block) { 950e9a5e479SAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 951e9a5e479SAndreas Jaekel } else { 952e9a5e479SAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 953e9a5e479SAndreas Jaekel } 954e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 955e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 956e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 957e9a5e479SAndreas Jaekel } 958e9a5e479SAndreas Jaekel return (0); 959e9a5e479SAndreas Jaekel } 960e9a5e479SAndreas Jaekel 961e9a5e479SAndreas Jaekel static int 962e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 963e9a5e479SAndreas Jaekel { 964e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 965e9a5e479SAndreas Jaekel 966e9a5e479SAndreas Jaekel if (!len) { 967e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 968e9a5e479SAndreas Jaekel return EXIT_FAILURE; 969e9a5e479SAndreas Jaekel } 970e9a5e479SAndreas Jaekel 9714ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9724ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 973e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 974e9a5e479SAndreas Jaekel return EXIT_FAILURE; 975e9a5e479SAndreas Jaekel } 9764ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 977e9a5e479SAndreas Jaekel 978e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 979e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 980e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 981e9a5e479SAndreas Jaekel } 982e9a5e479SAndreas Jaekel gqp.zev_max_queue_len = atol(len); 983e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 984e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 985e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 986e9a5e479SAndreas Jaekel } 987e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 988e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 989e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 990e9a5e479SAndreas Jaekel } 991e9a5e479SAndreas Jaekel 992e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 993e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 994e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 995e9a5e479SAndreas Jaekel } 996e9a5e479SAndreas Jaekel return (0); 997e9a5e479SAndreas Jaekel } 998e9a5e479SAndreas Jaekel 999e9a5e479SAndreas Jaekel static int 1000e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 1001e9a5e479SAndreas Jaekel { 1002e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1003e9a5e479SAndreas Jaekel 1004e9a5e479SAndreas Jaekel if (!len) { 1005e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 1006e9a5e479SAndreas Jaekel return EXIT_FAILURE; 1007e9a5e479SAndreas Jaekel } 1008e9a5e479SAndreas Jaekel 10094ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 10104ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1011e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 1012e9a5e479SAndreas Jaekel return EXIT_FAILURE; 1013e9a5e479SAndreas Jaekel } 10144ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 1015e9a5e479SAndreas Jaekel 1016e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1017e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 1018e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1019e9a5e479SAndreas Jaekel } 1020e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 1021e9a5e479SAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 1022e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 1023e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1024e9a5e479SAndreas Jaekel } 10254ca7dd5eSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 1026e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 1027e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1028e9a5e479SAndreas Jaekel } 1029e9a5e479SAndreas Jaekel 1030e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 1031e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 1032e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1033e9a5e479SAndreas Jaekel } 1034e9a5e479SAndreas Jaekel return (0); 1035e9a5e479SAndreas Jaekel } 1036e9a5e479SAndreas Jaekel 1037e9a5e479SAndreas Jaekel static int 1038e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg) 1039e9a5e479SAndreas Jaekel { 1040e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1041e9a5e479SAndreas Jaekel 10424ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 10434ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1044e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 1045e9a5e479SAndreas Jaekel return EXIT_FAILURE; 1046e9a5e479SAndreas Jaekel } 10474ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 1048e9a5e479SAndreas Jaekel 1049e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1050e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 1051e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1052e9a5e479SAndreas Jaekel } 1053e9a5e479SAndreas Jaekel 1054e9a5e479SAndreas Jaekel printf("queue : %s\n", arg); 1055e9a5e479SAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1056e9a5e479SAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1057e9a5e479SAndreas Jaekel printf("persistent : %s\n", 1058e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1059e9a5e479SAndreas Jaekel printf("blocking : %s\n", 1060e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1061e9a5e479SAndreas Jaekel 1062e9a5e479SAndreas Jaekel return (0); 1063e9a5e479SAndreas Jaekel } 1064e9a5e479SAndreas Jaekel 1065e9a5e479SAndreas Jaekel static int 1066e9a5e479SAndreas Jaekel zev_list_queues(int fd) 1067e9a5e479SAndreas Jaekel { 1068e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1069e9a5e479SAndreas Jaekel zev_ioctl_get_queue_list_t gql; 1070e9a5e479SAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 1071e9a5e479SAndreas Jaekel uint64_t i; 1072e9a5e479SAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1073e9a5e479SAndreas Jaekel 1074e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1075e9a5e479SAndreas Jaekel perror("getting queue list failed"); 1076e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1077e9a5e479SAndreas Jaekel } 1078e9a5e479SAndreas Jaekel 1079e9a5e479SAndreas Jaekel printf("Name Size " 1080e9a5e479SAndreas Jaekel "Max Size Wakeup Per Block\n"); 1081e9a5e479SAndreas Jaekel 1082e9a5e479SAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 1083e9a5e479SAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 1084e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 1085e9a5e479SAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1086e9a5e479SAndreas Jaekel 10874ca7dd5eSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 10884ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10894ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 10904ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1091e9a5e479SAndreas Jaekel 1092e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1093e9a5e479SAndreas Jaekel if (errno == ENOENT) 1094e9a5e479SAndreas Jaekel continue; 1095e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 1096e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1097e9a5e479SAndreas Jaekel } 1098e9a5e479SAndreas Jaekel 10994ca7dd5eSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 11004ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 11014ca7dd5eSAndreas Jaekel gs.zev_queue_name.zev_namelen = 11024ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1103e9a5e479SAndreas Jaekel 1104e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1105e9a5e479SAndreas Jaekel if (errno == ENOENT) 1106e9a5e479SAndreas Jaekel continue; 1107e9a5e479SAndreas Jaekel perror("getting statistics data failed"); 1108e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1109e9a5e479SAndreas Jaekel } 1110e9a5e479SAndreas Jaekel 1111e9a5e479SAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1112e9a5e479SAndreas Jaekel " %-3s %-3s\n", 1113e9a5e479SAndreas Jaekel name, 1114e9a5e479SAndreas Jaekel gs.zev_statistics.zev_queue_len, 1115e9a5e479SAndreas Jaekel gqp.zev_max_queue_len, 1116e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold, 1117e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1118e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1119e9a5e479SAndreas Jaekel "yes" : "no"); 1120e9a5e479SAndreas Jaekel } 1121e9a5e479SAndreas Jaekel 1122e9a5e479SAndreas Jaekel return (0); 1123e9a5e479SAndreas Jaekel } 1124e9a5e479SAndreas Jaekel 1125b9710123SAndreas Jaekel static int 1126b9710123SAndreas Jaekel zev_checksum(int dev_fd, char *filename) 1127b9710123SAndreas Jaekel { 1128b9710123SAndreas Jaekel int fd; 1129b9710123SAndreas Jaekel offset_t off; 1130b9710123SAndreas Jaekel offset_t data; 1131b9710123SAndreas Jaekel zev_sig_t *sig; 1132b9710123SAndreas Jaekel char *buf; 1133b9710123SAndreas Jaekel zev_ioctl_get_signatures_t *gs; 1134b9710123SAndreas Jaekel int i; 1135b9710123SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 1136b9710123SAndreas Jaekel int buf_size; 1137b9710123SAndreas Jaekel 1138b9710123SAndreas Jaekel /* control struct, one lv1 signature and up to 256 lv0 signatures */ 1139b9710123SAndreas Jaekel buf_size = (1 + 256) * sizeof(zev_sig_t); 1140b9710123SAndreas Jaekel buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 1141b9710123SAndreas Jaekel if (!buf) { 1142b9710123SAndreas Jaekel perror("can't allocate checksum buffer"); 1143b9710123SAndreas Jaekel return (EXIT_FAILURE); 1144b9710123SAndreas Jaekel } 1145b9710123SAndreas Jaekel 1146b9710123SAndreas Jaekel fd = open(filename, O_RDONLY); 1147b9710123SAndreas Jaekel if (fd < 0) { 1148b9710123SAndreas Jaekel perror("can't open file"); 1149b9710123SAndreas Jaekel return (EXIT_FAILURE); 1150b9710123SAndreas Jaekel } 1151b9710123SAndreas Jaekel 1152b9710123SAndreas Jaekel gs = (zev_ioctl_get_signatures_t *)buf; 1153b9710123SAndreas Jaekel gs->zev_fd = fd; 1154b9710123SAndreas Jaekel gs->zev_bufsize = buf_size; 1155b9710123SAndreas Jaekel 1156b9710123SAndreas Jaekel off = 0; 1157b9710123SAndreas Jaekel data = 0; 1158b9710123SAndreas Jaekel while (1) { 1159b9710123SAndreas Jaekel errno = 0; 1160b9710123SAndreas Jaekel data = llseek(fd, off, SEEK_DATA); 1161b9710123SAndreas Jaekel if (data < 0) { 1162b9710123SAndreas Jaekel if (errno == ENXIO) /* no more data */ 1163b9710123SAndreas Jaekel break; 1164b9710123SAndreas Jaekel perror("llseek failed"); 1165b9710123SAndreas Jaekel goto err; 1166b9710123SAndreas Jaekel } 1167b9710123SAndreas Jaekel data = P2ALIGN(data, ZEV_L1_SIZE); 1168b9710123SAndreas Jaekel off = data + ZEV_L1_SIZE; 1169b9710123SAndreas Jaekel 1170b9710123SAndreas Jaekel gs->zev_offset = data; 1171b9710123SAndreas Jaekel gs->zev_len = ZEV_L1_SIZE; 1172b9710123SAndreas Jaekel 1173b9710123SAndreas Jaekel if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 1174b9710123SAndreas Jaekel perror("ioctl to get signatures failed"); 1175b9710123SAndreas Jaekel goto err; 1176b9710123SAndreas Jaekel } 1177b9710123SAndreas Jaekel 1178b9710123SAndreas Jaekel for (i=0; i<gs->zev_signature_cnt; i++) { 1179b9710123SAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 1180b9710123SAndreas Jaekel sig += i; 1181b9710123SAndreas Jaekel sig2hex_direct(sig->value, sigval); 1182b9710123SAndreas Jaekel printf("level %d, offset %llu, value %s\n", 1183b9710123SAndreas Jaekel sig->level, sig->block_offset, sigval); 1184b9710123SAndreas Jaekel } 1185b9710123SAndreas Jaekel } 1186b9710123SAndreas Jaekel 1187b9710123SAndreas Jaekel free(buf); 1188b9710123SAndreas Jaekel close(fd); 1189b9710123SAndreas Jaekel return 0; 1190b9710123SAndreas Jaekel err: 1191b9710123SAndreas Jaekel free(buf); 1192b9710123SAndreas Jaekel close(fd); 1193b9710123SAndreas Jaekel return (EXIT_FAILURE); 1194b9710123SAndreas Jaekel } 1195b9710123SAndreas Jaekel 11960abdde4aSAndreas Jaekel typedef struct zevstat { 11970abdde4aSAndreas Jaekel uint64_t ns_start; 11980abdde4aSAndreas Jaekel uint64_t events[ZEV_OP_MIN + ZEV_OP_MAX]; 11990abdde4aSAndreas Jaekel uint64_t guids; 12000abdde4aSAndreas Jaekel uint64_t total_events; 12010abdde4aSAndreas Jaekel uint64_t total_guids; 12020abdde4aSAndreas Jaekel avl_tree_t guids_interval; 12030abdde4aSAndreas Jaekel avl_tree_t guids_runtime; 12040abdde4aSAndreas Jaekel } zevstat_t; 12050abdde4aSAndreas Jaekel 12060abdde4aSAndreas Jaekel typedef struct zev_guidtrack_t { 12070abdde4aSAndreas Jaekel uint64_t guid; 12080abdde4aSAndreas Jaekel avl_node_t avl_interval; 12090abdde4aSAndreas Jaekel avl_node_t avl_runtime; 12100abdde4aSAndreas Jaekel } zev_guidtrack_t; 12110abdde4aSAndreas Jaekel 12120abdde4aSAndreas Jaekel zevstat_t zevstat; 12130abdde4aSAndreas Jaekel 12140abdde4aSAndreas Jaekel static void 12150abdde4aSAndreas Jaekel zev_eventstat(char *buf, int len) 12160abdde4aSAndreas Jaekel { 12170abdde4aSAndreas Jaekel zev_header_t *rec = (zev_header_t *)buf; 12180abdde4aSAndreas Jaekel zev_guidtrack_t *gt; 12190abdde4aSAndreas Jaekel zev_guidtrack_t *gt_int; 12200abdde4aSAndreas Jaekel zev_guidtrack_t to_find; 12210abdde4aSAndreas Jaekel avl_index_t where; 12220abdde4aSAndreas Jaekel 12230abdde4aSAndreas Jaekel zevstat.total_events++; 12240abdde4aSAndreas Jaekel zevstat.events[rec->op]++; 12250abdde4aSAndreas Jaekel 12260abdde4aSAndreas Jaekel to_find.guid = rec->guid; 12270abdde4aSAndreas Jaekel gt = avl_find(&zevstat.guids_runtime, &to_find, &where); 12280abdde4aSAndreas Jaekel if (!gt) { 12290abdde4aSAndreas Jaekel gt = malloc(sizeof(*gt)); 12300abdde4aSAndreas Jaekel if (!gt) { 12310abdde4aSAndreas Jaekel perror("can't get guid tracking record"); 12320abdde4aSAndreas Jaekel exit (EXIT_FAILURE); 12330abdde4aSAndreas Jaekel } 12340abdde4aSAndreas Jaekel gt->guid = rec->guid; 12350abdde4aSAndreas Jaekel avl_insert(&zevstat.guids_runtime, gt, where); 12360abdde4aSAndreas Jaekel } 12370abdde4aSAndreas Jaekel gt_int = avl_find(&zevstat.guids_interval, &to_find, &where); 12380abdde4aSAndreas Jaekel if (!gt_int) 12390abdde4aSAndreas Jaekel avl_insert(&zevstat.guids_interval, gt, where); 12400abdde4aSAndreas Jaekel } 12410abdde4aSAndreas Jaekel 12420abdde4aSAndreas Jaekel static void 12430abdde4aSAndreas Jaekel zev_eventstat_interval(void) 12440abdde4aSAndreas Jaekel { 12450abdde4aSAndreas Jaekel uint64_t events; 12460abdde4aSAndreas Jaekel int i; 12470abdde4aSAndreas Jaekel zev_guidtrack_t *gt; 12480abdde4aSAndreas Jaekel 12490abdde4aSAndreas Jaekel events = 0; 12500abdde4aSAndreas Jaekel for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) { 12510abdde4aSAndreas Jaekel events += zevstat.events[i]; 12520abdde4aSAndreas Jaekel } 12530abdde4aSAndreas Jaekel 12540abdde4aSAndreas Jaekel if (verbose) { 12550abdde4aSAndreas Jaekel printf("%u %6llu %6llu %6llu %6llu ", 12560abdde4aSAndreas Jaekel time(NULL), 12570abdde4aSAndreas Jaekel events, 12580abdde4aSAndreas Jaekel zevstat.total_events, 12590abdde4aSAndreas Jaekel avl_numnodes(&zevstat.guids_interval), 12600abdde4aSAndreas Jaekel avl_numnodes(&zevstat.guids_runtime)); 12610abdde4aSAndreas Jaekel for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) 12620abdde4aSAndreas Jaekel printf("%6llu ", zevstat.events[i]); 12630abdde4aSAndreas Jaekel printf("\n"); 12640abdde4aSAndreas Jaekel } else { 12650abdde4aSAndreas Jaekel printf("%u %6llu %6llu %6llu %6llu\n", 12660abdde4aSAndreas Jaekel time(NULL), 12670abdde4aSAndreas Jaekel events, 12680abdde4aSAndreas Jaekel zevstat.total_events, 12690abdde4aSAndreas Jaekel avl_numnodes(&zevstat.guids_interval), 12700abdde4aSAndreas Jaekel avl_numnodes(&zevstat.guids_runtime)); 12710abdde4aSAndreas Jaekel } 12720abdde4aSAndreas Jaekel memset(&zevstat.events, 0, sizeof(zevstat.events)); 12730abdde4aSAndreas Jaekel zevstat.guids = 0; 12740abdde4aSAndreas Jaekel while (gt = avl_first(&zevstat.guids_interval)) 12750abdde4aSAndreas Jaekel avl_remove(&zevstat.guids_interval, gt); 12760abdde4aSAndreas Jaekel } 12770abdde4aSAndreas Jaekel 12780abdde4aSAndreas Jaekel static int 12790abdde4aSAndreas Jaekel zev_evcompar(const void *a, const void *b) 12800abdde4aSAndreas Jaekel { 12810abdde4aSAndreas Jaekel const zev_guidtrack_t *ga = a; 12820abdde4aSAndreas Jaekel const zev_guidtrack_t *gb = b; 12830abdde4aSAndreas Jaekel 12840abdde4aSAndreas Jaekel if (ga->guid > gb->guid) 12850abdde4aSAndreas Jaekel return 1; 12860abdde4aSAndreas Jaekel if (ga->guid < gb->guid) 12870abdde4aSAndreas Jaekel return -1; 12880abdde4aSAndreas Jaekel return 0; 12890abdde4aSAndreas Jaekel } 12900abdde4aSAndreas Jaekel 12910abdde4aSAndreas Jaekel static int 12920abdde4aSAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count) 12930abdde4aSAndreas Jaekel { 12940abdde4aSAndreas Jaekel uint64_t interval = 1000; 12950abdde4aSAndreas Jaekel uint64_t ms; 12960abdde4aSAndreas Jaekel uint64_t t_until; 12970abdde4aSAndreas Jaekel uint64_t t_now; 12980abdde4aSAndreas Jaekel int cnt = -1; 12990abdde4aSAndreas Jaekel struct pollfd pfd[1]; 13000abdde4aSAndreas Jaekel int ret; 13010abdde4aSAndreas Jaekel char buf[4096]; 13020abdde4aSAndreas Jaekel zev_event_t *ev; 13030abdde4aSAndreas Jaekel int off = 0; 13040abdde4aSAndreas Jaekel zev_ioctl_add_queue_t aq; 13050abdde4aSAndreas Jaekel int q_fd; 13060abdde4aSAndreas Jaekel zev_guidtrack_t *gt; 13070abdde4aSAndreas Jaekel 13080abdde4aSAndreas Jaekel memset(&zevstat, 0, sizeof(zevstat)); 13090abdde4aSAndreas Jaekel avl_create(&zevstat.guids_runtime, zev_evcompar, 13100abdde4aSAndreas Jaekel sizeof(zev_guidtrack_t), 13110abdde4aSAndreas Jaekel offsetof(zev_guidtrack_t, avl_runtime)); 13120abdde4aSAndreas Jaekel avl_create(&zevstat.guids_interval, zev_evcompar, 13130abdde4aSAndreas Jaekel sizeof(zev_guidtrack_t), 13140abdde4aSAndreas Jaekel offsetof(zev_guidtrack_t, avl_interval)); 13150abdde4aSAndreas Jaekel 1316ddaa5fcfSAndreas Jaekel if (s_interval) { 13170abdde4aSAndreas Jaekel interval = atol(s_interval); 13180abdde4aSAndreas Jaekel if (interval == 0) { 13190abdde4aSAndreas Jaekel fprintf(stderr, "invalid interval.\n"); 13200abdde4aSAndreas Jaekel return (EXIT_FAILURE); 13210abdde4aSAndreas Jaekel } 13220abdde4aSAndreas Jaekel interval *= 1000; 1323ddaa5fcfSAndreas Jaekel } 13240abdde4aSAndreas Jaekel if (s_count) { 13250abdde4aSAndreas Jaekel cnt = atol(s_count); 13260abdde4aSAndreas Jaekel if (interval == 0) { 13270abdde4aSAndreas Jaekel fprintf(stderr, "invalid count.\n"); 13280abdde4aSAndreas Jaekel return (EXIT_FAILURE); 13290abdde4aSAndreas Jaekel } 13300abdde4aSAndreas Jaekel } 13310abdde4aSAndreas Jaekel 13320abdde4aSAndreas Jaekel aq.zev_max_queue_len = 1024 * 1024; 13330abdde4aSAndreas Jaekel aq.zev_flags = 0; 13340abdde4aSAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 13350abdde4aSAndreas Jaekel "zevstat.%ld.%ld", time(NULL), getpid()); 13360abdde4aSAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 13370abdde4aSAndreas Jaekel 13380abdde4aSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 13390abdde4aSAndreas Jaekel perror("adding temporary queue failed"); 13400abdde4aSAndreas Jaekel return (EXIT_FAILURE); 13410abdde4aSAndreas Jaekel } 13420abdde4aSAndreas Jaekel 13430abdde4aSAndreas Jaekel snprintf(buf, sizeof(buf), 13440abdde4aSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 13450abdde4aSAndreas Jaekel q_fd = open(buf, O_RDONLY); 13460abdde4aSAndreas Jaekel if (q_fd < 0) { 13470abdde4aSAndreas Jaekel perror("opening queue device failed"); 13480abdde4aSAndreas Jaekel return (EXIT_FAILURE); 13490abdde4aSAndreas Jaekel } 13500abdde4aSAndreas Jaekel 13510abdde4aSAndreas Jaekel pfd[0].fd = q_fd; 13520abdde4aSAndreas Jaekel pfd[0].events = POLLIN; 13530abdde4aSAndreas Jaekel 13540abdde4aSAndreas Jaekel /* drain queue */ 1355ddaa5fcfSAndreas Jaekel while ((ret = poll(pfd, 1, 0)) > 0) { 13560abdde4aSAndreas Jaekel if (read(q_fd, buf, sizeof(buf)) < 0) { 13570abdde4aSAndreas Jaekel perror("read failed"); 13580abdde4aSAndreas Jaekel close(q_fd); 13590abdde4aSAndreas Jaekel return(EXIT_FAILURE); 13600abdde4aSAndreas Jaekel } 13610abdde4aSAndreas Jaekel } 13620abdde4aSAndreas Jaekel if (ret < 0) { 13630abdde4aSAndreas Jaekel perror("poll failed"); 13640abdde4aSAndreas Jaekel close(q_fd); 13650abdde4aSAndreas Jaekel return(EXIT_FAILURE); 13660abdde4aSAndreas Jaekel } 13670abdde4aSAndreas Jaekel 13680abdde4aSAndreas Jaekel printf("timestamp events tevents guids tguids"); 13690abdde4aSAndreas Jaekel if (verbose) { 13700abdde4aSAndreas Jaekel printf(" error mark mount umount zvol_w zvol_t "); 13710abdde4aSAndreas Jaekel printf(" close create mkdir mxattr remove rmdir "); 13720abdde4aSAndreas Jaekel printf(" link symlnk rename write trunc setatt acl"); 13730abdde4aSAndreas Jaekel } 13740abdde4aSAndreas Jaekel printf("\n"); 13750abdde4aSAndreas Jaekel while (cnt) { 13760abdde4aSAndreas Jaekel t_until = gethrtime() + (interval * 1000000); 13770abdde4aSAndreas Jaekel ms = interval; 13780abdde4aSAndreas Jaekel do { 13790abdde4aSAndreas Jaekel ret = poll(pfd, 1, ms); 13800abdde4aSAndreas Jaekel t_now = gethrtime(); 13810abdde4aSAndreas Jaekel if (t_now < t_until) { 13820abdde4aSAndreas Jaekel ms = t_until - t_now; 13830abdde4aSAndreas Jaekel ms /= 1000000ull; 13840abdde4aSAndreas Jaekel } 13850abdde4aSAndreas Jaekel if (ret < 0) { 13860abdde4aSAndreas Jaekel perror("poll failed"); 13870abdde4aSAndreas Jaekel close(q_fd); 13880abdde4aSAndreas Jaekel return(EXIT_FAILURE); 13890abdde4aSAndreas Jaekel } 13900abdde4aSAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 13910abdde4aSAndreas Jaekel continue; 13920abdde4aSAndreas Jaekel /* data available */ 13930abdde4aSAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 13940abdde4aSAndreas Jaekel if (ret < 0) { 13950abdde4aSAndreas Jaekel perror("read failed"); 13960abdde4aSAndreas Jaekel close(q_fd); 13970abdde4aSAndreas Jaekel return(EXIT_FAILURE); 13980abdde4aSAndreas Jaekel } 13990abdde4aSAndreas Jaekel if (ret == 0) 14000abdde4aSAndreas Jaekel continue; 14010abdde4aSAndreas Jaekel while (ret > off) { 14020abdde4aSAndreas Jaekel ev = (zev_event_t *)(buf + off); 14030abdde4aSAndreas Jaekel zev_eventstat(buf + off, ev->header.record_len); 14040abdde4aSAndreas Jaekel off += ev->header.record_len; 14050abdde4aSAndreas Jaekel } 14060abdde4aSAndreas Jaekel off = 0; 14070abdde4aSAndreas Jaekel } while ((t_now) < t_until && (ms > 0)); 14080abdde4aSAndreas Jaekel zev_eventstat_interval(); 14090abdde4aSAndreas Jaekel if (cnt > 0) 14100abdde4aSAndreas Jaekel cnt--; 14110abdde4aSAndreas Jaekel } 14120abdde4aSAndreas Jaekel close(q_fd); 14130abdde4aSAndreas Jaekel while (gt = avl_first(&zevstat.guids_interval)) 14140abdde4aSAndreas Jaekel avl_remove(&zevstat.guids_interval, gt); 14150abdde4aSAndreas Jaekel while (gt = avl_first(&zevstat.guids_runtime)) { 14160abdde4aSAndreas Jaekel avl_remove(&zevstat.guids_runtime, gt); 14170abdde4aSAndreas Jaekel free(gt); 14180abdde4aSAndreas Jaekel } 14190abdde4aSAndreas Jaekel return EXIT_SUCCESS; 14200abdde4aSAndreas Jaekel } 14210abdde4aSAndreas Jaekel 14222bb8e5e2SAndreas Jaekel int 14232bb8e5e2SAndreas Jaekel main(int argc, char **argv) 14242bb8e5e2SAndreas Jaekel { 14252bb8e5e2SAndreas Jaekel int fd; 14262bb8e5e2SAndreas Jaekel int c; 14272bb8e5e2SAndreas Jaekel extern char *optarg; 14284ca7dd5eSAndreas Jaekel int create_tmp_queue = 1; 14294ca7dd5eSAndreas Jaekel char buf[MAXPATHLEN]; 14306a3d43bfSAndreas Jaekel int mode = 0; 14316a3d43bfSAndreas Jaekel char *arg = NULL; 14326a3d43bfSAndreas Jaekel char *arg2 = NULL; 14330abdde4aSAndreas Jaekel char *p; 14340abdde4aSAndreas Jaekel 1435*29fab2f9SAndreas Jaekel /* open device */ 1436*29fab2f9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1437*29fab2f9SAndreas Jaekel if (fd < 0) { 1438*29fab2f9SAndreas Jaekel perror("opening zev device failed"); 1439*29fab2f9SAndreas Jaekel return EXIT_FAILURE; 1440*29fab2f9SAndreas Jaekel } 1441*29fab2f9SAndreas Jaekel 14420abdde4aSAndreas Jaekel p = strrchr(argv[0], '/'); 14430abdde4aSAndreas Jaekel if (!p) { 14440abdde4aSAndreas Jaekel p = argv[0]; 14450abdde4aSAndreas Jaekel } else { 14460abdde4aSAndreas Jaekel p++; 14470abdde4aSAndreas Jaekel } 14480abdde4aSAndreas Jaekel if (!strcmp(p, "zevstat")) { 14490abdde4aSAndreas Jaekel mode = MD_ZEVSTAT; 1450*29fab2f9SAndreas Jaekel if (argc < 2) 1451*29fab2f9SAndreas Jaekel zevstat_usage(argv[0]); 1452*29fab2f9SAndreas Jaekel if (!strcmp(argv[1], "-v")) { 1453*29fab2f9SAndreas Jaekel if (argc < 3) 1454*29fab2f9SAndreas Jaekel zevstat_usage(argv[0]); 1455*29fab2f9SAndreas Jaekel verbose++; 1456*29fab2f9SAndreas Jaekel arg = argv[2]; 1457*29fab2f9SAndreas Jaekel arg2 = argv[3]; 1458*29fab2f9SAndreas Jaekel } else { 1459*29fab2f9SAndreas Jaekel arg = argv[1]; 1460*29fab2f9SAndreas Jaekel arg2 = argv[2]; 1461*29fab2f9SAndreas Jaekel } 1462*29fab2f9SAndreas Jaekel return zev_zevstat(fd, arg, arg2); 14630abdde4aSAndreas Jaekel } 14642bb8e5e2SAndreas Jaekel 14654ca7dd5eSAndreas Jaekel while ((c = getopt(argc, argv, 14660abdde4aSAndreas Jaekel "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:T:h?")) != -1){ 14672bb8e5e2SAndreas Jaekel switch(c) { 1468d65b2fffSAndreas Jaekel case 'g': 1469d65b2fffSAndreas Jaekel grep_friendly++; 1470d65b2fffSAndreas Jaekel verbose++; 1471d65b2fffSAndreas Jaekel break; 14725e286361SAndreas Jaekel case 'v': 14735e286361SAndreas Jaekel verbose++; 14745e286361SAndreas Jaekel break; 14752bb8e5e2SAndreas Jaekel case 's': 14766a3d43bfSAndreas Jaekel mode = MD_STATISTICS; 14776a3d43bfSAndreas Jaekel break; 14782bb8e5e2SAndreas Jaekel case 'p': 14796a3d43bfSAndreas Jaekel mode = MD_POLL_EVENTS; 14806a3d43bfSAndreas Jaekel break; 1481b9710123SAndreas Jaekel case 'c': 14826a3d43bfSAndreas Jaekel mode = MD_CHECKSUMS; 14836a3d43bfSAndreas Jaekel arg = optarg; 14846a3d43bfSAndreas Jaekel break; 1485e9a5e479SAndreas Jaekel case 'D': 14866a3d43bfSAndreas Jaekel mode = MD_DEBUG_INFO; 14876a3d43bfSAndreas Jaekel break; 14882bb8e5e2SAndreas Jaekel case 'd': 1489e9a5e479SAndreas Jaekel close(fd); 14902bb8e5e2SAndreas Jaekel zev_device = optarg; 1491e9a5e479SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1492e9a5e479SAndreas Jaekel if (fd < 0) { 1493e9a5e479SAndreas Jaekel perror("opening zev device failed"); 1494e9a5e479SAndreas Jaekel return EXIT_FAILURE; 1495e9a5e479SAndreas Jaekel } 14964ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 14974ca7dd5eSAndreas Jaekel break; 14984ca7dd5eSAndreas Jaekel case 'q': 14994ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 15004ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 15014ca7dd5eSAndreas Jaekel close(fd); 15024ca7dd5eSAndreas Jaekel zev_device = buf; 15034ca7dd5eSAndreas Jaekel fd = open(zev_device, O_RDONLY); 15044ca7dd5eSAndreas Jaekel if (fd < 0) { 15054ca7dd5eSAndreas Jaekel perror("opening zev device failed"); 15064ca7dd5eSAndreas Jaekel return EXIT_FAILURE; 15074ca7dd5eSAndreas Jaekel } 15084ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 15092bb8e5e2SAndreas Jaekel break; 1510e9a5e479SAndreas Jaekel case 'l': 15116a3d43bfSAndreas Jaekel mode = MD_LIST_QUEUES; 15126a3d43bfSAndreas Jaekel break; 1513e9a5e479SAndreas Jaekel case 'Q': 15146a3d43bfSAndreas Jaekel mode = MD_SET_GLOBAL_MAX_QUEUE_LEN; 15156a3d43bfSAndreas Jaekel arg = optarg; 15166a3d43bfSAndreas Jaekel break; 15174ca7dd5eSAndreas Jaekel case 'L': 15186a3d43bfSAndreas Jaekel mode = MD_SET_MAX_QUEUE_LEN; 15196a3d43bfSAndreas Jaekel arg = optarg; 15206a3d43bfSAndreas Jaekel arg2 = argv[optind]; 15216a3d43bfSAndreas Jaekel break; 15220abdde4aSAndreas Jaekel case 'T': 15230abdde4aSAndreas Jaekel mode = MD_ZEVSTAT; 15240abdde4aSAndreas Jaekel arg = optarg; 15250abdde4aSAndreas Jaekel arg2 = argv[optind]; 15260abdde4aSAndreas Jaekel break; 1527205a9bc9SAndreas Jaekel case 't': 15286a3d43bfSAndreas Jaekel mode = MD_SET_POLL_WAKEUP_QUEUE_LEN; 15296a3d43bfSAndreas Jaekel arg = optarg; 15306a3d43bfSAndreas Jaekel arg2 = argv[optind]; 15316a3d43bfSAndreas Jaekel break; 15322bb8e5e2SAndreas Jaekel case 'm': 15336a3d43bfSAndreas Jaekel mode = MD_MUTE_POOL; 15346a3d43bfSAndreas Jaekel arg = optarg; 15356a3d43bfSAndreas Jaekel break; 15362bb8e5e2SAndreas Jaekel case 'M': 15376a3d43bfSAndreas Jaekel mode = MD_UNMUTE_POOL; 15386a3d43bfSAndreas Jaekel arg = optarg; 15396a3d43bfSAndreas Jaekel break; 154001c2c787SAndreas Jaekel case 'k': 15416a3d43bfSAndreas Jaekel mode = MD_MARK; 15426a3d43bfSAndreas Jaekel arg = optarg; 15436a3d43bfSAndreas Jaekel break; 1544e9a5e479SAndreas Jaekel case 'a': 15456a3d43bfSAndreas Jaekel mode = MD_ADD_QUEUE; 15466a3d43bfSAndreas Jaekel arg = optarg; 15476a3d43bfSAndreas Jaekel break; 15484ca7dd5eSAndreas Jaekel case 'A': 15496a3d43bfSAndreas Jaekel mode = MD_ADD_BLOCKING_QUEUE; 15506a3d43bfSAndreas Jaekel arg = optarg; 15516a3d43bfSAndreas Jaekel break; 1552e9a5e479SAndreas Jaekel case 'r': 15536a3d43bfSAndreas Jaekel mode = MD_REMOVE_QUEUE; 15546a3d43bfSAndreas Jaekel arg = optarg; 15556a3d43bfSAndreas Jaekel break; 1556e9a5e479SAndreas Jaekel case 'b': 15576a3d43bfSAndreas Jaekel mode = MD_QUEUE_BLOCKING; 15586a3d43bfSAndreas Jaekel arg = optarg; 15596a3d43bfSAndreas Jaekel break; 1560e9a5e479SAndreas Jaekel case 'B': 15616a3d43bfSAndreas Jaekel mode = MD_QUEUE_NONBLOCKING; 15626a3d43bfSAndreas Jaekel arg = optarg; 15636a3d43bfSAndreas Jaekel break; 1564e9a5e479SAndreas Jaekel case 'P': 15656a3d43bfSAndreas Jaekel mode = MD_QUEUE_PROPERTIES; 15666a3d43bfSAndreas Jaekel arg = optarg; 15676a3d43bfSAndreas Jaekel break; 15682bb8e5e2SAndreas Jaekel case 'h': 15692bb8e5e2SAndreas Jaekel case '?': 15702bb8e5e2SAndreas Jaekel default: 15712bb8e5e2SAndreas Jaekel usage(argv[0]); 15722bb8e5e2SAndreas Jaekel } 15732bb8e5e2SAndreas Jaekel } 15746a3d43bfSAndreas Jaekel 15756a3d43bfSAndreas Jaekel switch (mode) { 15766a3d43bfSAndreas Jaekel case MD_STATISTICS: 15776a3d43bfSAndreas Jaekel return zev_statistics(fd); 15786a3d43bfSAndreas Jaekel case MD_POLL_EVENTS: 15796a3d43bfSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 15806a3d43bfSAndreas Jaekel case MD_CHECKSUMS: 15816a3d43bfSAndreas Jaekel return zev_checksum(fd, arg); 15826a3d43bfSAndreas Jaekel case MD_DEBUG_INFO: 15836a3d43bfSAndreas Jaekel return zev_debug_info(fd); 15846a3d43bfSAndreas Jaekel case MD_LIST_QUEUES: 15856a3d43bfSAndreas Jaekel return zev_list_queues(fd); 15866a3d43bfSAndreas Jaekel case MD_SET_GLOBAL_MAX_QUEUE_LEN: 15876a3d43bfSAndreas Jaekel return zev_set_global_max_queue_len(fd, arg); 15886a3d43bfSAndreas Jaekel case MD_SET_MAX_QUEUE_LEN: 15896a3d43bfSAndreas Jaekel return zev_set_max_queue_len(fd, arg, arg2); 15906a3d43bfSAndreas Jaekel case MD_SET_POLL_WAKEUP_QUEUE_LEN: 15916a3d43bfSAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, arg, arg2); 15920abdde4aSAndreas Jaekel case MD_ZEVSTAT: 15930abdde4aSAndreas Jaekel return zev_zevstat(fd, arg, arg2); 15946a3d43bfSAndreas Jaekel case MD_MUTE_POOL: 15956a3d43bfSAndreas Jaekel return zev_mute_pool(fd, arg); 15966a3d43bfSAndreas Jaekel case MD_UNMUTE_POOL: 15976a3d43bfSAndreas Jaekel return zev_unmute_pool(fd, arg); 15986a3d43bfSAndreas Jaekel case MD_MARK: 15996a3d43bfSAndreas Jaekel return zev_mark(fd, arg); 16006a3d43bfSAndreas Jaekel case MD_ADD_QUEUE: 16016a3d43bfSAndreas Jaekel return zev_add_queue(fd, arg, 0); 16026a3d43bfSAndreas Jaekel case MD_ADD_BLOCKING_QUEUE: 16036a3d43bfSAndreas Jaekel return zev_add_queue(fd, arg, 1); 16046a3d43bfSAndreas Jaekel case MD_REMOVE_QUEUE: 16056a3d43bfSAndreas Jaekel return zev_remove_queue(fd, arg); 16066a3d43bfSAndreas Jaekel case MD_QUEUE_BLOCKING: 16076a3d43bfSAndreas Jaekel return zev_queue_blocking(fd, arg, 0); 16086a3d43bfSAndreas Jaekel case MD_QUEUE_NONBLOCKING: 16096a3d43bfSAndreas Jaekel return zev_queue_blocking(fd, arg, 1); 16106a3d43bfSAndreas Jaekel case MD_QUEUE_PROPERTIES: 16116a3d43bfSAndreas Jaekel return zev_queue_properties(fd, arg); 16126a3d43bfSAndreas Jaekel default: 16132bb8e5e2SAndreas Jaekel close(fd); 16146a3d43bfSAndreas Jaekel usage(argv[0]); 1615e9a5e479SAndreas Jaekel return EXIT_FAILURE; 16166a3d43bfSAndreas Jaekel }; 16172bb8e5e2SAndreas Jaekel } 16182bb8e5e2SAndreas Jaekel 1619