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> 122bb8e5e2SAndreas Jaekel 13e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 142bb8e5e2SAndreas Jaekel 152bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 162bb8e5e2SAndreas Jaekel 179193e9c2SAndreas Jaekel static char *zev_op_name[] = { 18d65b2fffSAndreas Jaekel "ERROR", 19d65b2fffSAndreas Jaekel "MARK", 20d65b2fffSAndreas Jaekel "ZFS_MOUNT", 21d65b2fffSAndreas Jaekel "ZFS_UMOUNT", 22d65b2fffSAndreas Jaekel "ZVOL_WRITE", 23d65b2fffSAndreas Jaekel "ZVOL_TRUNCATE", 24d65b2fffSAndreas Jaekel "ZNODE_CLOSE_AFTER_UPDATE", 25d65b2fffSAndreas Jaekel "ZNODE_CREATE", 26d65b2fffSAndreas Jaekel "ZNODE_MKDIR", 27d65b2fffSAndreas Jaekel "ZNODE_MAKE_XATTR_DIR", 28d65b2fffSAndreas Jaekel "ZNODE_REMOVE", 29d65b2fffSAndreas Jaekel "ZNODE_RMDIR", 30d65b2fffSAndreas Jaekel "ZNODE_LINK", 31d65b2fffSAndreas Jaekel "ZNODE_SYMLINK", 32d65b2fffSAndreas Jaekel "ZNODE_RENAME", 33d65b2fffSAndreas Jaekel "ZNODE_WRITE", 34d65b2fffSAndreas Jaekel "ZNODE_TRUNCATE", 35d65b2fffSAndreas Jaekel "ZNODE_SETATTR", 36d65b2fffSAndreas Jaekel "ZNODE_ACL", 379193e9c2SAndreas Jaekel NULL 389193e9c2SAndreas Jaekel }; 399193e9c2SAndreas Jaekel 405e286361SAndreas Jaekel static int verbose = 0; 41d65b2fffSAndreas Jaekel static int grep_friendly = 0; 42d65b2fffSAndreas Jaekel 43d65b2fffSAndreas Jaekel static void 44d65b2fffSAndreas Jaekel zpf(char *fmt, ...) 45d65b2fffSAndreas Jaekel { 46d65b2fffSAndreas Jaekel va_list ap; 47d65b2fffSAndreas Jaekel 48d65b2fffSAndreas Jaekel va_start(ap, fmt); 49d65b2fffSAndreas Jaekel vprintf(fmt, ap); 50d65b2fffSAndreas Jaekel va_end(ap); 51d65b2fffSAndreas Jaekel if (grep_friendly) { 52d65b2fffSAndreas Jaekel printf(" "); 53d65b2fffSAndreas Jaekel } else { 54d65b2fffSAndreas Jaekel printf("\n"); 55d65b2fffSAndreas Jaekel } 56d65b2fffSAndreas Jaekel } 57d65b2fffSAndreas Jaekel 58d65b2fffSAndreas Jaekel static void 59d65b2fffSAndreas Jaekel znl(void) 60d65b2fffSAndreas Jaekel { 61d65b2fffSAndreas Jaekel if (grep_friendly) 62d65b2fffSAndreas Jaekel printf("\n"); 63d65b2fffSAndreas Jaekel } 645e286361SAndreas Jaekel 65*1ca5a13bSAndreas Jaekel static void 66*1ca5a13bSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 67*1ca5a13bSAndreas Jaekel { 68*1ca5a13bSAndreas Jaekel int i; 69*1ca5a13bSAndreas Jaekel 70*1ca5a13bSAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 71*1ca5a13bSAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 72*1ca5a13bSAndreas Jaekel } 73*1ca5a13bSAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 74*1ca5a13bSAndreas Jaekel } 75*1ca5a13bSAndreas Jaekel 76e9a5e479SAndreas Jaekel static int 772bb8e5e2SAndreas Jaekel zev_statistics(int fd) 782bb8e5e2SAndreas Jaekel { 792bb8e5e2SAndreas Jaekel zev_statistics_t zs; 80e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 812bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 82e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 832bb8e5e2SAndreas Jaekel } 842bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 852bb8e5e2SAndreas Jaekel 862bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 872bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 882bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 892bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 902bb8e5e2SAndreas Jaekel 91e9a5e479SAndreas Jaekel printf(" discarded events : %lu\n", 92e9a5e479SAndreas Jaekel zs.zev_cnt_discarded_events); 93e9a5e479SAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 94e9a5e479SAndreas Jaekel 952bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 962bb8e5e2SAndreas Jaekel 972bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 982bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 992bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 1002bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 1012bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 1022bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 1032bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 1042bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 1052bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 1062bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 1072bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 1082bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 1092bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 1102bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 1112bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 1122bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 1132bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 114e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 1152bb8e5e2SAndreas Jaekel } 1162bb8e5e2SAndreas Jaekel 1172bb8e5e2SAndreas Jaekel static void 118d65b2fffSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info) 119d65b2fffSAndreas Jaekel { 120d65b2fffSAndreas Jaekel zpf(" %s.inode: %llu", name, info->ino); 121d65b2fffSAndreas Jaekel zpf(" %s.gen: %llu", name, info->gen); 122d65b2fffSAndreas Jaekel zpf(" %s.mtime: %llu", name, info->mtime); 123d65b2fffSAndreas Jaekel zpf(" %s.ctime: %llu", name, info->ctime); 124d65b2fffSAndreas Jaekel zpf(" %s.size: %llu", name, info->size); 125d65b2fffSAndreas Jaekel zpf(" %s.mode: %llo", name, info->mode); 126d65b2fffSAndreas Jaekel zpf(" %s.links: %llu", name, info->links); 127d65b2fffSAndreas Jaekel zpf(" %s.type: %lu", name, info->type); 128d65b2fffSAndreas Jaekel zpf(" %s.flags: %lu", name, info->flags); 129d65b2fffSAndreas Jaekel } 130d65b2fffSAndreas Jaekel 131d65b2fffSAndreas Jaekel static void 132d65b2fffSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec) 133d65b2fffSAndreas Jaekel { 134d65b2fffSAndreas Jaekel int i; 135d65b2fffSAndreas Jaekel int j; 136d65b2fffSAndreas Jaekel uint8_t *p; 137d65b2fffSAndreas Jaekel char c; 138d65b2fffSAndreas Jaekel 139d65b2fffSAndreas Jaekel zpf(" payload:"); 140d65b2fffSAndreas Jaekel p = (uint8_t *)ZEV_PAYLOAD(rec); 141d65b2fffSAndreas Jaekel for (i=0; i<rec->payload_len; i+=16) { 142d65b2fffSAndreas Jaekel printf(" "); 143d65b2fffSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 144d65b2fffSAndreas Jaekel printf("%02x ", p[j]); 145d65b2fffSAndreas Jaekel if (j == i + 7) 146d65b2fffSAndreas Jaekel printf(" "); 147d65b2fffSAndreas Jaekel } 148d65b2fffSAndreas Jaekel if (grep_friendly) 149d65b2fffSAndreas Jaekel continue; 150d65b2fffSAndreas Jaekel for (; j<i+16; j++) { 151d65b2fffSAndreas Jaekel printf(" "); 152d65b2fffSAndreas Jaekel if (j == i + 7) 153d65b2fffSAndreas Jaekel printf(" "); 154d65b2fffSAndreas Jaekel } 155d65b2fffSAndreas Jaekel printf(" "); 156d65b2fffSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 157d65b2fffSAndreas Jaekel c = '.'; 158d65b2fffSAndreas Jaekel if (p[j] >= ' ' && p[j] <= '~') 159d65b2fffSAndreas Jaekel c = p[j]; 160d65b2fffSAndreas Jaekel printf("%c", c); 161d65b2fffSAndreas Jaekel if (j == i + 7) 162d65b2fffSAndreas Jaekel printf(" "); 163d65b2fffSAndreas Jaekel } 164d65b2fffSAndreas Jaekel printf("\n"); 165d65b2fffSAndreas Jaekel } 166d65b2fffSAndreas Jaekel } 167d65b2fffSAndreas Jaekel 168d65b2fffSAndreas Jaekel static void 16963aba447SAndreas Jaekel zev_print_error(char *buf) 17063aba447SAndreas Jaekel { 17163aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 17263aba447SAndreas Jaekel time_t op_time = rec->op_time; 17363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 17463aba447SAndreas Jaekel 175d65b2fffSAndreas Jaekel if (verbose) { 176d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 177d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 178d65b2fffSAndreas Jaekel zpf(" failed.op: %s", 179d65b2fffSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN]); 180d65b2fffSAndreas Jaekel zpf(" message: %s", ZEV_ERRSTR(rec)); 181d65b2fffSAndreas Jaekel znl(); 182d65b2fffSAndreas Jaekel } else { 18363aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 18463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 185d65b2fffSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], 186d65b2fffSAndreas Jaekel ZEV_ERRSTR(rec)); 187d65b2fffSAndreas Jaekel } 18863aba447SAndreas Jaekel } 18963aba447SAndreas Jaekel 19063aba447SAndreas Jaekel static void 19101c2c787SAndreas Jaekel zev_print_mark(char *buf) 19201c2c787SAndreas Jaekel { 19301c2c787SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 19401c2c787SAndreas Jaekel time_t op_time = rec->op_time; 19501c2c787SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 19601c2c787SAndreas Jaekel 197d65b2fffSAndreas Jaekel if (verbose) { 198d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 199d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 200d65b2fffSAndreas Jaekel zpf(" mark.id: %llu", rec->mark_id); 201d65b2fffSAndreas Jaekel zpf(" payload.len: %llu", rec->payload_len); 202d65b2fffSAndreas Jaekel if (rec->payload_len) 203d65b2fffSAndreas Jaekel zev_print_mark_payload(rec); 204d65b2fffSAndreas Jaekel znl(); 205d65b2fffSAndreas Jaekel } else { 20601c2c787SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 207d65b2fffSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 208d65b2fffSAndreas Jaekel rec->mark_id, rec->payload_len); 209d65b2fffSAndreas Jaekel } 21001c2c787SAndreas Jaekel } 21101c2c787SAndreas Jaekel 21201c2c787SAndreas Jaekel static void 21363aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 21463aba447SAndreas Jaekel { 21563aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 21663aba447SAndreas Jaekel time_t op_time = rec->op_time; 21763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 21863aba447SAndreas Jaekel 219d65b2fffSAndreas Jaekel if (verbose) { 220d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 221d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 222d65b2fffSAndreas Jaekel zpf(" dataset: %s", ZEV_DATASET(rec)); 223d65b2fffSAndreas Jaekel zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 224d65b2fffSAndreas Jaekel zpf(" remount: %s", rec->remount ? "true" : "false"); 225d65b2fffSAndreas Jaekel zev_print_inode_info("root", &rec->root); 226d65b2fffSAndreas Jaekel znl(); 227d65b2fffSAndreas Jaekel } else { 228d65b2fffSAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' " 229d65b2fffSAndreas Jaekel "mountpoint='%s'\n", 23063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 23163aba447SAndreas Jaekel rec->guid, 23263aba447SAndreas Jaekel rec->remount ? "true" : "false", 23363aba447SAndreas Jaekel ZEV_DATASET(rec), 23463aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 23563aba447SAndreas Jaekel } 236d65b2fffSAndreas Jaekel } 23763aba447SAndreas Jaekel 23863aba447SAndreas Jaekel static void 23963aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 24063aba447SAndreas Jaekel { 24163aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 24263aba447SAndreas Jaekel time_t op_time = rec->op_time; 24363aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 24463aba447SAndreas Jaekel 245d65b2fffSAndreas Jaekel if (verbose) { 246d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 247d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 248d65b2fffSAndreas Jaekel znl(); 249d65b2fffSAndreas Jaekel } else { 25063aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 25163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 25263aba447SAndreas Jaekel rec->guid); 25363aba447SAndreas Jaekel } 254d65b2fffSAndreas Jaekel } 25563aba447SAndreas Jaekel 25663aba447SAndreas Jaekel static void 25763aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 25863aba447SAndreas Jaekel { 25963aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 26063aba447SAndreas Jaekel time_t op_time = rec->op_time; 26163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 26263aba447SAndreas Jaekel 263d65b2fffSAndreas Jaekel if (verbose) { 264d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 265d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 266e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 267d65b2fffSAndreas Jaekel zpf(" offset: %llu", rec->offset); 268d65b2fffSAndreas Jaekel zpf(" length: %llu", rec->length); 269d65b2fffSAndreas Jaekel znl(); 270d65b2fffSAndreas Jaekel } else { 27163aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 27263aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 27363aba447SAndreas Jaekel rec->guid, 27463aba447SAndreas Jaekel rec->offset, 27563aba447SAndreas Jaekel rec->length); 27663aba447SAndreas Jaekel } 277d65b2fffSAndreas Jaekel } 27863aba447SAndreas Jaekel 27963aba447SAndreas Jaekel static void 28063aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 28163aba447SAndreas Jaekel { 28263aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 28363aba447SAndreas Jaekel } 28463aba447SAndreas Jaekel 28563aba447SAndreas Jaekel static void 28663aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 28763aba447SAndreas Jaekel { 28863aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 28963aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 29063aba447SAndreas Jaekel time_t op_time = rec->op_time; 29163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 29263aba447SAndreas Jaekel 293d65b2fffSAndreas Jaekel if (verbose) { 294d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 295d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 296d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 297d65b2fffSAndreas Jaekel znl(); 298d65b2fffSAndreas Jaekel } else { 29963aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 30063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 30163aba447SAndreas Jaekel rec->guid, 30263aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 30363aba447SAndreas Jaekel } 304d65b2fffSAndreas Jaekel } 30563aba447SAndreas Jaekel 30663aba447SAndreas Jaekel static void 30763aba447SAndreas Jaekel zev_print_znode_create(char *buf) 30863aba447SAndreas Jaekel { 30963aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 31063aba447SAndreas Jaekel time_t op_time = rec->op_time; 31163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 312*1ca5a13bSAndreas Jaekel zev_sig_t *sig; 313*1ca5a13bSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 31463aba447SAndreas Jaekel 315d65b2fffSAndreas Jaekel if (verbose) { 316d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 317d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 318e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 319d65b2fffSAndreas Jaekel zpf(" name: '%s'", ZEV_NAME(rec)); 320*1ca5a13bSAndreas Jaekel sig = &rec->signature; 321*1ca5a13bSAndreas Jaekel sig2hex_direct(sig->value, sigval); 322*1ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 323*1ca5a13bSAndreas Jaekel sig->level, sig->block_offset, sigval); 324d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 325e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 326d65b2fffSAndreas Jaekel znl(); 327d65b2fffSAndreas Jaekel } else { 328c035b1e8SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 329c035b1e8SAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 33063aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 33163aba447SAndreas Jaekel rec->guid, 33263aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 33363aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 334c035b1e8SAndreas Jaekel rec->file.mtime, rec->parent.mtime, 33563aba447SAndreas Jaekel ZEV_NAME(rec)); 33663aba447SAndreas Jaekel } 337d65b2fffSAndreas Jaekel } 33863aba447SAndreas Jaekel 33963aba447SAndreas Jaekel static void 34063aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 34163aba447SAndreas Jaekel { 34263aba447SAndreas Jaekel zev_print_znode_create(buf); 34363aba447SAndreas Jaekel } 34463aba447SAndreas Jaekel 34563aba447SAndreas Jaekel static void 34663aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 34763aba447SAndreas Jaekel { 34863aba447SAndreas Jaekel zev_print_znode_create(buf); 34963aba447SAndreas Jaekel } 35063aba447SAndreas Jaekel 35163aba447SAndreas Jaekel static void 35263aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 35363aba447SAndreas Jaekel { 35463aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 35563aba447SAndreas Jaekel time_t op_time = rec->op_time; 35663aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 35763aba447SAndreas Jaekel 358d65b2fffSAndreas Jaekel if (verbose) { 359d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 360d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 361e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 362d65b2fffSAndreas Jaekel zpf(" file.name: '%s'", ZEV_NAME(rec)); 363d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 364e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 365d65b2fffSAndreas Jaekel znl(); 366d65b2fffSAndreas Jaekel } else { 367d65b2fffSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu " 368d65b2fffSAndreas Jaekel "file.mtime=%llu name='%s'\n", 36963aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 37063aba447SAndreas Jaekel rec->guid, 37163aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 3726db5d4ecSAndreas Jaekel rec->file.mtime, 37363aba447SAndreas Jaekel ZEV_NAME(rec)); 37463aba447SAndreas Jaekel } 375d65b2fffSAndreas Jaekel } 37663aba447SAndreas Jaekel 37763aba447SAndreas Jaekel static void 37863aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 37963aba447SAndreas Jaekel { 38063aba447SAndreas Jaekel zev_print_znode_remove(buf); 38163aba447SAndreas Jaekel } 38263aba447SAndreas Jaekel 38363aba447SAndreas Jaekel static void 38463aba447SAndreas Jaekel zev_print_znode_link(char *buf) 38563aba447SAndreas Jaekel { 38663aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 38763aba447SAndreas Jaekel time_t op_time = rec->op_time; 38863aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 38963aba447SAndreas Jaekel 390d65b2fffSAndreas Jaekel if (verbose) { 391d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 392d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 393e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 394d65b2fffSAndreas Jaekel zpf(" link.name: '%s'", ZEV_NAME(rec)); 395d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 396e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 397d65b2fffSAndreas Jaekel znl(); 398d65b2fffSAndreas Jaekel } else { 39903101f54SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 40003101f54SAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 40163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 40263aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 40363aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 40403101f54SAndreas Jaekel rec->file.ctime, rec->parent.ctime, 40563aba447SAndreas Jaekel ZEV_NAME(rec)); 406d65b2fffSAndreas Jaekel } 40763aba447SAndreas Jaekel } 40863aba447SAndreas Jaekel 40963aba447SAndreas Jaekel static void 41063aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 41163aba447SAndreas Jaekel { 41263aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 41363aba447SAndreas Jaekel time_t op_time = rec->op_time; 41463aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 415*1ca5a13bSAndreas Jaekel zev_sig_t *sig; 416*1ca5a13bSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 41763aba447SAndreas Jaekel 418d65b2fffSAndreas Jaekel if (verbose) { 419d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 420d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 421e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 422d65b2fffSAndreas Jaekel zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 423d65b2fffSAndreas Jaekel zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 424*1ca5a13bSAndreas Jaekel sig = &rec->signature; 425*1ca5a13bSAndreas Jaekel sig2hex_direct(sig->value, sigval); 426*1ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 427*1ca5a13bSAndreas Jaekel sig->level, sig->block_offset, sigval); 428d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 429e206ace3SAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 430d65b2fffSAndreas Jaekel znl(); 431d65b2fffSAndreas Jaekel } else { 432d65b2fffSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 433d65b2fffSAndreas Jaekel "name='%s' link='%s'\n", 43463aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 43563aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 43663aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 43763aba447SAndreas Jaekel ZEV_NAME(rec), 43863aba447SAndreas Jaekel ZEV_LINK(rec)); 43963aba447SAndreas Jaekel } 440d65b2fffSAndreas Jaekel } 44163aba447SAndreas Jaekel 44263aba447SAndreas Jaekel static void 44363aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 44463aba447SAndreas Jaekel { 44563aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 44663aba447SAndreas Jaekel time_t op_time = rec->op_time; 44763aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 44863aba447SAndreas Jaekel 449d65b2fffSAndreas Jaekel if (verbose) { 450d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 451d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 452e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 453d65b2fffSAndreas Jaekel zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 454d65b2fffSAndreas Jaekel zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 455d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 456d65b2fffSAndreas Jaekel zev_print_inode_info("srcdir", &rec->srcdir); 457d65b2fffSAndreas Jaekel zev_print_inode_info("dstdir", &rec->dstdir); 458d65b2fffSAndreas Jaekel znl(); 459d65b2fffSAndreas Jaekel } else { 460d65b2fffSAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 461d65b2fffSAndreas Jaekel "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 462d65b2fffSAndreas Jaekel "srcdir.mtime=%llu, srcdir.ctime=%llu, " 463d65b2fffSAndreas Jaekel "dstdir.mtime=%llu, dstdir.ctime=%llu, " 46463aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 46563aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 46663aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 46763aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 46863aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 469c035b1e8SAndreas Jaekel rec->file.mtime, rec->file.ctime, 470c035b1e8SAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 471c035b1e8SAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 47263aba447SAndreas Jaekel ZEV_SRCNAME(rec), 47363aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 47463aba447SAndreas Jaekel } 475d65b2fffSAndreas Jaekel } 47663aba447SAndreas Jaekel 47763aba447SAndreas Jaekel static void 47863aba447SAndreas Jaekel zev_print_znode_write(char *buf) 47963aba447SAndreas Jaekel { 48063aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 48163aba447SAndreas Jaekel time_t op_time = rec->op_time; 48263aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 4835e286361SAndreas Jaekel zev_sig_t *sig; 4845e286361SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 4855e286361SAndreas Jaekel int i; 48663aba447SAndreas Jaekel 4875e286361SAndreas Jaekel if (verbose) { 488d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 489d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 490e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 491d65b2fffSAndreas Jaekel zpf(" offset: %llu", rec->offset); 492d65b2fffSAndreas Jaekel zpf(" length: %llu", rec->length); 493d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 494d65b2fffSAndreas Jaekel znl(); 4955e286361SAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 4965e286361SAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 4975e286361SAndreas Jaekel sig += i; 4985e286361SAndreas Jaekel sig2hex_direct(sig->value, sigval); 499*1ca5a13bSAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 5005e286361SAndreas Jaekel sig->level, sig->block_offset, sigval); 5015e286361SAndreas Jaekel } 502d65b2fffSAndreas Jaekel } else { 503d65b2fffSAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 504d65b2fffSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 505d65b2fffSAndreas Jaekel rec->file.ino, rec->file.gen, 506d65b2fffSAndreas Jaekel rec->offset, rec->length); 5075e286361SAndreas Jaekel } 50863aba447SAndreas Jaekel } 50963aba447SAndreas Jaekel 51063aba447SAndreas Jaekel static void 51163aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 51263aba447SAndreas Jaekel { 51363aba447SAndreas Jaekel zev_print_znode_write(buf); 51463aba447SAndreas Jaekel } 51563aba447SAndreas Jaekel 51663aba447SAndreas Jaekel static void 51763aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 51863aba447SAndreas Jaekel { 51963aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 52063aba447SAndreas Jaekel time_t op_time = rec->op_time; 52163aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 52263aba447SAndreas Jaekel 523d65b2fffSAndreas Jaekel if (verbose) { 524d65b2fffSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 525d65b2fffSAndreas Jaekel zpf(" guid: %llu", rec->guid); 526e206ace3SAndreas Jaekel zpf(" txg: %llu", rec->txg); 527d65b2fffSAndreas Jaekel zev_print_inode_info("file", &rec->file); 528d65b2fffSAndreas Jaekel znl(); 529d65b2fffSAndreas Jaekel } else { 530c035b1e8SAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 53163aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 532c035b1e8SAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 53363aba447SAndreas Jaekel } 534d65b2fffSAndreas Jaekel } 53563aba447SAndreas Jaekel 53663aba447SAndreas Jaekel static void 53763aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 53863aba447SAndreas Jaekel { 53963aba447SAndreas Jaekel zev_print_znode_setattr(buf); 54063aba447SAndreas Jaekel } 54163aba447SAndreas Jaekel 54263aba447SAndreas Jaekel static void 5439193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 5449193e9c2SAndreas Jaekel { 54563aba447SAndreas Jaekel int record_len; 54663aba447SAndreas Jaekel int op; 5479193e9c2SAndreas Jaekel 54863aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 54963aba447SAndreas Jaekel if (record_len != len) { 55063aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 55163aba447SAndreas Jaekel record_len, len); 5529193e9c2SAndreas Jaekel exit(1); 5539193e9c2SAndreas Jaekel } 55463aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 5559193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 55663aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 5579193e9c2SAndreas Jaekel exit(1); 5589193e9c2SAndreas Jaekel } 55963aba447SAndreas Jaekel switch (op) { 56063aba447SAndreas Jaekel case ZEV_OP_ERROR: 56163aba447SAndreas Jaekel zev_print_error(buf); 5629193e9c2SAndreas Jaekel break; 56301c2c787SAndreas Jaekel case ZEV_OP_MARK: 56401c2c787SAndreas Jaekel zev_print_mark(buf); 56501c2c787SAndreas Jaekel break; 56663aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 56763aba447SAndreas Jaekel zev_print_zfs_mount(buf); 5689193e9c2SAndreas Jaekel break; 56963aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 57063aba447SAndreas Jaekel zev_print_zfs_umount(buf); 5719193e9c2SAndreas Jaekel break; 57263aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 57363aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 5749193e9c2SAndreas Jaekel break; 57563aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 57663aba447SAndreas Jaekel zev_print_zvol_write(buf); 57763aba447SAndreas Jaekel break; 57863aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 57963aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 58063aba447SAndreas Jaekel break; 58163aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 58263aba447SAndreas Jaekel zev_print_znode_create(buf); 58363aba447SAndreas Jaekel break; 58463aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 58563aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 58663aba447SAndreas Jaekel break; 58763aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 58863aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 58963aba447SAndreas Jaekel break; 59063aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 59163aba447SAndreas Jaekel zev_print_znode_remove(buf); 59263aba447SAndreas Jaekel break; 59363aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 59463aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 59563aba447SAndreas Jaekel break; 59663aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 59763aba447SAndreas Jaekel zev_print_znode_link(buf); 59863aba447SAndreas Jaekel break; 59963aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 60063aba447SAndreas Jaekel zev_print_znode_symlink(buf); 60163aba447SAndreas Jaekel break; 60263aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 60363aba447SAndreas Jaekel zev_print_znode_rename(buf); 60463aba447SAndreas Jaekel break; 60563aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 60663aba447SAndreas Jaekel zev_print_znode_write(buf); 60763aba447SAndreas Jaekel break; 60863aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 60963aba447SAndreas Jaekel zev_print_znode_truncate(buf); 61063aba447SAndreas Jaekel break; 61163aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 61263aba447SAndreas Jaekel zev_print_znode_setattr(buf); 61363aba447SAndreas Jaekel break; 61463aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 61563aba447SAndreas Jaekel zev_print_znode_acl(buf); 6169193e9c2SAndreas Jaekel break; 6179193e9c2SAndreas Jaekel default: 61863aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 6199193e9c2SAndreas Jaekel exit(1); 6209193e9c2SAndreas Jaekel } 6219193e9c2SAndreas Jaekel } 6229193e9c2SAndreas Jaekel 623e9a5e479SAndreas Jaekel static int 6244ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 6252bb8e5e2SAndreas Jaekel { 6262bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 6272bb8e5e2SAndreas Jaekel int ret; 6289193e9c2SAndreas Jaekel char buf[4096]; 62968a46c64SAndreas Jaekel zev_event_t *ev; 63068a46c64SAndreas Jaekel int off = 0; 631e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 632e9a5e479SAndreas Jaekel int q_fd; 633e9a5e479SAndreas Jaekel 6344ca7dd5eSAndreas Jaekel if (create_tmp_queue) { 635e9a5e479SAndreas Jaekel aq.zev_max_queue_len = 0; 636e9a5e479SAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 637e9a5e479SAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 638e9a5e479SAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 639e9a5e479SAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 640e9a5e479SAndreas Jaekel 641e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 642e9a5e479SAndreas Jaekel perror("adding temporary queue failed"); 643e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 644e9a5e479SAndreas Jaekel } 645e9a5e479SAndreas Jaekel 6464ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 6474ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 648e9a5e479SAndreas Jaekel q_fd = open(buf, O_RDONLY); 649e9a5e479SAndreas Jaekel if (q_fd < 0) { 650e9a5e479SAndreas Jaekel perror("opening queue device failed"); 651e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 652e9a5e479SAndreas Jaekel } 6534ca7dd5eSAndreas Jaekel } else { 6544ca7dd5eSAndreas Jaekel q_fd = fd; 6554ca7dd5eSAndreas Jaekel } 656e9a5e479SAndreas Jaekel 6572bb8e5e2SAndreas Jaekel while (1) { 658e9a5e479SAndreas Jaekel pfd[0].fd = q_fd; 6592bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 6602bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 6612bb8e5e2SAndreas Jaekel if (ret < 0) { 6622bb8e5e2SAndreas Jaekel perror("poll failed"); 6634ca7dd5eSAndreas Jaekel close(q_fd); 664e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 6652bb8e5e2SAndreas Jaekel } 6662bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 6672bb8e5e2SAndreas Jaekel continue; 6682bb8e5e2SAndreas Jaekel /* data available */ 669e9a5e479SAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 6702bb8e5e2SAndreas Jaekel if (ret < 0) { 6712bb8e5e2SAndreas Jaekel perror("read failed"); 6724ca7dd5eSAndreas Jaekel close(q_fd); 673e9a5e479SAndreas Jaekel return(EXIT_FAILURE); 6742bb8e5e2SAndreas Jaekel } 6752bb8e5e2SAndreas Jaekel if (ret == 0) 6762bb8e5e2SAndreas Jaekel continue; 67768a46c64SAndreas Jaekel while (ret > off) { 67868a46c64SAndreas Jaekel ev = (zev_event_t *)(buf + off); 67968a46c64SAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 68068a46c64SAndreas Jaekel off += ev->header.record_len; 68168a46c64SAndreas Jaekel } 682108668daSAndreas Jaekel off = 0; 6832bb8e5e2SAndreas Jaekel } 6844ca7dd5eSAndreas Jaekel if (create_tmp_queue) 685e9a5e479SAndreas Jaekel close(q_fd); 686e9a5e479SAndreas Jaekel return EXIT_SUCCESS; 6872bb8e5e2SAndreas Jaekel } 6882bb8e5e2SAndreas Jaekel 6892bb8e5e2SAndreas Jaekel static void 6902bb8e5e2SAndreas Jaekel usage(char *progname) 6912bb8e5e2SAndreas Jaekel { 692e9a5e479SAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 693e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 694e9a5e479SAndreas Jaekel fprintf(stderr, " Status information:\n"); 6952bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 6962bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 697e9a5e479SAndreas Jaekel fprintf(stderr, " -D print zev module debug " 698e9a5e479SAndreas Jaekel "information\n"); 699e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 700e9a5e479SAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 701e9a5e479SAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 702e9a5e479SAndreas Jaekel "length\n"); 703e9a5e479SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 704e9a5e479SAndreas Jaekel "this pool\n"); 7052bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 706e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 707e9a5e479SAndreas Jaekel fprintf(stderr, " Queue management:\n"); 708e9a5e479SAndreas Jaekel fprintf(stderr, " -l list queues\n"); 7094ca7dd5eSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 7104ca7dd5eSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 711e9a5e479SAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 712e9a5e479SAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 713e9a5e479SAndreas Jaekel "(default)\n"); 714e9a5e479SAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 715e9a5e479SAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 7164ca7dd5eSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 717e9a5e479SAndreas Jaekel "length\n"); 718e9a5e479SAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 719e9a5e479SAndreas Jaekel "throttle\n"); 720e9a5e479SAndreas Jaekel fprintf(stderr, "\n"); 721e9a5e479SAndreas Jaekel fprintf(stderr, " Other options:\n"); 722e9a5e479SAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 723e9a5e479SAndreas Jaekel "('%s')\n", ZEV_DEVICE); 7244ca7dd5eSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 7254ca7dd5eSAndreas Jaekel "queue name\n"); 72601c2c787SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 727b9710123SAndreas Jaekel fprintf(stderr, " -c <filename> list file's content " 728b9710123SAndreas Jaekel "checksums\n"); 729d65b2fffSAndreas Jaekel fprintf(stderr, " -v verbose: additional output " 7305e286361SAndreas Jaekel "for some operations\n"); 731d65b2fffSAndreas Jaekel fprintf(stderr, " -g grep-friendly event output, " 732d65b2fffSAndreas Jaekel "one event per line\n"); 7332bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 7342bb8e5e2SAndreas Jaekel } 7352bb8e5e2SAndreas Jaekel 7362bb8e5e2SAndreas Jaekel static int 7374ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 7382bb8e5e2SAndreas Jaekel { 739e9a5e479SAndreas Jaekel zev_ioctl_add_queue_t aq; 740e9a5e479SAndreas Jaekel int namelen; 7412bb8e5e2SAndreas Jaekel 742e9a5e479SAndreas Jaekel namelen = strlen(arg); 743e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 744e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 7452bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 7462bb8e5e2SAndreas Jaekel } 747e9a5e479SAndreas Jaekel 748e9a5e479SAndreas Jaekel aq.zev_namelen = namelen; 749e9a5e479SAndreas Jaekel strcpy(aq.zev_name, arg); 7504ca7dd5eSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 7514ca7dd5eSAndreas Jaekel if (blocking) { 7524ca7dd5eSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 7534ca7dd5eSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 7544ca7dd5eSAndreas Jaekel } else { 755e9a5e479SAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 7564ca7dd5eSAndreas Jaekel } 757e9a5e479SAndreas Jaekel 758e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 759e9a5e479SAndreas Jaekel perror("adding queue failed"); 7602bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 7612bb8e5e2SAndreas Jaekel } 7622bb8e5e2SAndreas Jaekel return (0); 7632bb8e5e2SAndreas Jaekel } 7642bb8e5e2SAndreas Jaekel 7652bb8e5e2SAndreas Jaekel static int 766e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg) 767205a9bc9SAndreas Jaekel { 768e9a5e479SAndreas Jaekel zev_ioctl_remove_queue_t aq; 769e9a5e479SAndreas Jaekel int namelen; 770205a9bc9SAndreas Jaekel 771e9a5e479SAndreas Jaekel namelen = strlen(arg); 772e9a5e479SAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 773e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 774205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 775205a9bc9SAndreas Jaekel } 776e9a5e479SAndreas Jaekel 7774ca7dd5eSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 7784ca7dd5eSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 779e9a5e479SAndreas Jaekel 780e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 781e9a5e479SAndreas Jaekel perror("removing queue failed"); 782e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 783e9a5e479SAndreas Jaekel } 784e9a5e479SAndreas Jaekel return (0); 785e9a5e479SAndreas Jaekel } 786e9a5e479SAndreas Jaekel 787e9a5e479SAndreas Jaekel static int 788e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 789e9a5e479SAndreas Jaekel { 790e9a5e479SAndreas Jaekel uint64_t maxqueuelen; 791e9a5e479SAndreas Jaekel 792e9a5e479SAndreas Jaekel errno = 0; 793e9a5e479SAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 794e9a5e479SAndreas Jaekel if (errno) { 795e9a5e479SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 796e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 797e9a5e479SAndreas Jaekel } 798e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 799e9a5e479SAndreas Jaekel perror("setting max queue length failed"); 800205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 801205a9bc9SAndreas Jaekel } 802205a9bc9SAndreas Jaekel return (0); 803205a9bc9SAndreas Jaekel } 804205a9bc9SAndreas Jaekel 805205a9bc9SAndreas Jaekel static int 8062bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 8072bb8e5e2SAndreas Jaekel { 8082bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 8092bb8e5e2SAndreas Jaekel int len; 8102bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 8112bb8e5e2SAndreas Jaekel len = strlen(poolname); 8122bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 8132bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 8142bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 8152bb8e5e2SAndreas Jaekel } 8162bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 8172bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 8182bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 8192bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 8202bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 8212bb8e5e2SAndreas Jaekel } 8222bb8e5e2SAndreas Jaekel return (0); 8232bb8e5e2SAndreas Jaekel } 8242bb8e5e2SAndreas Jaekel 8252bb8e5e2SAndreas Jaekel int 8262bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 8272bb8e5e2SAndreas Jaekel { 8282bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 8292bb8e5e2SAndreas Jaekel } 8302bb8e5e2SAndreas Jaekel 8312bb8e5e2SAndreas Jaekel int 8322bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 8332bb8e5e2SAndreas Jaekel { 8342bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 8352bb8e5e2SAndreas Jaekel } 8362bb8e5e2SAndreas Jaekel 83701c2c787SAndreas Jaekel static int 838e9a5e479SAndreas Jaekel zev_debug_info(int fd) 839e9a5e479SAndreas Jaekel { 840e9a5e479SAndreas Jaekel zev_ioctl_debug_info_t di; 841e9a5e479SAndreas Jaekel 842e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 843e9a5e479SAndreas Jaekel perror("getting zev debug info failed"); 844e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 845e9a5e479SAndreas Jaekel } 846e9a5e479SAndreas Jaekel 847e9a5e479SAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 8485e286361SAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 8495e286361SAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 8505e286361SAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 851e9a5e479SAndreas Jaekel return 0; 852e9a5e479SAndreas Jaekel } 853e9a5e479SAndreas Jaekel 854e9a5e479SAndreas Jaekel static int 85501c2c787SAndreas Jaekel zev_mark(int fd, char *arg) 85601c2c787SAndreas Jaekel { 85701c2c787SAndreas Jaekel zev_ioctl_mark_t *mark; 85801c2c787SAndreas Jaekel uint64_t guid; 85901c2c787SAndreas Jaekel int len; 86001c2c787SAndreas Jaekel char *p; 86101c2c787SAndreas Jaekel 86201c2c787SAndreas Jaekel p = strchr(arg, ':'); 86301c2c787SAndreas Jaekel if (!p) { 86401c2c787SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 86501c2c787SAndreas Jaekel "e.g. '123:hello'\n"); 86601c2c787SAndreas Jaekel exit (EXIT_FAILURE); 86701c2c787SAndreas Jaekel } 86801c2c787SAndreas Jaekel *p = '\n'; 86901c2c787SAndreas Jaekel p++; 87001c2c787SAndreas Jaekel 87101c2c787SAndreas Jaekel errno = 0; 872e9a5e479SAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 87301c2c787SAndreas Jaekel if (errno) { 87401c2c787SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 87501c2c787SAndreas Jaekel exit (EXIT_FAILURE); 87601c2c787SAndreas Jaekel } 87701c2c787SAndreas Jaekel 87801c2c787SAndreas Jaekel len = strlen(p); 87901c2c787SAndreas Jaekel 88001c2c787SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 88101c2c787SAndreas Jaekel if (!mark) { 88201c2c787SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 88301c2c787SAndreas Jaekel strerror(errno)); 88401c2c787SAndreas Jaekel exit (EXIT_FAILURE); 88501c2c787SAndreas Jaekel } 88601c2c787SAndreas Jaekel mark->zev_guid = guid; 88701c2c787SAndreas Jaekel mark->zev_mark_id = 0; 88801c2c787SAndreas Jaekel mark->zev_payload_len = len; 88901c2c787SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 89001c2c787SAndreas Jaekel 89101c2c787SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 89201c2c787SAndreas Jaekel perror("queueing mark failed"); 89301c2c787SAndreas Jaekel return (EXIT_FAILURE); 89401c2c787SAndreas Jaekel } 89501c2c787SAndreas Jaekel 89601c2c787SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 89701c2c787SAndreas Jaekel return (0); 89801c2c787SAndreas Jaekel } 89901c2c787SAndreas Jaekel 900e9a5e479SAndreas Jaekel static int 901e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 902e9a5e479SAndreas Jaekel { 903e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 904e9a5e479SAndreas Jaekel 9054ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9064ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 907e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 908e9a5e479SAndreas Jaekel return EXIT_FAILURE; 909e9a5e479SAndreas Jaekel } 9104ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 911e9a5e479SAndreas Jaekel 912e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 913e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 914e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 915e9a5e479SAndreas Jaekel } 916e9a5e479SAndreas Jaekel if (block) { 917e9a5e479SAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 918e9a5e479SAndreas Jaekel } else { 919e9a5e479SAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 920e9a5e479SAndreas Jaekel } 921e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 922e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 923e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 924e9a5e479SAndreas Jaekel } 925e9a5e479SAndreas Jaekel return (0); 926e9a5e479SAndreas Jaekel } 927e9a5e479SAndreas Jaekel 928e9a5e479SAndreas Jaekel static int 929e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 930e9a5e479SAndreas Jaekel { 931e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 932e9a5e479SAndreas Jaekel 933e9a5e479SAndreas Jaekel if (!len) { 934e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 935e9a5e479SAndreas Jaekel return EXIT_FAILURE; 936e9a5e479SAndreas Jaekel } 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 gqp.zev_max_queue_len = atol(len); 950e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 951e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 952e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 953e9a5e479SAndreas Jaekel } 954e9a5e479SAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 955e9a5e479SAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 956e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 957e9a5e479SAndreas Jaekel } 958e9a5e479SAndreas Jaekel 959e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 960e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 961e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 962e9a5e479SAndreas Jaekel } 963e9a5e479SAndreas Jaekel return (0); 964e9a5e479SAndreas Jaekel } 965e9a5e479SAndreas Jaekel 966e9a5e479SAndreas Jaekel static int 967e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 968e9a5e479SAndreas Jaekel { 969e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 970e9a5e479SAndreas Jaekel 971e9a5e479SAndreas Jaekel if (!len) { 972e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 973e9a5e479SAndreas Jaekel return EXIT_FAILURE; 974e9a5e479SAndreas Jaekel } 975e9a5e479SAndreas Jaekel 9764ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9774ca7dd5eSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 978e9a5e479SAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 979e9a5e479SAndreas Jaekel return EXIT_FAILURE; 980e9a5e479SAndreas Jaekel } 9814ca7dd5eSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 982e9a5e479SAndreas Jaekel 983e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 984e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 985e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 986e9a5e479SAndreas Jaekel } 987e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 988e9a5e479SAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 989e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 990e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 991e9a5e479SAndreas Jaekel } 9924ca7dd5eSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 993e9a5e479SAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 994e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 995e9a5e479SAndreas Jaekel } 996e9a5e479SAndreas Jaekel 997e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 998e9a5e479SAndreas Jaekel perror("setting queue properties failed"); 999e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1000e9a5e479SAndreas Jaekel } 1001e9a5e479SAndreas Jaekel return (0); 1002e9a5e479SAndreas Jaekel } 1003e9a5e479SAndreas Jaekel 1004e9a5e479SAndreas Jaekel static int 1005e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg) 1006e9a5e479SAndreas Jaekel { 1007e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 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 1021e9a5e479SAndreas Jaekel printf("queue : %s\n", arg); 1022e9a5e479SAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1023e9a5e479SAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1024e9a5e479SAndreas Jaekel printf("persistent : %s\n", 1025e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1026e9a5e479SAndreas Jaekel printf("blocking : %s\n", 1027e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1028e9a5e479SAndreas Jaekel 1029e9a5e479SAndreas Jaekel return (0); 1030e9a5e479SAndreas Jaekel } 1031e9a5e479SAndreas Jaekel 1032e9a5e479SAndreas Jaekel static int 1033e9a5e479SAndreas Jaekel zev_list_queues(int fd) 1034e9a5e479SAndreas Jaekel { 1035e9a5e479SAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1036e9a5e479SAndreas Jaekel zev_ioctl_get_queue_list_t gql; 1037e9a5e479SAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 1038e9a5e479SAndreas Jaekel uint64_t i; 1039e9a5e479SAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1040e9a5e479SAndreas Jaekel 1041e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1042e9a5e479SAndreas Jaekel perror("getting queue list failed"); 1043e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1044e9a5e479SAndreas Jaekel } 1045e9a5e479SAndreas Jaekel 1046e9a5e479SAndreas Jaekel printf("Name Size " 1047e9a5e479SAndreas Jaekel "Max Size Wakeup Per Block\n"); 1048e9a5e479SAndreas Jaekel 1049e9a5e479SAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 1050e9a5e479SAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 1051e9a5e479SAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 1052e9a5e479SAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1053e9a5e479SAndreas Jaekel 10544ca7dd5eSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 10554ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10564ca7dd5eSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 10574ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1058e9a5e479SAndreas Jaekel 1059e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1060e9a5e479SAndreas Jaekel if (errno == ENOENT) 1061e9a5e479SAndreas Jaekel continue; 1062e9a5e479SAndreas Jaekel perror("getting queue properties failed"); 1063e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1064e9a5e479SAndreas Jaekel } 1065e9a5e479SAndreas Jaekel 10664ca7dd5eSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 10674ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10684ca7dd5eSAndreas Jaekel gs.zev_queue_name.zev_namelen = 10694ca7dd5eSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1070e9a5e479SAndreas Jaekel 1071e9a5e479SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1072e9a5e479SAndreas Jaekel if (errno == ENOENT) 1073e9a5e479SAndreas Jaekel continue; 1074e9a5e479SAndreas Jaekel perror("getting statistics data failed"); 1075e9a5e479SAndreas Jaekel return (EXIT_FAILURE); 1076e9a5e479SAndreas Jaekel } 1077e9a5e479SAndreas Jaekel 1078e9a5e479SAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1079e9a5e479SAndreas Jaekel " %-3s %-3s\n", 1080e9a5e479SAndreas Jaekel name, 1081e9a5e479SAndreas Jaekel gs.zev_statistics.zev_queue_len, 1082e9a5e479SAndreas Jaekel gqp.zev_max_queue_len, 1083e9a5e479SAndreas Jaekel gqp.zev_poll_wakeup_threshold, 1084e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1085e9a5e479SAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1086e9a5e479SAndreas Jaekel "yes" : "no"); 1087e9a5e479SAndreas Jaekel } 1088e9a5e479SAndreas Jaekel 1089e9a5e479SAndreas Jaekel return (0); 1090e9a5e479SAndreas Jaekel } 1091e9a5e479SAndreas Jaekel 1092b9710123SAndreas Jaekel static int 1093b9710123SAndreas Jaekel zev_checksum(int dev_fd, char *filename) 1094b9710123SAndreas Jaekel { 1095b9710123SAndreas Jaekel int fd; 1096b9710123SAndreas Jaekel offset_t off; 1097b9710123SAndreas Jaekel offset_t data; 1098b9710123SAndreas Jaekel zev_sig_t *sig; 1099b9710123SAndreas Jaekel char *buf; 1100b9710123SAndreas Jaekel zev_ioctl_get_signatures_t *gs; 1101b9710123SAndreas Jaekel int i; 1102b9710123SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 1103b9710123SAndreas Jaekel int buf_size; 1104b9710123SAndreas Jaekel 1105b9710123SAndreas Jaekel /* control struct, one lv1 signature and up to 256 lv0 signatures */ 1106b9710123SAndreas Jaekel buf_size = (1 + 256) * sizeof(zev_sig_t); 1107b9710123SAndreas Jaekel buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 1108b9710123SAndreas Jaekel if (!buf) { 1109b9710123SAndreas Jaekel perror("can't allocate checksum buffer"); 1110b9710123SAndreas Jaekel return (EXIT_FAILURE); 1111b9710123SAndreas Jaekel } 1112b9710123SAndreas Jaekel 1113b9710123SAndreas Jaekel fd = open(filename, O_RDONLY); 1114b9710123SAndreas Jaekel if (fd < 0) { 1115b9710123SAndreas Jaekel perror("can't open file"); 1116b9710123SAndreas Jaekel return (EXIT_FAILURE); 1117b9710123SAndreas Jaekel } 1118b9710123SAndreas Jaekel 1119b9710123SAndreas Jaekel gs = (zev_ioctl_get_signatures_t *)buf; 1120b9710123SAndreas Jaekel gs->zev_fd = fd; 1121b9710123SAndreas Jaekel gs->zev_bufsize = buf_size; 1122b9710123SAndreas Jaekel 1123b9710123SAndreas Jaekel off = 0; 1124b9710123SAndreas Jaekel data = 0; 1125b9710123SAndreas Jaekel while (1) { 1126b9710123SAndreas Jaekel errno = 0; 1127b9710123SAndreas Jaekel data = llseek(fd, off, SEEK_DATA); 1128b9710123SAndreas Jaekel if (data < 0) { 1129b9710123SAndreas Jaekel if (errno == ENXIO) /* no more data */ 1130b9710123SAndreas Jaekel break; 1131b9710123SAndreas Jaekel perror("llseek failed"); 1132b9710123SAndreas Jaekel goto err; 1133b9710123SAndreas Jaekel } 1134b9710123SAndreas Jaekel data = P2ALIGN(data, ZEV_L1_SIZE); 1135b9710123SAndreas Jaekel off = data + ZEV_L1_SIZE; 1136b9710123SAndreas Jaekel 1137b9710123SAndreas Jaekel gs->zev_offset = data; 1138b9710123SAndreas Jaekel gs->zev_len = ZEV_L1_SIZE; 1139b9710123SAndreas Jaekel 1140b9710123SAndreas Jaekel if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 1141b9710123SAndreas Jaekel perror("ioctl to get signatures failed"); 1142b9710123SAndreas Jaekel goto err; 1143b9710123SAndreas Jaekel } 1144b9710123SAndreas Jaekel 1145b9710123SAndreas Jaekel for (i=0; i<gs->zev_signature_cnt; i++) { 1146b9710123SAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 1147b9710123SAndreas Jaekel sig += i; 1148b9710123SAndreas Jaekel sig2hex_direct(sig->value, sigval); 1149b9710123SAndreas Jaekel printf("level %d, offset %llu, value %s\n", 1150b9710123SAndreas Jaekel sig->level, sig->block_offset, sigval); 1151b9710123SAndreas Jaekel } 1152b9710123SAndreas Jaekel } 1153b9710123SAndreas Jaekel 1154b9710123SAndreas Jaekel free(buf); 1155b9710123SAndreas Jaekel close(fd); 1156b9710123SAndreas Jaekel return 0; 1157b9710123SAndreas Jaekel err: 1158b9710123SAndreas Jaekel free(buf); 1159b9710123SAndreas Jaekel close(fd); 1160b9710123SAndreas Jaekel return (EXIT_FAILURE); 1161b9710123SAndreas Jaekel } 1162b9710123SAndreas Jaekel 11632bb8e5e2SAndreas Jaekel int 11642bb8e5e2SAndreas Jaekel main(int argc, char **argv) 11652bb8e5e2SAndreas Jaekel { 11662bb8e5e2SAndreas Jaekel int fd; 11672bb8e5e2SAndreas Jaekel int c; 11682bb8e5e2SAndreas Jaekel extern char *optarg; 11694ca7dd5eSAndreas Jaekel int create_tmp_queue = 1; 11704ca7dd5eSAndreas Jaekel char buf[MAXPATHLEN]; 11712bb8e5e2SAndreas Jaekel 11722bb8e5e2SAndreas Jaekel /* open device */ 11732bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 11742bb8e5e2SAndreas Jaekel if (fd < 0) { 11752bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 11762bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 11772bb8e5e2SAndreas Jaekel } 11784ca7dd5eSAndreas Jaekel while ((c = getopt(argc, argv, 1179d65b2fffSAndreas Jaekel "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 11802bb8e5e2SAndreas Jaekel switch(c) { 1181d65b2fffSAndreas Jaekel case 'g': 1182d65b2fffSAndreas Jaekel grep_friendly++; 1183d65b2fffSAndreas Jaekel verbose++; 1184d65b2fffSAndreas Jaekel break; 11855e286361SAndreas Jaekel case 'v': 11865e286361SAndreas Jaekel verbose++; 11875e286361SAndreas Jaekel break; 11882bb8e5e2SAndreas Jaekel case 's': 1189e9a5e479SAndreas Jaekel return zev_statistics(fd); 11902bb8e5e2SAndreas Jaekel case 'p': 11914ca7dd5eSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 1192b9710123SAndreas Jaekel case 'c': 1193b9710123SAndreas Jaekel return zev_checksum(fd, optarg); 1194e9a5e479SAndreas Jaekel case 'D': 1195e9a5e479SAndreas Jaekel return zev_debug_info(fd); 11962bb8e5e2SAndreas Jaekel case 'd': 1197e9a5e479SAndreas Jaekel close(fd); 11982bb8e5e2SAndreas Jaekel zev_device = optarg; 1199e9a5e479SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1200e9a5e479SAndreas Jaekel if (fd < 0) { 1201e9a5e479SAndreas Jaekel perror("opening zev device failed"); 1202e9a5e479SAndreas Jaekel return EXIT_FAILURE; 1203e9a5e479SAndreas Jaekel } 12044ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 12054ca7dd5eSAndreas Jaekel break; 12064ca7dd5eSAndreas Jaekel case 'q': 12074ca7dd5eSAndreas Jaekel snprintf(buf, sizeof(buf), 12084ca7dd5eSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 12094ca7dd5eSAndreas Jaekel close(fd); 12104ca7dd5eSAndreas Jaekel zev_device = buf; 12114ca7dd5eSAndreas Jaekel fd = open(zev_device, O_RDONLY); 12124ca7dd5eSAndreas Jaekel if (fd < 0) { 12134ca7dd5eSAndreas Jaekel perror("opening zev device failed"); 12144ca7dd5eSAndreas Jaekel return EXIT_FAILURE; 12154ca7dd5eSAndreas Jaekel } 12164ca7dd5eSAndreas Jaekel create_tmp_queue = 0; 12172bb8e5e2SAndreas Jaekel break; 1218e9a5e479SAndreas Jaekel case 'l': 1219e9a5e479SAndreas Jaekel return zev_list_queues(fd); 1220e9a5e479SAndreas Jaekel case 'Q': 1221e9a5e479SAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 12224ca7dd5eSAndreas Jaekel case 'L': 1223e9a5e479SAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 1224205a9bc9SAndreas Jaekel case 't': 1225e9a5e479SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 1226e9a5e479SAndreas Jaekel argv[optind]); 12272bb8e5e2SAndreas Jaekel case 'm': 12282bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 12292bb8e5e2SAndreas Jaekel case 'M': 12302bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 123101c2c787SAndreas Jaekel case 'k': 123201c2c787SAndreas Jaekel return zev_mark(fd, optarg); 1233e9a5e479SAndreas Jaekel case 'a': 12344ca7dd5eSAndreas Jaekel return zev_add_queue(fd, optarg, 0); 12354ca7dd5eSAndreas Jaekel case 'A': 12364ca7dd5eSAndreas Jaekel return zev_add_queue(fd, optarg, 1); 1237e9a5e479SAndreas Jaekel case 'r': 1238e9a5e479SAndreas Jaekel return zev_remove_queue(fd, optarg); 1239e9a5e479SAndreas Jaekel case 'b': 1240e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 1241e9a5e479SAndreas Jaekel case 'B': 1242e9a5e479SAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 1243e9a5e479SAndreas Jaekel case 'P': 1244e9a5e479SAndreas Jaekel return zev_queue_properties(fd, optarg); 12452bb8e5e2SAndreas Jaekel case 'h': 12462bb8e5e2SAndreas Jaekel case '?': 12472bb8e5e2SAndreas Jaekel default: 12482bb8e5e2SAndreas Jaekel usage(argv[0]); 12492bb8e5e2SAndreas Jaekel } 12502bb8e5e2SAndreas Jaekel } 12512bb8e5e2SAndreas Jaekel usage(argv[0]); 12522bb8e5e2SAndreas Jaekel close(fd); 1253e9a5e479SAndreas Jaekel return EXIT_FAILURE; 12542bb8e5e2SAndreas Jaekel } 12552bb8e5e2SAndreas Jaekel 1256