1a18c35b9SAndreas Jaekel #include <stdio.h> 2a18c35b9SAndreas Jaekel #include <unistd.h> 3a18c35b9SAndreas Jaekel #include <stdlib.h> 4a18c35b9SAndreas Jaekel #include <fcntl.h> 5a18c35b9SAndreas Jaekel #include <stropts.h> 6a18c35b9SAndreas Jaekel #include <poll.h> 7a18c35b9SAndreas Jaekel #include <string.h> 8a18c35b9SAndreas Jaekel #include <sys/fs/zev.h> 9a18c35b9SAndreas Jaekel #include <errno.h> 1042110aacSAndreas Jaekel #include <sys/sysmacros.h> 1116ff6b2fSAndreas Jaekel #include <stdarg.h> 12a18c35b9SAndreas Jaekel 13add9520fSAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 14a18c35b9SAndreas Jaekel 15a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 16a18c35b9SAndreas Jaekel 17aafc540fSAndreas Jaekel static char *zev_op_name[] = { 1816ff6b2fSAndreas Jaekel "ERROR", 1916ff6b2fSAndreas Jaekel "MARK", 2016ff6b2fSAndreas Jaekel "ZFS_MOUNT", 2116ff6b2fSAndreas Jaekel "ZFS_UMOUNT", 2216ff6b2fSAndreas Jaekel "ZVOL_WRITE", 2316ff6b2fSAndreas Jaekel "ZVOL_TRUNCATE", 2416ff6b2fSAndreas Jaekel "ZNODE_CLOSE_AFTER_UPDATE", 2516ff6b2fSAndreas Jaekel "ZNODE_CREATE", 2616ff6b2fSAndreas Jaekel "ZNODE_MKDIR", 2716ff6b2fSAndreas Jaekel "ZNODE_MAKE_XATTR_DIR", 2816ff6b2fSAndreas Jaekel "ZNODE_REMOVE", 2916ff6b2fSAndreas Jaekel "ZNODE_RMDIR", 3016ff6b2fSAndreas Jaekel "ZNODE_LINK", 3116ff6b2fSAndreas Jaekel "ZNODE_SYMLINK", 3216ff6b2fSAndreas Jaekel "ZNODE_RENAME", 3316ff6b2fSAndreas Jaekel "ZNODE_WRITE", 3416ff6b2fSAndreas Jaekel "ZNODE_TRUNCATE", 3516ff6b2fSAndreas Jaekel "ZNODE_SETATTR", 3616ff6b2fSAndreas Jaekel "ZNODE_ACL", 37aafc540fSAndreas Jaekel NULL 38aafc540fSAndreas Jaekel }; 39aafc540fSAndreas Jaekel 40*a5090b97SAndreas Jaekel #define MD_STATISTICS 1 41*a5090b97SAndreas Jaekel #define MD_POLL_EVENTS 2 42*a5090b97SAndreas Jaekel #define MD_CHECKSUMS 3 43*a5090b97SAndreas Jaekel #define MD_DEBUG_INFO 4 44*a5090b97SAndreas Jaekel #define MD_LIST_QUEUES 5 45*a5090b97SAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN 6 46*a5090b97SAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN 7 47*a5090b97SAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN 8 48*a5090b97SAndreas Jaekel #define MD_MUTE_POOL 9 49*a5090b97SAndreas Jaekel #define MD_UNMUTE_POOL 10 50*a5090b97SAndreas Jaekel #define MD_MARK 11 51*a5090b97SAndreas Jaekel #define MD_ADD_QUEUE 12 52*a5090b97SAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE 13 53*a5090b97SAndreas Jaekel #define MD_REMOVE_QUEUE 14 54*a5090b97SAndreas Jaekel #define MD_QUEUE_BLOCKING 15 55*a5090b97SAndreas Jaekel #define MD_QUEUE_NONBLOCKING 16 56*a5090b97SAndreas Jaekel #define MD_QUEUE_PROPERTIES 17 57*a5090b97SAndreas Jaekel 58205ed6bfSAndreas Jaekel static int verbose = 0; 5916ff6b2fSAndreas Jaekel static int grep_friendly = 0; 6016ff6b2fSAndreas Jaekel 6116ff6b2fSAndreas Jaekel static void 6216ff6b2fSAndreas Jaekel zpf(char *fmt, ...) 6316ff6b2fSAndreas Jaekel { 6416ff6b2fSAndreas Jaekel va_list ap; 6516ff6b2fSAndreas Jaekel 6616ff6b2fSAndreas Jaekel va_start(ap, fmt); 6716ff6b2fSAndreas Jaekel vprintf(fmt, ap); 6816ff6b2fSAndreas Jaekel va_end(ap); 6916ff6b2fSAndreas Jaekel if (grep_friendly) { 7016ff6b2fSAndreas Jaekel printf(" "); 7116ff6b2fSAndreas Jaekel } else { 7216ff6b2fSAndreas Jaekel printf("\n"); 7316ff6b2fSAndreas Jaekel } 7416ff6b2fSAndreas Jaekel } 7516ff6b2fSAndreas Jaekel 7616ff6b2fSAndreas Jaekel static void 7716ff6b2fSAndreas Jaekel znl(void) 7816ff6b2fSAndreas Jaekel { 7916ff6b2fSAndreas Jaekel if (grep_friendly) 8016ff6b2fSAndreas Jaekel printf("\n"); 8116ff6b2fSAndreas Jaekel } 82205ed6bfSAndreas Jaekel 832eabeab5SAndreas Jaekel static void 842eabeab5SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 852eabeab5SAndreas Jaekel { 862eabeab5SAndreas Jaekel int i; 872eabeab5SAndreas Jaekel 882eabeab5SAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 892eabeab5SAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 902eabeab5SAndreas Jaekel } 912eabeab5SAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 922eabeab5SAndreas Jaekel } 932eabeab5SAndreas Jaekel 94add9520fSAndreas Jaekel static int 95a18c35b9SAndreas Jaekel zev_statistics(int fd) 96a18c35b9SAndreas Jaekel { 97a18c35b9SAndreas Jaekel zev_statistics_t zs; 98add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 99a18c35b9SAndreas Jaekel perror("getting statistics data failed"); 100add9520fSAndreas Jaekel return (EXIT_FAILURE); 101a18c35b9SAndreas Jaekel } 102a18c35b9SAndreas Jaekel printf("ZEV module state:\n"); 103a18c35b9SAndreas Jaekel 104a18c35b9SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 105a18c35b9SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 106a18c35b9SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 107a18c35b9SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 108a18c35b9SAndreas Jaekel 109add9520fSAndreas Jaekel printf(" discarded events : %lu\n", 110add9520fSAndreas Jaekel zs.zev_cnt_discarded_events); 111add9520fSAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 112add9520fSAndreas Jaekel 113a18c35b9SAndreas Jaekel printf("ZFS event statistics:\n"); 114a18c35b9SAndreas Jaekel 115a18c35b9SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 116a18c35b9SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 117a18c35b9SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 118a18c35b9SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 119a18c35b9SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 120a18c35b9SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 121a18c35b9SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 122a18c35b9SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 123a18c35b9SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 124a18c35b9SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 125a18c35b9SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 126a18c35b9SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 127a18c35b9SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 128a18c35b9SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 129a18c35b9SAndreas Jaekel zs.zev_cnt_znode_truncate); 130a18c35b9SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 131a18c35b9SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 132add9520fSAndreas Jaekel return EXIT_SUCCESS; 133a18c35b9SAndreas Jaekel } 134a18c35b9SAndreas Jaekel 135a18c35b9SAndreas Jaekel static void 13616ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info) 13716ff6b2fSAndreas Jaekel { 13816ff6b2fSAndreas Jaekel zpf(" %s.inode: %llu", name, info->ino); 13916ff6b2fSAndreas Jaekel zpf(" %s.gen: %llu", name, info->gen); 14016ff6b2fSAndreas Jaekel zpf(" %s.mtime: %llu", name, info->mtime); 14116ff6b2fSAndreas Jaekel zpf(" %s.ctime: %llu", name, info->ctime); 14216ff6b2fSAndreas Jaekel zpf(" %s.size: %llu", name, info->size); 14316ff6b2fSAndreas Jaekel zpf(" %s.mode: %llo", name, info->mode); 14416ff6b2fSAndreas Jaekel zpf(" %s.links: %llu", name, info->links); 14516ff6b2fSAndreas Jaekel zpf(" %s.type: %lu", name, info->type); 14616ff6b2fSAndreas Jaekel zpf(" %s.flags: %lu", name, info->flags); 14716ff6b2fSAndreas Jaekel } 14816ff6b2fSAndreas Jaekel 14916ff6b2fSAndreas Jaekel static void 15016ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec) 15116ff6b2fSAndreas Jaekel { 15216ff6b2fSAndreas Jaekel int i; 15316ff6b2fSAndreas Jaekel int j; 15416ff6b2fSAndreas Jaekel uint8_t *p; 15516ff6b2fSAndreas Jaekel char c; 15616ff6b2fSAndreas Jaekel 15716ff6b2fSAndreas Jaekel zpf(" payload:"); 15816ff6b2fSAndreas Jaekel p = (uint8_t *)ZEV_PAYLOAD(rec); 15916ff6b2fSAndreas Jaekel for (i=0; i<rec->payload_len; i+=16) { 16016ff6b2fSAndreas Jaekel printf(" "); 16116ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 16216ff6b2fSAndreas Jaekel printf("%02x ", p[j]); 16316ff6b2fSAndreas Jaekel if (j == i + 7) 16416ff6b2fSAndreas Jaekel printf(" "); 16516ff6b2fSAndreas Jaekel } 16616ff6b2fSAndreas Jaekel if (grep_friendly) 16716ff6b2fSAndreas Jaekel continue; 16816ff6b2fSAndreas Jaekel for (; j<i+16; j++) { 16916ff6b2fSAndreas Jaekel printf(" "); 17016ff6b2fSAndreas Jaekel if (j == i + 7) 17116ff6b2fSAndreas Jaekel printf(" "); 17216ff6b2fSAndreas Jaekel } 17316ff6b2fSAndreas Jaekel printf(" "); 17416ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 17516ff6b2fSAndreas Jaekel c = '.'; 17616ff6b2fSAndreas Jaekel if (p[j] >= ' ' && p[j] <= '~') 17716ff6b2fSAndreas Jaekel c = p[j]; 17816ff6b2fSAndreas Jaekel printf("%c", c); 17916ff6b2fSAndreas Jaekel if (j == i + 7) 18016ff6b2fSAndreas Jaekel printf(" "); 18116ff6b2fSAndreas Jaekel } 18216ff6b2fSAndreas Jaekel printf("\n"); 18316ff6b2fSAndreas Jaekel } 18416ff6b2fSAndreas Jaekel } 18516ff6b2fSAndreas Jaekel 18616ff6b2fSAndreas Jaekel static void 187f2dd45e5SAndreas Jaekel zev_print_error(char *buf) 188f2dd45e5SAndreas Jaekel { 189f2dd45e5SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 190f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 191f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 192f2dd45e5SAndreas Jaekel 19316ff6b2fSAndreas Jaekel if (verbose) { 19416ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 19516ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 19616ff6b2fSAndreas Jaekel zpf(" failed.op: %s", 19716ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN]); 19816ff6b2fSAndreas Jaekel zpf(" message: %s", ZEV_ERRSTR(rec)); 19916ff6b2fSAndreas Jaekel znl(); 20016ff6b2fSAndreas Jaekel } else { 201f2dd45e5SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 202f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 20316ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], 20416ff6b2fSAndreas Jaekel ZEV_ERRSTR(rec)); 20516ff6b2fSAndreas Jaekel } 206f2dd45e5SAndreas Jaekel } 207f2dd45e5SAndreas Jaekel 208f2dd45e5SAndreas Jaekel static void 209888fea18SAndreas Jaekel zev_print_mark(char *buf) 210888fea18SAndreas Jaekel { 211888fea18SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 212888fea18SAndreas Jaekel time_t op_time = rec->op_time; 213888fea18SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 214888fea18SAndreas Jaekel 21516ff6b2fSAndreas Jaekel if (verbose) { 21616ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 21716ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 21816ff6b2fSAndreas Jaekel zpf(" mark.id: %llu", rec->mark_id); 21916ff6b2fSAndreas Jaekel zpf(" payload.len: %llu", rec->payload_len); 22016ff6b2fSAndreas Jaekel if (rec->payload_len) 22116ff6b2fSAndreas Jaekel zev_print_mark_payload(rec); 22216ff6b2fSAndreas Jaekel znl(); 22316ff6b2fSAndreas Jaekel } else { 224888fea18SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 22516ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 22616ff6b2fSAndreas Jaekel rec->mark_id, rec->payload_len); 22716ff6b2fSAndreas Jaekel } 228888fea18SAndreas Jaekel } 229888fea18SAndreas Jaekel 230888fea18SAndreas Jaekel static void 231f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf) 232f2dd45e5SAndreas Jaekel { 233f2dd45e5SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 234f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 235f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 236f2dd45e5SAndreas Jaekel 23716ff6b2fSAndreas Jaekel if (verbose) { 23816ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 23916ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 24016ff6b2fSAndreas Jaekel zpf(" dataset: %s", ZEV_DATASET(rec)); 24116ff6b2fSAndreas Jaekel zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 24216ff6b2fSAndreas Jaekel zpf(" remount: %s", rec->remount ? "true" : "false"); 24316ff6b2fSAndreas Jaekel zev_print_inode_info("root", &rec->root); 24416ff6b2fSAndreas Jaekel znl(); 24516ff6b2fSAndreas Jaekel } else { 24616ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' " 24716ff6b2fSAndreas Jaekel "mountpoint='%s'\n", 248f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 249f2dd45e5SAndreas Jaekel rec->guid, 250f2dd45e5SAndreas Jaekel rec->remount ? "true" : "false", 251f2dd45e5SAndreas Jaekel ZEV_DATASET(rec), 252f2dd45e5SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 253f2dd45e5SAndreas Jaekel } 25416ff6b2fSAndreas Jaekel } 255f2dd45e5SAndreas Jaekel 256f2dd45e5SAndreas Jaekel static void 257f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf) 258f2dd45e5SAndreas Jaekel { 259f2dd45e5SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 260f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 261f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 262f2dd45e5SAndreas Jaekel 26316ff6b2fSAndreas Jaekel if (verbose) { 26416ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 26516ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 26616ff6b2fSAndreas Jaekel znl(); 26716ff6b2fSAndreas Jaekel } else { 268f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu\n", 269f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 270f2dd45e5SAndreas Jaekel rec->guid); 271f2dd45e5SAndreas Jaekel } 27216ff6b2fSAndreas Jaekel } 273f2dd45e5SAndreas Jaekel 274f2dd45e5SAndreas Jaekel static void 275f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf) 276f2dd45e5SAndreas Jaekel { 277f2dd45e5SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 278f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 279f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 280f2dd45e5SAndreas Jaekel 28116ff6b2fSAndreas Jaekel if (verbose) { 28216ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 28316ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 28412119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 28516ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 28616ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 28716ff6b2fSAndreas Jaekel znl(); 28816ff6b2fSAndreas Jaekel } else { 289f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 290f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 291f2dd45e5SAndreas Jaekel rec->guid, 292f2dd45e5SAndreas Jaekel rec->offset, 293f2dd45e5SAndreas Jaekel rec->length); 294f2dd45e5SAndreas Jaekel } 29516ff6b2fSAndreas Jaekel } 296f2dd45e5SAndreas Jaekel 297f2dd45e5SAndreas Jaekel static void 298f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf) 299f2dd45e5SAndreas Jaekel { 300f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 301f2dd45e5SAndreas Jaekel } 302f2dd45e5SAndreas Jaekel 303f2dd45e5SAndreas Jaekel static void 304f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 305f2dd45e5SAndreas Jaekel { 306f2dd45e5SAndreas Jaekel zev_znode_close_after_update_t *rec = 307f2dd45e5SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 308f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 309f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 310f2dd45e5SAndreas Jaekel 31116ff6b2fSAndreas Jaekel if (verbose) { 31216ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 31316ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 31416ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 31516ff6b2fSAndreas Jaekel znl(); 31616ff6b2fSAndreas Jaekel } else { 317f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 318f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 319f2dd45e5SAndreas Jaekel rec->guid, 320f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 321f2dd45e5SAndreas Jaekel } 32216ff6b2fSAndreas Jaekel } 323f2dd45e5SAndreas Jaekel 324f2dd45e5SAndreas Jaekel static void 325f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf) 326f2dd45e5SAndreas Jaekel { 327f2dd45e5SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 328f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 329f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 3302eabeab5SAndreas Jaekel zev_sig_t *sig; 3312eabeab5SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 332f2dd45e5SAndreas Jaekel 33316ff6b2fSAndreas Jaekel if (verbose) { 33416ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 33516ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 33612119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 33716ff6b2fSAndreas Jaekel zpf(" name: '%s'", ZEV_NAME(rec)); 3382eabeab5SAndreas Jaekel sig = &rec->signature; 3392eabeab5SAndreas Jaekel sig2hex_direct(sig->value, sigval); 3402eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 3412eabeab5SAndreas Jaekel sig->level, sig->block_offset, sigval); 34216ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 34312119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 34416ff6b2fSAndreas Jaekel znl(); 34516ff6b2fSAndreas Jaekel } else { 34635d4e8ddSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 34735d4e8ddSAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 348f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 349f2dd45e5SAndreas Jaekel rec->guid, 350f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 351f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 35235d4e8ddSAndreas Jaekel rec->file.mtime, rec->parent.mtime, 353f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 354f2dd45e5SAndreas Jaekel } 35516ff6b2fSAndreas Jaekel } 356f2dd45e5SAndreas Jaekel 357f2dd45e5SAndreas Jaekel static void 358f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf) 359f2dd45e5SAndreas Jaekel { 360f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 361f2dd45e5SAndreas Jaekel } 362f2dd45e5SAndreas Jaekel 363f2dd45e5SAndreas Jaekel static void 364f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 365f2dd45e5SAndreas Jaekel { 366f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 367f2dd45e5SAndreas Jaekel } 368f2dd45e5SAndreas Jaekel 369f2dd45e5SAndreas Jaekel static void 370f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf) 371f2dd45e5SAndreas Jaekel { 372f2dd45e5SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 373f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 374f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 375f2dd45e5SAndreas Jaekel 37616ff6b2fSAndreas Jaekel if (verbose) { 37716ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 37816ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 37912119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 38016ff6b2fSAndreas Jaekel zpf(" file.name: '%s'", ZEV_NAME(rec)); 38116ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 38212119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 38316ff6b2fSAndreas Jaekel znl(); 38416ff6b2fSAndreas Jaekel } else { 38516ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu " 38616ff6b2fSAndreas Jaekel "file.mtime=%llu name='%s'\n", 387f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 388f2dd45e5SAndreas Jaekel rec->guid, 389f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 39097dcf88dSAndreas Jaekel rec->file.mtime, 391f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 392f2dd45e5SAndreas Jaekel } 39316ff6b2fSAndreas Jaekel } 394f2dd45e5SAndreas Jaekel 395f2dd45e5SAndreas Jaekel static void 396f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf) 397f2dd45e5SAndreas Jaekel { 398f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 399f2dd45e5SAndreas Jaekel } 400f2dd45e5SAndreas Jaekel 401f2dd45e5SAndreas Jaekel static void 402f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf) 403f2dd45e5SAndreas Jaekel { 404f2dd45e5SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 405f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 406f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 407f2dd45e5SAndreas Jaekel 40816ff6b2fSAndreas Jaekel if (verbose) { 40916ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 41016ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 41112119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 41216ff6b2fSAndreas Jaekel zpf(" link.name: '%s'", ZEV_NAME(rec)); 41316ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 41412119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 41516ff6b2fSAndreas Jaekel znl(); 41616ff6b2fSAndreas Jaekel } else { 417a01b300aSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 418a01b300aSAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 419f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 420f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 421f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 422a01b300aSAndreas Jaekel rec->file.ctime, rec->parent.ctime, 423f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 42416ff6b2fSAndreas Jaekel } 425f2dd45e5SAndreas Jaekel } 426f2dd45e5SAndreas Jaekel 427f2dd45e5SAndreas Jaekel static void 428f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf) 429f2dd45e5SAndreas Jaekel { 430f2dd45e5SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 431f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 432f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 4332eabeab5SAndreas Jaekel zev_sig_t *sig; 4342eabeab5SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 435f2dd45e5SAndreas Jaekel 43616ff6b2fSAndreas Jaekel if (verbose) { 43716ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 43816ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 43912119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 44016ff6b2fSAndreas Jaekel zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 44116ff6b2fSAndreas Jaekel zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 4422eabeab5SAndreas Jaekel sig = &rec->signature; 4432eabeab5SAndreas Jaekel sig2hex_direct(sig->value, sigval); 4442eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 4452eabeab5SAndreas Jaekel sig->level, sig->block_offset, sigval); 44616ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 44712119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 44816ff6b2fSAndreas Jaekel znl(); 44916ff6b2fSAndreas Jaekel } else { 45016ff6b2fSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 45116ff6b2fSAndreas Jaekel "name='%s' link='%s'\n", 452f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 453f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 454f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 455f2dd45e5SAndreas Jaekel ZEV_NAME(rec), 456f2dd45e5SAndreas Jaekel ZEV_LINK(rec)); 457f2dd45e5SAndreas Jaekel } 45816ff6b2fSAndreas Jaekel } 459f2dd45e5SAndreas Jaekel 460f2dd45e5SAndreas Jaekel static void 461f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf) 462f2dd45e5SAndreas Jaekel { 463f2dd45e5SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 464f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 465f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 466f2dd45e5SAndreas Jaekel 46716ff6b2fSAndreas Jaekel if (verbose) { 46816ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 46916ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 47012119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 47116ff6b2fSAndreas Jaekel zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 47216ff6b2fSAndreas Jaekel zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 47316ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 47416ff6b2fSAndreas Jaekel zev_print_inode_info("srcdir", &rec->srcdir); 47516ff6b2fSAndreas Jaekel zev_print_inode_info("dstdir", &rec->dstdir); 47616ff6b2fSAndreas Jaekel znl(); 47716ff6b2fSAndreas Jaekel } else { 47816ff6b2fSAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 47916ff6b2fSAndreas Jaekel "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 48016ff6b2fSAndreas Jaekel "srcdir.mtime=%llu, srcdir.ctime=%llu, " 48116ff6b2fSAndreas Jaekel "dstdir.mtime=%llu, dstdir.ctime=%llu, " 482f2dd45e5SAndreas Jaekel "srcname='%s' dstname='%s'\n", 483f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 484f2dd45e5SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 485f2dd45e5SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 486f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 48735d4e8ddSAndreas Jaekel rec->file.mtime, rec->file.ctime, 48835d4e8ddSAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 48935d4e8ddSAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 490f2dd45e5SAndreas Jaekel ZEV_SRCNAME(rec), 491f2dd45e5SAndreas Jaekel ZEV_DSTNAME(rec)); 492f2dd45e5SAndreas Jaekel } 49316ff6b2fSAndreas Jaekel } 494f2dd45e5SAndreas Jaekel 495f2dd45e5SAndreas Jaekel static void 496f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf) 497f2dd45e5SAndreas Jaekel { 498f2dd45e5SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 499f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 500f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 501205ed6bfSAndreas Jaekel zev_sig_t *sig; 502205ed6bfSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 503205ed6bfSAndreas Jaekel int i; 504f2dd45e5SAndreas Jaekel 505205ed6bfSAndreas Jaekel if (verbose) { 50616ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 50716ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 50812119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 50916ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 51016ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 51116ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 51216ff6b2fSAndreas Jaekel znl(); 513205ed6bfSAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 514205ed6bfSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 515205ed6bfSAndreas Jaekel sig += i; 516205ed6bfSAndreas Jaekel sig2hex_direct(sig->value, sigval); 5172eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 518205ed6bfSAndreas Jaekel sig->level, sig->block_offset, sigval); 519205ed6bfSAndreas Jaekel } 52016ff6b2fSAndreas Jaekel } else { 52116ff6b2fSAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 52216ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 52316ff6b2fSAndreas Jaekel rec->file.ino, rec->file.gen, 52416ff6b2fSAndreas Jaekel rec->offset, rec->length); 525205ed6bfSAndreas Jaekel } 526f2dd45e5SAndreas Jaekel } 527f2dd45e5SAndreas Jaekel 528f2dd45e5SAndreas Jaekel static void 529f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf) 530f2dd45e5SAndreas Jaekel { 531f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 532f2dd45e5SAndreas Jaekel } 533f2dd45e5SAndreas Jaekel 534f2dd45e5SAndreas Jaekel static void 535f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf) 536f2dd45e5SAndreas Jaekel { 537f2dd45e5SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 538f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 539f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 540f2dd45e5SAndreas Jaekel 54116ff6b2fSAndreas Jaekel if (verbose) { 54216ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 54316ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 54412119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 54516ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 54616ff6b2fSAndreas Jaekel znl(); 54716ff6b2fSAndreas Jaekel } else { 54835d4e8ddSAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 549f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 55035d4e8ddSAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 551f2dd45e5SAndreas Jaekel } 55216ff6b2fSAndreas Jaekel } 553f2dd45e5SAndreas Jaekel 554f2dd45e5SAndreas Jaekel static void 555f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf) 556f2dd45e5SAndreas Jaekel { 557f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 558f2dd45e5SAndreas Jaekel } 559f2dd45e5SAndreas Jaekel 560f2dd45e5SAndreas Jaekel static void 561aafc540fSAndreas Jaekel zev_print_event(char *buf, int len) 562aafc540fSAndreas Jaekel { 563f2dd45e5SAndreas Jaekel int record_len; 564f2dd45e5SAndreas Jaekel int op; 565aafc540fSAndreas Jaekel 566f2dd45e5SAndreas Jaekel record_len = *(uint32_t *)buf; 567f2dd45e5SAndreas Jaekel if (record_len != len) { 568f2dd45e5SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 569f2dd45e5SAndreas Jaekel record_len, len); 570aafc540fSAndreas Jaekel exit(1); 571aafc540fSAndreas Jaekel } 572f2dd45e5SAndreas Jaekel op = *((uint32_t *)buf + 1); 573aafc540fSAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 574f2dd45e5SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 575aafc540fSAndreas Jaekel exit(1); 576aafc540fSAndreas Jaekel } 577f2dd45e5SAndreas Jaekel switch (op) { 578f2dd45e5SAndreas Jaekel case ZEV_OP_ERROR: 579f2dd45e5SAndreas Jaekel zev_print_error(buf); 580aafc540fSAndreas Jaekel break; 581888fea18SAndreas Jaekel case ZEV_OP_MARK: 582888fea18SAndreas Jaekel zev_print_mark(buf); 583888fea18SAndreas Jaekel break; 584f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 585f2dd45e5SAndreas Jaekel zev_print_zfs_mount(buf); 586aafc540fSAndreas Jaekel break; 587f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 588f2dd45e5SAndreas Jaekel zev_print_zfs_umount(buf); 589aafc540fSAndreas Jaekel break; 590f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 591f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 592aafc540fSAndreas Jaekel break; 593f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 594f2dd45e5SAndreas Jaekel zev_print_zvol_write(buf); 595f2dd45e5SAndreas Jaekel break; 596f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 597f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(buf); 598f2dd45e5SAndreas Jaekel break; 599f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 600f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 601f2dd45e5SAndreas Jaekel break; 602f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 603f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(buf); 604f2dd45e5SAndreas Jaekel break; 605f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 606f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 607f2dd45e5SAndreas Jaekel break; 608f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 609f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 610f2dd45e5SAndreas Jaekel break; 611f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 612f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(buf); 613f2dd45e5SAndreas Jaekel break; 614f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 615f2dd45e5SAndreas Jaekel zev_print_znode_link(buf); 616f2dd45e5SAndreas Jaekel break; 617f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 618f2dd45e5SAndreas Jaekel zev_print_znode_symlink(buf); 619f2dd45e5SAndreas Jaekel break; 620f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 621f2dd45e5SAndreas Jaekel zev_print_znode_rename(buf); 622f2dd45e5SAndreas Jaekel break; 623f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 624f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 625f2dd45e5SAndreas Jaekel break; 626f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 627f2dd45e5SAndreas Jaekel zev_print_znode_truncate(buf); 628f2dd45e5SAndreas Jaekel break; 629f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 630f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 631f2dd45e5SAndreas Jaekel break; 632f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 633f2dd45e5SAndreas Jaekel zev_print_znode_acl(buf); 634aafc540fSAndreas Jaekel break; 635aafc540fSAndreas Jaekel default: 636f2dd45e5SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 637aafc540fSAndreas Jaekel exit(1); 638aafc540fSAndreas Jaekel } 639aafc540fSAndreas Jaekel } 640aafc540fSAndreas Jaekel 641add9520fSAndreas Jaekel static int 6426a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 643a18c35b9SAndreas Jaekel { 644a18c35b9SAndreas Jaekel struct pollfd pfd[1]; 645a18c35b9SAndreas Jaekel int ret; 646aafc540fSAndreas Jaekel char buf[4096]; 647d979f56cSAndreas Jaekel zev_event_t *ev; 648d979f56cSAndreas Jaekel int off = 0; 649add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 650add9520fSAndreas Jaekel int q_fd; 651add9520fSAndreas Jaekel 6526a6a51eeSAndreas Jaekel if (create_tmp_queue) { 653add9520fSAndreas Jaekel aq.zev_max_queue_len = 0; 654add9520fSAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 655add9520fSAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 656add9520fSAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 657add9520fSAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 658add9520fSAndreas Jaekel 659add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 660add9520fSAndreas Jaekel perror("adding temporary queue failed"); 661add9520fSAndreas Jaekel return (EXIT_FAILURE); 662add9520fSAndreas Jaekel } 663add9520fSAndreas Jaekel 6646a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 6656a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 666add9520fSAndreas Jaekel q_fd = open(buf, O_RDONLY); 667add9520fSAndreas Jaekel if (q_fd < 0) { 668add9520fSAndreas Jaekel perror("opening queue device failed"); 669add9520fSAndreas Jaekel return (EXIT_FAILURE); 670add9520fSAndreas Jaekel } 6716a6a51eeSAndreas Jaekel } else { 6726a6a51eeSAndreas Jaekel q_fd = fd; 6736a6a51eeSAndreas Jaekel } 674add9520fSAndreas Jaekel 675a18c35b9SAndreas Jaekel while (1) { 676add9520fSAndreas Jaekel pfd[0].fd = q_fd; 677a18c35b9SAndreas Jaekel pfd[0].events = POLLIN; 678a18c35b9SAndreas Jaekel ret = poll(pfd, 1, 1000); 679a18c35b9SAndreas Jaekel if (ret < 0) { 680a18c35b9SAndreas Jaekel perror("poll failed"); 6816a6a51eeSAndreas Jaekel close(q_fd); 682add9520fSAndreas Jaekel return(EXIT_FAILURE); 683a18c35b9SAndreas Jaekel } 684a18c35b9SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 685a18c35b9SAndreas Jaekel continue; 686a18c35b9SAndreas Jaekel /* data available */ 687add9520fSAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 688a18c35b9SAndreas Jaekel if (ret < 0) { 689a18c35b9SAndreas Jaekel perror("read failed"); 6906a6a51eeSAndreas Jaekel close(q_fd); 691add9520fSAndreas Jaekel return(EXIT_FAILURE); 692a18c35b9SAndreas Jaekel } 693a18c35b9SAndreas Jaekel if (ret == 0) 694a18c35b9SAndreas Jaekel continue; 695d979f56cSAndreas Jaekel while (ret > off) { 696d979f56cSAndreas Jaekel ev = (zev_event_t *)(buf + off); 697d979f56cSAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 698d979f56cSAndreas Jaekel off += ev->header.record_len; 699d979f56cSAndreas Jaekel } 700149d0affSAndreas Jaekel off = 0; 701a18c35b9SAndreas Jaekel } 7026a6a51eeSAndreas Jaekel if (create_tmp_queue) 703add9520fSAndreas Jaekel close(q_fd); 704add9520fSAndreas Jaekel return EXIT_SUCCESS; 705a18c35b9SAndreas Jaekel } 706a18c35b9SAndreas Jaekel 707a18c35b9SAndreas Jaekel static void 708a18c35b9SAndreas Jaekel usage(char *progname) 709a18c35b9SAndreas Jaekel { 710add9520fSAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 711add9520fSAndreas Jaekel fprintf(stderr, "\n"); 712add9520fSAndreas Jaekel fprintf(stderr, " Status information:\n"); 713a18c35b9SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 714a18c35b9SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 715add9520fSAndreas Jaekel fprintf(stderr, " -D print zev module debug " 716add9520fSAndreas Jaekel "information\n"); 717add9520fSAndreas Jaekel fprintf(stderr, "\n"); 718add9520fSAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 719add9520fSAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 720add9520fSAndreas Jaekel "length\n"); 721add9520fSAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 722add9520fSAndreas Jaekel "this pool\n"); 723a18c35b9SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 724add9520fSAndreas Jaekel fprintf(stderr, "\n"); 725add9520fSAndreas Jaekel fprintf(stderr, " Queue management:\n"); 726add9520fSAndreas Jaekel fprintf(stderr, " -l list queues\n"); 7276a6a51eeSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 7286a6a51eeSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 729add9520fSAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 730add9520fSAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 731add9520fSAndreas Jaekel "(default)\n"); 732add9520fSAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 733add9520fSAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 7346a6a51eeSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 735add9520fSAndreas Jaekel "length\n"); 736add9520fSAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 737add9520fSAndreas Jaekel "throttle\n"); 738add9520fSAndreas Jaekel fprintf(stderr, "\n"); 739add9520fSAndreas Jaekel fprintf(stderr, " Other options:\n"); 740add9520fSAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 741add9520fSAndreas Jaekel "('%s')\n", ZEV_DEVICE); 7426a6a51eeSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 7436a6a51eeSAndreas Jaekel "queue name\n"); 744888fea18SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 74542110aacSAndreas Jaekel fprintf(stderr, " -c <filename> list file's content " 74642110aacSAndreas Jaekel "checksums\n"); 74716ff6b2fSAndreas Jaekel fprintf(stderr, " -v verbose: additional output " 748205ed6bfSAndreas Jaekel "for some operations\n"); 74916ff6b2fSAndreas Jaekel fprintf(stderr, " -g grep-friendly event output, " 75016ff6b2fSAndreas Jaekel "one event per line\n"); 751a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 752a18c35b9SAndreas Jaekel } 753a18c35b9SAndreas Jaekel 754a18c35b9SAndreas Jaekel static int 7556a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 756a18c35b9SAndreas Jaekel { 757add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 758add9520fSAndreas Jaekel int namelen; 759a18c35b9SAndreas Jaekel 760add9520fSAndreas Jaekel namelen = strlen(arg); 761add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 762add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 763a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 764a18c35b9SAndreas Jaekel } 765add9520fSAndreas Jaekel 766add9520fSAndreas Jaekel aq.zev_namelen = namelen; 767add9520fSAndreas Jaekel strcpy(aq.zev_name, arg); 7686a6a51eeSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 7696a6a51eeSAndreas Jaekel if (blocking) { 7706a6a51eeSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 7716a6a51eeSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 7726a6a51eeSAndreas Jaekel } else { 773add9520fSAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 7746a6a51eeSAndreas Jaekel } 775add9520fSAndreas Jaekel 776add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 777add9520fSAndreas Jaekel perror("adding queue failed"); 778a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 779a18c35b9SAndreas Jaekel } 780a18c35b9SAndreas Jaekel return (0); 781a18c35b9SAndreas Jaekel } 782a18c35b9SAndreas Jaekel 783a18c35b9SAndreas Jaekel static int 784add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg) 785fec460f8SAndreas Jaekel { 786add9520fSAndreas Jaekel zev_ioctl_remove_queue_t aq; 787add9520fSAndreas Jaekel int namelen; 788fec460f8SAndreas Jaekel 789add9520fSAndreas Jaekel namelen = strlen(arg); 790add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 791add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 792fec460f8SAndreas Jaekel return (EXIT_FAILURE); 793fec460f8SAndreas Jaekel } 794add9520fSAndreas Jaekel 7956a6a51eeSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 7966a6a51eeSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 797add9520fSAndreas Jaekel 798add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 799add9520fSAndreas Jaekel perror("removing queue failed"); 800add9520fSAndreas Jaekel return (EXIT_FAILURE); 801add9520fSAndreas Jaekel } 802add9520fSAndreas Jaekel return (0); 803add9520fSAndreas Jaekel } 804add9520fSAndreas Jaekel 805add9520fSAndreas Jaekel static int 806add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 807add9520fSAndreas Jaekel { 808add9520fSAndreas Jaekel uint64_t maxqueuelen; 809add9520fSAndreas Jaekel 810add9520fSAndreas Jaekel errno = 0; 811add9520fSAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 812add9520fSAndreas Jaekel if (errno) { 813add9520fSAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 814add9520fSAndreas Jaekel return (EXIT_FAILURE); 815add9520fSAndreas Jaekel } 816add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 817add9520fSAndreas Jaekel perror("setting max queue length failed"); 818fec460f8SAndreas Jaekel return (EXIT_FAILURE); 819fec460f8SAndreas Jaekel } 820fec460f8SAndreas Jaekel return (0); 821fec460f8SAndreas Jaekel } 822fec460f8SAndreas Jaekel 823fec460f8SAndreas Jaekel static int 824a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 825a18c35b9SAndreas Jaekel { 826a18c35b9SAndreas Jaekel zev_ioctl_poolarg_t pa; 827a18c35b9SAndreas Jaekel int len; 828a18c35b9SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 829a18c35b9SAndreas Jaekel len = strlen(poolname); 830a18c35b9SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 831a18c35b9SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 832a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 833a18c35b9SAndreas Jaekel } 834a18c35b9SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 835a18c35b9SAndreas Jaekel pa.zev_poolname_len = len; 836a18c35b9SAndreas Jaekel if (ioctl(fd, op, &pa)) { 837a18c35b9SAndreas Jaekel perror("muting pool data failed"); 838a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 839a18c35b9SAndreas Jaekel } 840a18c35b9SAndreas Jaekel return (0); 841a18c35b9SAndreas Jaekel } 842a18c35b9SAndreas Jaekel 843a18c35b9SAndreas Jaekel int 844a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 845a18c35b9SAndreas Jaekel { 846a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 847a18c35b9SAndreas Jaekel } 848a18c35b9SAndreas Jaekel 849a18c35b9SAndreas Jaekel int 850a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 851a18c35b9SAndreas Jaekel { 852a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 853a18c35b9SAndreas Jaekel } 854a18c35b9SAndreas Jaekel 855888fea18SAndreas Jaekel static int 856add9520fSAndreas Jaekel zev_debug_info(int fd) 857add9520fSAndreas Jaekel { 858add9520fSAndreas Jaekel zev_ioctl_debug_info_t di; 859add9520fSAndreas Jaekel 860add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 861add9520fSAndreas Jaekel perror("getting zev debug info failed"); 862add9520fSAndreas Jaekel return (EXIT_FAILURE); 863add9520fSAndreas Jaekel } 864add9520fSAndreas Jaekel 865add9520fSAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 866205ed6bfSAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 867205ed6bfSAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 868205ed6bfSAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 869add9520fSAndreas Jaekel return 0; 870add9520fSAndreas Jaekel } 871add9520fSAndreas Jaekel 872add9520fSAndreas Jaekel static int 873888fea18SAndreas Jaekel zev_mark(int fd, char *arg) 874888fea18SAndreas Jaekel { 875888fea18SAndreas Jaekel zev_ioctl_mark_t *mark; 876888fea18SAndreas Jaekel uint64_t guid; 877888fea18SAndreas Jaekel int len; 878888fea18SAndreas Jaekel char *p; 879888fea18SAndreas Jaekel 880888fea18SAndreas Jaekel p = strchr(arg, ':'); 881888fea18SAndreas Jaekel if (!p) { 882888fea18SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 883888fea18SAndreas Jaekel "e.g. '123:hello'\n"); 884888fea18SAndreas Jaekel exit (EXIT_FAILURE); 885888fea18SAndreas Jaekel } 886888fea18SAndreas Jaekel *p = '\n'; 887888fea18SAndreas Jaekel p++; 888888fea18SAndreas Jaekel 889888fea18SAndreas Jaekel errno = 0; 890add9520fSAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 891888fea18SAndreas Jaekel if (errno) { 892888fea18SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 893888fea18SAndreas Jaekel exit (EXIT_FAILURE); 894888fea18SAndreas Jaekel } 895888fea18SAndreas Jaekel 896888fea18SAndreas Jaekel len = strlen(p); 897888fea18SAndreas Jaekel 898888fea18SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 899888fea18SAndreas Jaekel if (!mark) { 900888fea18SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 901888fea18SAndreas Jaekel strerror(errno)); 902888fea18SAndreas Jaekel exit (EXIT_FAILURE); 903888fea18SAndreas Jaekel } 904888fea18SAndreas Jaekel mark->zev_guid = guid; 905888fea18SAndreas Jaekel mark->zev_mark_id = 0; 906888fea18SAndreas Jaekel mark->zev_payload_len = len; 907888fea18SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 908888fea18SAndreas Jaekel 909888fea18SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 910888fea18SAndreas Jaekel perror("queueing mark failed"); 911888fea18SAndreas Jaekel return (EXIT_FAILURE); 912888fea18SAndreas Jaekel } 913888fea18SAndreas Jaekel 914888fea18SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 915888fea18SAndreas Jaekel return (0); 916888fea18SAndreas Jaekel } 917888fea18SAndreas Jaekel 918add9520fSAndreas Jaekel static int 919add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 920add9520fSAndreas Jaekel { 921add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 922add9520fSAndreas Jaekel 9236a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9246a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 925add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 926add9520fSAndreas Jaekel return EXIT_FAILURE; 927add9520fSAndreas Jaekel } 9286a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 929add9520fSAndreas Jaekel 930add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 931add9520fSAndreas Jaekel perror("getting queue properties failed"); 932add9520fSAndreas Jaekel return (EXIT_FAILURE); 933add9520fSAndreas Jaekel } 934add9520fSAndreas Jaekel if (block) { 935add9520fSAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 936add9520fSAndreas Jaekel } else { 937add9520fSAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 938add9520fSAndreas Jaekel } 939add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 940add9520fSAndreas Jaekel perror("setting queue properties failed"); 941add9520fSAndreas Jaekel return (EXIT_FAILURE); 942add9520fSAndreas Jaekel } 943add9520fSAndreas Jaekel return (0); 944add9520fSAndreas Jaekel } 945add9520fSAndreas Jaekel 946add9520fSAndreas Jaekel static int 947add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 948add9520fSAndreas Jaekel { 949add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 950add9520fSAndreas Jaekel 951add9520fSAndreas Jaekel if (!len) { 952add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 953add9520fSAndreas Jaekel return EXIT_FAILURE; 954add9520fSAndreas Jaekel } 955add9520fSAndreas Jaekel 9566a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9576a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 958add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 959add9520fSAndreas Jaekel return EXIT_FAILURE; 960add9520fSAndreas Jaekel } 9616a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 962add9520fSAndreas Jaekel 963add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 964add9520fSAndreas Jaekel perror("getting queue properties failed"); 965add9520fSAndreas Jaekel return (EXIT_FAILURE); 966add9520fSAndreas Jaekel } 967add9520fSAndreas Jaekel gqp.zev_max_queue_len = atol(len); 968add9520fSAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 969add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 970add9520fSAndreas Jaekel return (EXIT_FAILURE); 971add9520fSAndreas Jaekel } 972add9520fSAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 973add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 974add9520fSAndreas Jaekel return (EXIT_FAILURE); 975add9520fSAndreas Jaekel } 976add9520fSAndreas Jaekel 977add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 978add9520fSAndreas Jaekel perror("setting queue properties failed"); 979add9520fSAndreas Jaekel return (EXIT_FAILURE); 980add9520fSAndreas Jaekel } 981add9520fSAndreas Jaekel return (0); 982add9520fSAndreas Jaekel } 983add9520fSAndreas Jaekel 984add9520fSAndreas Jaekel static int 985add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 986add9520fSAndreas Jaekel { 987add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 988add9520fSAndreas Jaekel 989add9520fSAndreas Jaekel if (!len) { 990add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 991add9520fSAndreas Jaekel return EXIT_FAILURE; 992add9520fSAndreas Jaekel } 993add9520fSAndreas Jaekel 9946a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9956a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 996add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 997add9520fSAndreas Jaekel return EXIT_FAILURE; 998add9520fSAndreas Jaekel } 9996a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 1000add9520fSAndreas Jaekel 1001add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1002add9520fSAndreas Jaekel perror("getting queue properties failed"); 1003add9520fSAndreas Jaekel return (EXIT_FAILURE); 1004add9520fSAndreas Jaekel } 1005add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 1006add9520fSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 1007add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 1008add9520fSAndreas Jaekel return (EXIT_FAILURE); 1009add9520fSAndreas Jaekel } 10106a6a51eeSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 1011add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 1012add9520fSAndreas Jaekel return (EXIT_FAILURE); 1013add9520fSAndreas Jaekel } 1014add9520fSAndreas Jaekel 1015add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 1016add9520fSAndreas Jaekel perror("setting queue properties failed"); 1017add9520fSAndreas Jaekel return (EXIT_FAILURE); 1018add9520fSAndreas Jaekel } 1019add9520fSAndreas Jaekel return (0); 1020add9520fSAndreas Jaekel } 1021add9520fSAndreas Jaekel 1022add9520fSAndreas Jaekel static int 1023add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg) 1024add9520fSAndreas Jaekel { 1025add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1026add9520fSAndreas Jaekel 10276a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 10286a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1029add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 1030add9520fSAndreas Jaekel return EXIT_FAILURE; 1031add9520fSAndreas Jaekel } 10326a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 1033add9520fSAndreas Jaekel 1034add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1035add9520fSAndreas Jaekel perror("getting queue properties failed"); 1036add9520fSAndreas Jaekel return (EXIT_FAILURE); 1037add9520fSAndreas Jaekel } 1038add9520fSAndreas Jaekel 1039add9520fSAndreas Jaekel printf("queue : %s\n", arg); 1040add9520fSAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1041add9520fSAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1042add9520fSAndreas Jaekel printf("persistent : %s\n", 1043add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1044add9520fSAndreas Jaekel printf("blocking : %s\n", 1045add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1046add9520fSAndreas Jaekel 1047add9520fSAndreas Jaekel return (0); 1048add9520fSAndreas Jaekel } 1049add9520fSAndreas Jaekel 1050add9520fSAndreas Jaekel static int 1051add9520fSAndreas Jaekel zev_list_queues(int fd) 1052add9520fSAndreas Jaekel { 1053add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1054add9520fSAndreas Jaekel zev_ioctl_get_queue_list_t gql; 1055add9520fSAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 1056add9520fSAndreas Jaekel uint64_t i; 1057add9520fSAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1058add9520fSAndreas Jaekel 1059add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1060add9520fSAndreas Jaekel perror("getting queue list failed"); 1061add9520fSAndreas Jaekel return (EXIT_FAILURE); 1062add9520fSAndreas Jaekel } 1063add9520fSAndreas Jaekel 1064add9520fSAndreas Jaekel printf("Name Size " 1065add9520fSAndreas Jaekel "Max Size Wakeup Per Block\n"); 1066add9520fSAndreas Jaekel 1067add9520fSAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 1068add9520fSAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 1069add9520fSAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 1070add9520fSAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1071add9520fSAndreas Jaekel 10726a6a51eeSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 10736a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10746a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 10756a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1076add9520fSAndreas Jaekel 1077add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1078add9520fSAndreas Jaekel if (errno == ENOENT) 1079add9520fSAndreas Jaekel continue; 1080add9520fSAndreas Jaekel perror("getting queue properties failed"); 1081add9520fSAndreas Jaekel return (EXIT_FAILURE); 1082add9520fSAndreas Jaekel } 1083add9520fSAndreas Jaekel 10846a6a51eeSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 10856a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10866a6a51eeSAndreas Jaekel gs.zev_queue_name.zev_namelen = 10876a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1088add9520fSAndreas Jaekel 1089add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1090add9520fSAndreas Jaekel if (errno == ENOENT) 1091add9520fSAndreas Jaekel continue; 1092add9520fSAndreas Jaekel perror("getting statistics data failed"); 1093add9520fSAndreas Jaekel return (EXIT_FAILURE); 1094add9520fSAndreas Jaekel } 1095add9520fSAndreas Jaekel 1096add9520fSAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1097add9520fSAndreas Jaekel " %-3s %-3s\n", 1098add9520fSAndreas Jaekel name, 1099add9520fSAndreas Jaekel gs.zev_statistics.zev_queue_len, 1100add9520fSAndreas Jaekel gqp.zev_max_queue_len, 1101add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold, 1102add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1103add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1104add9520fSAndreas Jaekel "yes" : "no"); 1105add9520fSAndreas Jaekel } 1106add9520fSAndreas Jaekel 1107add9520fSAndreas Jaekel return (0); 1108add9520fSAndreas Jaekel } 1109add9520fSAndreas Jaekel 111042110aacSAndreas Jaekel static int 111142110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename) 111242110aacSAndreas Jaekel { 111342110aacSAndreas Jaekel int fd; 111442110aacSAndreas Jaekel offset_t off; 111542110aacSAndreas Jaekel offset_t data; 111642110aacSAndreas Jaekel zev_sig_t *sig; 111742110aacSAndreas Jaekel char *buf; 111842110aacSAndreas Jaekel zev_ioctl_get_signatures_t *gs; 111942110aacSAndreas Jaekel int i; 112042110aacSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 112142110aacSAndreas Jaekel int buf_size; 112242110aacSAndreas Jaekel 112342110aacSAndreas Jaekel /* control struct, one lv1 signature and up to 256 lv0 signatures */ 112442110aacSAndreas Jaekel buf_size = (1 + 256) * sizeof(zev_sig_t); 112542110aacSAndreas Jaekel buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 112642110aacSAndreas Jaekel if (!buf) { 112742110aacSAndreas Jaekel perror("can't allocate checksum buffer"); 112842110aacSAndreas Jaekel return (EXIT_FAILURE); 112942110aacSAndreas Jaekel } 113042110aacSAndreas Jaekel 113142110aacSAndreas Jaekel fd = open(filename, O_RDONLY); 113242110aacSAndreas Jaekel if (fd < 0) { 113342110aacSAndreas Jaekel perror("can't open file"); 113442110aacSAndreas Jaekel return (EXIT_FAILURE); 113542110aacSAndreas Jaekel } 113642110aacSAndreas Jaekel 113742110aacSAndreas Jaekel gs = (zev_ioctl_get_signatures_t *)buf; 113842110aacSAndreas Jaekel gs->zev_fd = fd; 113942110aacSAndreas Jaekel gs->zev_bufsize = buf_size; 114042110aacSAndreas Jaekel 114142110aacSAndreas Jaekel off = 0; 114242110aacSAndreas Jaekel data = 0; 114342110aacSAndreas Jaekel while (1) { 114442110aacSAndreas Jaekel errno = 0; 114542110aacSAndreas Jaekel data = llseek(fd, off, SEEK_DATA); 114642110aacSAndreas Jaekel if (data < 0) { 114742110aacSAndreas Jaekel if (errno == ENXIO) /* no more data */ 114842110aacSAndreas Jaekel break; 114942110aacSAndreas Jaekel perror("llseek failed"); 115042110aacSAndreas Jaekel goto err; 115142110aacSAndreas Jaekel } 115242110aacSAndreas Jaekel data = P2ALIGN(data, ZEV_L1_SIZE); 115342110aacSAndreas Jaekel off = data + ZEV_L1_SIZE; 115442110aacSAndreas Jaekel 115542110aacSAndreas Jaekel gs->zev_offset = data; 115642110aacSAndreas Jaekel gs->zev_len = ZEV_L1_SIZE; 115742110aacSAndreas Jaekel 115842110aacSAndreas Jaekel if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 115942110aacSAndreas Jaekel perror("ioctl to get signatures failed"); 116042110aacSAndreas Jaekel goto err; 116142110aacSAndreas Jaekel } 116242110aacSAndreas Jaekel 116342110aacSAndreas Jaekel for (i=0; i<gs->zev_signature_cnt; i++) { 116442110aacSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 116542110aacSAndreas Jaekel sig += i; 116642110aacSAndreas Jaekel sig2hex_direct(sig->value, sigval); 116742110aacSAndreas Jaekel printf("level %d, offset %llu, value %s\n", 116842110aacSAndreas Jaekel sig->level, sig->block_offset, sigval); 116942110aacSAndreas Jaekel } 117042110aacSAndreas Jaekel } 117142110aacSAndreas Jaekel 117242110aacSAndreas Jaekel free(buf); 117342110aacSAndreas Jaekel close(fd); 117442110aacSAndreas Jaekel return 0; 117542110aacSAndreas Jaekel err: 117642110aacSAndreas Jaekel free(buf); 117742110aacSAndreas Jaekel close(fd); 117842110aacSAndreas Jaekel return (EXIT_FAILURE); 117942110aacSAndreas Jaekel } 118042110aacSAndreas Jaekel 1181a18c35b9SAndreas Jaekel int 1182a18c35b9SAndreas Jaekel main(int argc, char **argv) 1183a18c35b9SAndreas Jaekel { 1184a18c35b9SAndreas Jaekel int fd; 1185a18c35b9SAndreas Jaekel int c; 1186a18c35b9SAndreas Jaekel extern char *optarg; 11876a6a51eeSAndreas Jaekel int create_tmp_queue = 1; 11886a6a51eeSAndreas Jaekel char buf[MAXPATHLEN]; 1189*a5090b97SAndreas Jaekel int mode = 0; 1190*a5090b97SAndreas Jaekel char *arg = NULL; 1191*a5090b97SAndreas Jaekel char *arg2 = NULL; 1192a18c35b9SAndreas Jaekel 1193a18c35b9SAndreas Jaekel /* open device */ 1194a18c35b9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1195a18c35b9SAndreas Jaekel if (fd < 0) { 1196a18c35b9SAndreas Jaekel perror("opening zev device failed"); 1197a18c35b9SAndreas Jaekel return EXIT_FAILURE; 1198a18c35b9SAndreas Jaekel } 11996a6a51eeSAndreas Jaekel while ((c = getopt(argc, argv, 120016ff6b2fSAndreas Jaekel "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 1201a18c35b9SAndreas Jaekel switch(c) { 120216ff6b2fSAndreas Jaekel case 'g': 120316ff6b2fSAndreas Jaekel grep_friendly++; 120416ff6b2fSAndreas Jaekel verbose++; 120516ff6b2fSAndreas Jaekel break; 1206205ed6bfSAndreas Jaekel case 'v': 1207205ed6bfSAndreas Jaekel verbose++; 1208205ed6bfSAndreas Jaekel break; 1209a18c35b9SAndreas Jaekel case 's': 1210*a5090b97SAndreas Jaekel mode = MD_STATISTICS; 1211*a5090b97SAndreas Jaekel break; 1212a18c35b9SAndreas Jaekel case 'p': 1213*a5090b97SAndreas Jaekel mode = MD_POLL_EVENTS; 1214*a5090b97SAndreas Jaekel break; 121542110aacSAndreas Jaekel case 'c': 1216*a5090b97SAndreas Jaekel mode = MD_CHECKSUMS; 1217*a5090b97SAndreas Jaekel arg = optarg; 1218*a5090b97SAndreas Jaekel break; 1219add9520fSAndreas Jaekel case 'D': 1220*a5090b97SAndreas Jaekel mode = MD_DEBUG_INFO; 1221*a5090b97SAndreas Jaekel break; 1222a18c35b9SAndreas Jaekel case 'd': 1223add9520fSAndreas Jaekel close(fd); 1224a18c35b9SAndreas Jaekel zev_device = optarg; 1225add9520fSAndreas Jaekel fd = open(zev_device, O_RDONLY); 1226add9520fSAndreas Jaekel if (fd < 0) { 1227add9520fSAndreas Jaekel perror("opening zev device failed"); 1228add9520fSAndreas Jaekel return EXIT_FAILURE; 1229add9520fSAndreas Jaekel } 12306a6a51eeSAndreas Jaekel create_tmp_queue = 0; 12316a6a51eeSAndreas Jaekel break; 12326a6a51eeSAndreas Jaekel case 'q': 12336a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 12346a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 12356a6a51eeSAndreas Jaekel close(fd); 12366a6a51eeSAndreas Jaekel zev_device = buf; 12376a6a51eeSAndreas Jaekel fd = open(zev_device, O_RDONLY); 12386a6a51eeSAndreas Jaekel if (fd < 0) { 12396a6a51eeSAndreas Jaekel perror("opening zev device failed"); 12406a6a51eeSAndreas Jaekel return EXIT_FAILURE; 12416a6a51eeSAndreas Jaekel } 12426a6a51eeSAndreas Jaekel create_tmp_queue = 0; 1243a18c35b9SAndreas Jaekel break; 1244add9520fSAndreas Jaekel case 'l': 1245*a5090b97SAndreas Jaekel mode = MD_LIST_QUEUES; 1246*a5090b97SAndreas Jaekel break; 1247add9520fSAndreas Jaekel case 'Q': 1248*a5090b97SAndreas Jaekel mode = MD_SET_GLOBAL_MAX_QUEUE_LEN; 1249*a5090b97SAndreas Jaekel arg = optarg; 1250*a5090b97SAndreas Jaekel break; 12516a6a51eeSAndreas Jaekel case 'L': 1252*a5090b97SAndreas Jaekel mode = MD_SET_MAX_QUEUE_LEN; 1253*a5090b97SAndreas Jaekel arg = optarg; 1254*a5090b97SAndreas Jaekel arg2 = argv[optind]; 1255*a5090b97SAndreas Jaekel break; 1256fec460f8SAndreas Jaekel case 't': 1257*a5090b97SAndreas Jaekel mode = MD_SET_POLL_WAKEUP_QUEUE_LEN; 1258*a5090b97SAndreas Jaekel arg = optarg; 1259*a5090b97SAndreas Jaekel arg2 = argv[optind]; 1260*a5090b97SAndreas Jaekel break; 1261a18c35b9SAndreas Jaekel case 'm': 1262*a5090b97SAndreas Jaekel mode = MD_MUTE_POOL; 1263*a5090b97SAndreas Jaekel arg = optarg; 1264*a5090b97SAndreas Jaekel break; 1265a18c35b9SAndreas Jaekel case 'M': 1266*a5090b97SAndreas Jaekel mode = MD_UNMUTE_POOL; 1267*a5090b97SAndreas Jaekel arg = optarg; 1268*a5090b97SAndreas Jaekel break; 1269888fea18SAndreas Jaekel case 'k': 1270*a5090b97SAndreas Jaekel mode = MD_MARK; 1271*a5090b97SAndreas Jaekel arg = optarg; 1272*a5090b97SAndreas Jaekel break; 1273add9520fSAndreas Jaekel case 'a': 1274*a5090b97SAndreas Jaekel mode = MD_ADD_QUEUE; 1275*a5090b97SAndreas Jaekel arg = optarg; 1276*a5090b97SAndreas Jaekel break; 12776a6a51eeSAndreas Jaekel case 'A': 1278*a5090b97SAndreas Jaekel mode = MD_ADD_BLOCKING_QUEUE; 1279*a5090b97SAndreas Jaekel arg = optarg; 1280*a5090b97SAndreas Jaekel break; 1281add9520fSAndreas Jaekel case 'r': 1282*a5090b97SAndreas Jaekel mode = MD_REMOVE_QUEUE; 1283*a5090b97SAndreas Jaekel arg = optarg; 1284*a5090b97SAndreas Jaekel break; 1285add9520fSAndreas Jaekel case 'b': 1286*a5090b97SAndreas Jaekel mode = MD_QUEUE_BLOCKING; 1287*a5090b97SAndreas Jaekel arg = optarg; 1288*a5090b97SAndreas Jaekel break; 1289add9520fSAndreas Jaekel case 'B': 1290*a5090b97SAndreas Jaekel mode = MD_QUEUE_NONBLOCKING; 1291*a5090b97SAndreas Jaekel arg = optarg; 1292*a5090b97SAndreas Jaekel break; 1293add9520fSAndreas Jaekel case 'P': 1294*a5090b97SAndreas Jaekel mode = MD_QUEUE_PROPERTIES; 1295*a5090b97SAndreas Jaekel arg = optarg; 1296*a5090b97SAndreas Jaekel break; 1297a18c35b9SAndreas Jaekel case 'h': 1298a18c35b9SAndreas Jaekel case '?': 1299a18c35b9SAndreas Jaekel default: 1300a18c35b9SAndreas Jaekel usage(argv[0]); 1301a18c35b9SAndreas Jaekel } 1302a18c35b9SAndreas Jaekel } 1303*a5090b97SAndreas Jaekel 1304*a5090b97SAndreas Jaekel switch (mode) { 1305*a5090b97SAndreas Jaekel case MD_STATISTICS: 1306*a5090b97SAndreas Jaekel return zev_statistics(fd); 1307*a5090b97SAndreas Jaekel case MD_POLL_EVENTS: 1308*a5090b97SAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 1309*a5090b97SAndreas Jaekel case MD_CHECKSUMS: 1310*a5090b97SAndreas Jaekel return zev_checksum(fd, arg); 1311*a5090b97SAndreas Jaekel case MD_DEBUG_INFO: 1312*a5090b97SAndreas Jaekel return zev_debug_info(fd); 1313*a5090b97SAndreas Jaekel case MD_LIST_QUEUES: 1314*a5090b97SAndreas Jaekel return zev_list_queues(fd); 1315*a5090b97SAndreas Jaekel case MD_SET_GLOBAL_MAX_QUEUE_LEN: 1316*a5090b97SAndreas Jaekel return zev_set_global_max_queue_len(fd, arg); 1317*a5090b97SAndreas Jaekel case MD_SET_MAX_QUEUE_LEN: 1318*a5090b97SAndreas Jaekel return zev_set_max_queue_len(fd, arg, arg2); 1319*a5090b97SAndreas Jaekel case MD_SET_POLL_WAKEUP_QUEUE_LEN: 1320*a5090b97SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, arg, arg2); 1321*a5090b97SAndreas Jaekel case MD_MUTE_POOL: 1322*a5090b97SAndreas Jaekel return zev_mute_pool(fd, arg); 1323*a5090b97SAndreas Jaekel case MD_UNMUTE_POOL: 1324*a5090b97SAndreas Jaekel return zev_unmute_pool(fd, arg); 1325*a5090b97SAndreas Jaekel case MD_MARK: 1326*a5090b97SAndreas Jaekel return zev_mark(fd, arg); 1327*a5090b97SAndreas Jaekel case MD_ADD_QUEUE: 1328*a5090b97SAndreas Jaekel return zev_add_queue(fd, arg, 0); 1329*a5090b97SAndreas Jaekel case MD_ADD_BLOCKING_QUEUE: 1330*a5090b97SAndreas Jaekel return zev_add_queue(fd, arg, 1); 1331*a5090b97SAndreas Jaekel case MD_REMOVE_QUEUE: 1332*a5090b97SAndreas Jaekel return zev_remove_queue(fd, arg); 1333*a5090b97SAndreas Jaekel case MD_QUEUE_BLOCKING: 1334*a5090b97SAndreas Jaekel return zev_queue_blocking(fd, arg, 0); 1335*a5090b97SAndreas Jaekel case MD_QUEUE_NONBLOCKING: 1336*a5090b97SAndreas Jaekel return zev_queue_blocking(fd, arg, 1); 1337*a5090b97SAndreas Jaekel case MD_QUEUE_PROPERTIES: 1338*a5090b97SAndreas Jaekel return zev_queue_properties(fd, arg); 1339*a5090b97SAndreas Jaekel default: 1340a18c35b9SAndreas Jaekel close(fd); 1341*a5090b97SAndreas Jaekel usage(argv[0]); 1342add9520fSAndreas Jaekel return EXIT_FAILURE; 1343*a5090b97SAndreas Jaekel }; 1344a18c35b9SAndreas Jaekel } 1345a18c35b9SAndreas Jaekel 1346